i486
x86 32bit version of the heap-zero exercise.
Now we understand how the program works after reading the source code it might be a good ideia to also take a look into the assembly code.
Let's open the program in gdb and run it with a regular argument, just to start our dynamic analysis.
(gdb) set args AAAA
(gdb) r
The program makes it easier by telling us where our input is and where fp is, so we could easily calculate our offset and complete the challenge without even using a debugger, but we'll take the long way in order to get the most out of this exercise.
Let's disassemble the main function:
We can see the calls to malloc() and strcpy() that were mentioned previously. Let's set breakpoints at those to see how the heap looks like throughout execution. I'll set a breakpoint after the last malloc to see the layout of the heap, another one when the pointer to the nowinner function (fp) is stored and finally another one after our input is copied to the heap. So we want to break in the line after each of the following instructions:
The address that follow each of these are, respectively, 0x080488c4, 0x080488d3 and 0x080488e8
Now let's run the program to further investigate.
We can find the heap at 0xf7e69000, now let's analyse it. x/64wx will print 64 words (1 word = 4 bytes).
Reading the chunk headers we can see there are 2 chunks of 48 bytes total (one for each malloc), and we add 1 byte (previous-in-use flag) to the size metadata to indicate that the previous chunk is in use, so that's why both chunks have 49 as the size.
This is the size of the rest of the heap apart from this 2 chunks that were already allocated, this is also known as the top chunk or wilderness.
After continuing the execution we can see exactly where fp (the pointer we want to overwrite) is,
And if we continue again we can find our input:
We start writing at 0xf7e69008, and we want to reach 0xf7e69050 with junk, so our junk size will be 72 bytes, and the next for bytes are the value we want to write, which is the address of the winner function.
So we just need to provide an argument with 72 meaningless bytes + address of winner. Here is the expected heap layout:
The following python code will do the job:
And we win :)
Last updated
Was this helpful?