[Pwnable.kr] bof writeup – Toddler’s bottle

You probably guessed what this level is about : we will try to trigger a buffer overflow (bof) in order to smash the stack and overwrite something; a return address, a variable, a pointer or something !

The link of the source code is provided to us, let’s check it out :

After a quick scan of the code, in the function func() , the program is expecting the variable key  to contain the value 0xcafebabe , but the we don’t have much control over the variable key  through i/o, since the value is already hard coded in the function call in main() , to the value 0xdeadbeef .

How are we going to do that ? Well the writers of the challenge were nice enough to write down a little hint in the comment : we gotta smash the variable overflowme . We have to trigger a buffer overflow so we can overwrite the value of the variable key  with 0xcafebabe .

Before I got ahead and try to do that, I’d like to review first the calling convention for x86 linux. So, we all know that, when calling a function, there are some things that get done to the stack before executing the body of the function. First, the parameters of the function are pushed into the stack, from the last one to the first one, and then the old stack base pointer (EBP) is pushed, then the return address to the caller is saved above the EBP, after that, EBP gets the old value of ESP. Then to allocate some space for the new stack frame, we subtract a number of bytes from ESP (because the stack grows from higher addresses to lower addresses). Finally, the local static variables of the callee are allocated in the new stack frame.

Sidenote : the parameters will have a positive index from EBP, and local variable will have negative indexes.

We can sum up all those operations in the following diagram:

Calling convention - stack frame

Now onto our challenge, let’s fire up GDB, analyze the asm code, and try to imagine how would the stack look like.

Below is the result of the command disas on func()  :

From the last diagram we drew, we can guess that 0xdeadbeef  would be placed in EBP+8, since it’s the only parameter passed to the function func() , and this hypothesis can be confirmed by looking at the line marked with the number (1); the value 0xcafebabe , is indeed compared with EBP+8, which is the adresse of the variable key .

Let’s check the effective address of the variable key :

Now we have the address where 0xdeadbeef  is stored. The next thing we need to do, is to now the exact offset between 0xdeadbeef , and where and the variable overflowme , in which the function gets() stores our input.

We know that the function  gets() , takes the address of a buffer as a parameter, and it expects that address in the register EAX. Now, let’s look at the line marked with the number (2), we can see that the program loads the effective address EBP-0x2c into EAX, right before calling gets() ; now this only lets me think that the variable overflowme  is stored in EBP-0x2c. Let’s look at the stack to make sure of that.

First we set up a break point at the function gets() , and then we run the program:

Let’s step outside of gets()  so we can provide our input :

Now we look into the address EBP-0x2c to see what it contains:

We guessed right, it does contain our input, which means it is indeed the address of the variable overflowme .

Here are the addresses we got so far :

Let’s calculate the offset between the two addresses :

So the two values are 52 bytes apart. Just for fun, let’s draw a little diagram:

Calling convention - stack frame

So, finally, to exploit this, we need to smash the variable overflowme  by feeding it 52 bytes of junk, that should be sufficient to reach the address of key , and then concatenate it with the value 0xcafebabe  to overwrite the value 0xdeadbeef . That way, when the program wants to compare key with 0xcafababe , it’ll find it already overwritten with that value, and it’ll just give us the shell.

So the payload we need to send is something like this (don’t forget that the system is little Endian):

Let’s try it on the remote server of the challenge :

And voilà, we caught the flag 🙂

One thought on “[Pwnable.kr] bof writeup – Toddler’s bottle

Leave a Reply

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

* Copy This Password *

* Type Or Paste Password Here *