In this level , we don’t have a function pointer on the stack (at least not in the traditional sense, I guess), but we’re still tasked with calling the win function. Our first step is to find the address of win, and using objdump like we did in the last level, we find that it’s 080483f4
. Now we know our payload, the next step is to find the target.
Looking through the code, there’s not much to it. It makes a call to gets and then immediately exits. If we disassemble the main function, we see the only real chance we have of altering executing is to take advance of the ret
instruction. Ret will pop an address off the stack and the jump to it, so if we’re able to overwrite that address, we can jump to the win function and complete the challenge.
We know that buffer is the only local variable on the stack, and it’s 64 bytes. However, we need to figure out how far beyond those 64 bytes we need to write in order to get to the return address. I set a breakpoint inside main, just before the call to gets. After that I printed out the value of EBP, 0xBFFFF808, which should be pointing to the base of the stack. I stepped through the next few instructions and input a very long string of the character “A” when gets was called. After returning from that function, I examined the stack and noted the address where the 0x41 (ascii code for the A character) started, which appeared to be at 0xBFFFF7C0. Based on that, we need to overwrite the next word of memory that’s just beyond EBP, which is the address that the ret command is going to jump to. 0xBFFFF808 - 0xBFFFF7C0 appears to be 72 bytes. The base of the stack should be pointing at the old EBP value, so we need to overwrite those four bytes as well, making the total amount of bytes 76 (I think? My visualization of the stack may be a bit shaky here).
Testing out our theory, we appear to succeed, although we don’t exit cleanly. The important thing is that we were able to call the win function though.