Points: 150 Solves: 30 Category: Exploitation Description: nc 126.96.36.199 1970
If we start the binary we see it’s a form of note keeping application.
Leaking the heap address
If we disassemble the “Input your name/Org/Host” functions, we will notice the first vulnerability.
Top arrow points to the local buffer of 0x40 bytes for the name. Exactly 0x40 bytes after it, we see a space designed to store a pointer to a heap allocated chunk for permanent store of the name. Later, we see that the name is copied from the local stack buffer to the allocated heap buffer. However, as we know strcpy terminates on null byte and if we fill the name with exactly 0x40 bytes, the ptr to the heap buffer will get copied on to the heap as well. Right after that the printWelcome() function will print the heap buffer, providing us with a leak of the heap address.
Now let’s look at the way Org and Host are provided.
As you have probably figured out, we have the same bug here as well. The pointer for the Host’s heap buffer is stored right between the local buffers of the Org and Host on the stack. By filling 0x40 bytes in the Host’s local buffer we can cause strcpy to overwrite the Wilderness’s chunk metadata on the heap.
House of Force
Knowing that we control the Wilderness’s metadata, we can use exploitation technique called House of Force. The way this technique works is by corrupting the size of the wilderness to some huge value and having a function that allows us to specify the size of heap allocated buffer. This way we can make malloc allocate a buffer that will eventually wrap around the address space available on 32bit system and reach the area we want to write data to (as we will see later, this would be a .bss address in this case). Once malloc has allocated a chunk so big that the end of it will reach the area we are going to write to, we need to call malloc again so we get a smaller chunk, right on top of our write target.
Fortunately we have a function that satisfies this malloc(controlled_size) condition.
So far we have only looked at the binary’s welcome message and what we can gain/exploit via the Name/Org/Host buffers. Here we will see how we can use the binary’s functionality to leverage these vulnerabilities.
After the printWelcome() function, we have a regular case/switch statement with 7 options.
Show note, Syn and Quit are not important or just useless in our case. We are left with New note, Edit note and Delete note.
As you can tell, newNote() uses malloc() with size that we control. It also stores the pointer to the allocated buffer in an integer array of 10 elements on the .bss - 0x804b120. It also stores the length of each buffer in another integer array of 10 elements on the .bss - 0x804b0a0.
The editNote() function let’s us edit the content of previously created note by requesting an index from the notes array. The length of the input data is taken from the lengths array from the same index as the notes on the .bss.
The deleteNote() function uses free(notes[index]) and zeros the lengths[index] element only if the notes[index] contain an element.
So far we have a leak of a ptr on the heap. We have an overflow to control the wilderness’s size and we have a way to allocate huge chunks. You might be thinking, “Cool, we are just going to overwrite the GOT and we are done.”. Yes, but let’s not forget that ASLR is enabled and we only have an address of the heap.
So to exploit this,
- I’m going to use House of Force to allocate a heap chunk that reaches the notes array on the .bss.
- Allocate another chunk that stretches from the beginning of the lengths array at 0x804b0a0 to the end of the notes array @ 0x804b120 on the .BSS. This way we can control everything in those 2 arrays (and something in between that we don’t care about).
Once we get control of the notes and lengths we can simply use editNote() to write to the addresses we fill notes array with.
We do get a lot of writes what/where this way, but we still haven’t leaked a libc address. To do that I’m going to overwrite the free@got with printf@got, this way we can use the deleteNote() function using printf with controlled argument and leak whatever/whereever. So, 4. Replace free@got with printf@got.
- Leak the atoi@got.
- Replace atoi with system.
One function we haven’t looked at is the getChoice() function. This function is used pretty much everywhere, including the main menu for the switch/case statement.
As you can see, atoi() here is pretty handy for exchanging with system().