Sunday, April 13, 2014

PlaidCTF pwnable 200 ezhp

[Played with Team Segfault]

The challenge provided a means for adding, removing, changing and printing of notes. The challenge binary was not made available for a while initially -- playing around with the remote challenge for a while we can notice that a couple of crashes happens while removing notes.

On obtaining the binary, we can RE it to find the following interesting functions. NX is disabled, unsure about ASLR.

-========]
Analysis

The "add" function checks if the number of notes has exceeded 1022, if not allocates memory for a new note. The size of the note depends on user input. Even though the allocation happens based on a size given by the user, the size is not kept track of in a variable or struct. Memory allocation does not seem to be using malloc, its something custom made(I've named it "allocate_space" below). The code for allocation looks a bit more involved, maybe I'll come back to that later if needed.


The "change" function takes in a size, and reads input to an earlier allocated note. Needless to say, we don't keep track of the allocated sizes, and can cause reads that read beyond the allocated space. Nice.
The "remove" notes function looks normal too, it has sanity checks in place. However, it seems to be calling what seems like a custom made "free"(I'm calling it "free_space"). Its clear that we can control writes to arbitrary memory by manipulating next and prev. 
From the above code, we can deduce that the "metadata" of each allocated "block" starts 12 bytes before the actual block. At 4 bytes and 8 bytes from the start of the metadata we have 2 pointers. If we can overwrite one pointer with the GOT address of puts(minus 4) and the second with the address of our shellcode, we could get a shell when "puts" is called next.
Looking at the "print" notes function we can see that, the data is printed out using a puts. 

-========]
Debugging

Creating 3 notes and debugging in gdb, we get the following memory layout.

We can confirm a few things :-
- It is possible to overwrite the block metadata of the next block and overwrite pointers as needed. I could create 3 blocks, the third containing the shellcode, the first overwriting the metadata of the second. I could then free the second to overwrite pointers.
- We can have an infoleak when puts tries to print notes. This way we can get the address of where the next block ends. In the figure above, after the block of "B"'s we have the address 0x0804c342(its actually 0x0804c300, I just overwrote the LSB of the address, more on this later). 0x0804c300 is the address where the next block(the last block of nops) ends.

-========]
Exploitation

The final exploit for the challenge can be found here
-========]
Note :
The leaked address might contain a "\x00" as the LSB, hence it is important to overwrite it with a "B"(as shown in the figure under "Debugging") so that "puts" leaks the address properly.

No comments:

Post a Comment