Similar with Pwn200, Pwn400 gave us a binary file, but no libc.so. Open it with IDA Pro and analyze it, we found some information:
First, there's a data structure ( let's call it node ) which look like this:
In this program, we're allow to:
1. New a node
2. Show a node's address ( yep, no need to leak it! )
3. Edit a node's content
4. Delete a node (by giving its address)
Notice that we can ovewrite a node's data by overflowing its previous node's content. Moreover, after checking the function of deleting a node, we found the following code:
The vulnerability's obvious: Heap overflow, except it use its own data structure.
Since it doesn't enable the DEP protection, we can store our shellcode in a known memory address (which is, in this case, a node's content), then exploit the heap overflow vulnerability, by overwriting free()'s GOT, let the function pointer point to our shellcode.
Note that 4 bytes in shellcode will be overwritten, so we'll have to use jmp relative to skip those 4 bytes machine code. Here's my shellcode:
So here's the exploitation:
1. New 3 nodes: node1, node2 & node3
2. Store the shellcode in node3's content
3. Get the address of node3 & node2, calculate the shellcode's address
4. Edit node1, overwrite node2's prev & next by overflowing node1's content
5. Delete node2, overwrite free()'s GOT, execute the shellcode & capture the flag
Here's the python script. Due to the connection problem, it has to wait 1 second before it recieve server's response.
The "BBBB" in the exploit is a 4 bytes data between each node. It actually is the meta data of a chunk. The free() function will check the meta data before it free the memory of a node. If the meta data isn't correct, the program will crash. But since we overwrite free()'s GOT, that meta data's no longer a problem.