This challenge serves as the introduction into heap exploitation and as such isn’t too bad. In fact, we’ll exploit this in a manner very similar to classic stack based overflow.
For starters, I just examined the output of the program. Once I observed the information they gave me, the location of data and fp, it became clear what I had to do. There is a buffer overflow in the strcpy in line 36. Directly after that buffer overflow is a call to a function pointer contained in the struct fp. We can leverage the buffer overflow to overwrite the function pointer for nowinner and replace it with winner.
While the program gives you the locations of name and fp, I like to assume I won’t get those. Assuming the program didn’t print them for us we can obtain them without much difficulty by observing the disassembly.
We can see that directly before the strcpy at location 0x080484f2 two arguments are pushed on the stack. Since we are using stdcall here the arguments are pushed from right to left. Therefore the name variable is the second. I went ahead and placed a breakpoint on the strcpy function and ran the program with some dummy input.
In this scenario, I know the eax register has the address that our input will be written to. I checked the address calculated and placed into eax before strcpy and then checked that address after strcpy. The results are below:
I now know that our string is stored at 0x0804a008.
Next I placed a breakpoint on 0x080484f7. At this location I assume that [$esp] holds the value of f and that fp() must be at offset 0x1c. I step once and check the value of eax.
I now know the value of f to be 0x0804a050. I also know that whatever is at that location will be loaded and called. Therefore this is the location I need to overwrite.
First I need to calculate the difference between the two addresses. 0x0804a50-0x0804a008 = 72. After 72 bytes I will start overwriting address 0x0804a50 (remember we write from low addresses towards the high). I confirm this with a quick test:
Now all that remains is to put the location of winner into the address. You can just run p winner to get the address of the winner function which is at 0x08048464.
And there you have it.