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.


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. 


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.


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.

Saturday, April 5, 2014

Playing around with SROP

Recently, an interesting paper came out[1] that described an interesting mechanism that could be used for the exploitation of memory corruption vulnerabilities. While the paper does a good job of explaining how such an attack could be performed, this is my attempt at reproducing the same with a PoC and introducing a library that could be used to write such exploits in an easier fashion. This paper was interesting for two reasons : it talked about "portable shellcode" and "relative ease of exploitation".

Vulnerable code

The code can be viewed here[2]. It contains an obvious overflow, is compiled statically, and has inline assembly to make the demonstration even easier. The server code also has intentional info leaks where it gives out information about a the address of a local buffer and the address of a page mapped in using mmap, that has RW permissions. The PoC exploit for 32 bit does not use the mmap'd region and is run on non-ASLR systems.


Signal handlers return to a stub that perform a system call named "sigreturn". Its purpose is to restore the execution state of the program that had been interrupted when the signal handler was called. It does this by popping a signal frame that contains the values of all registers and storing those values into the registers.

This presents us with an opportunity to craft fake signal frames and perform a kind of "SROP-chaining".

Assumptions made :-
[a] EAX/RAX has the register value of 0x77/0xf.
[b] The "syscall/int 0x80 instruction is present"
[c] There is a writeable page in memory whose address we know.
[d] Nulls are allowed in the payload.

Advantage of using SROP the authors[1] point out is that :-
- You only need the address of one gadget "syscall/int 0x80; ret".
- For the most part, the signal frames that are created can be reused.


Let us consider the vulnerable program shown at [2]. An EIP overwrite can be achieved by giving in input of length greater than the buffer size. We can notice that for ease of presenting the idea, we have added an inline gadget to meet requirement [a][b], and a call to mmap to accurately meet [c]. The input is read in the vulnerable program using "read" to circumvent the null space terminal requirement and meet [d].

The exploit can be viewed here[3]. It performs a jump to the gadget that performs a sigreturn call which in turn will load the sigreturn frame from the stack and load it into the registers. In order to ease the creation of the signal frame you could choose to do use the Frame module[4] like the following :-
>>> from Frame import SigreturnFrame
>>> frame = SigreturnFrame()
>>> frame.setvalue("<register>", <value>)
>>> sploit += frame.get_frame()

An exploit that spawns an execve shell can be found at [3].

Further plans
- Add support/poc for x64 , its been added[5], thanks for [Segfault]Reno for helping out.
- Add support/poc for ARM
- Try finding out global unvarying addresses for gadgets such as "int 80/syscall/svc; ret" across multiple distros.

References :-
[1] Framing Signals, A return to portable shellcode