Intro

This program is based off the CaNaKMgF pwnable challenge, except that CaNaKMgF_remastered has full RELRO enabled and PIE enabled. Interestingly, during the CTF, I had already solved CaNaKMgF using a technique that bypassed both mitigations, so I re-used the same exploit for CaNaKMgF_remastered and was able to get the flag.

Reversing

When we run the program, we are presented with the following menu.

1. Allocate2. Pray for Allah3. Free4. Read5. Run away

The program is very simple. It allows us to allocate heap chunks of different sizes, which it places in a global array in the .BSS called alloc_list[].
We can write data of our choosing into these chunks and the program ensures that the length of our data fits inside the chunk we’ve allocated for it.
We can specify chunks from this list that we would like to print out the contents of.
Similarly, we can also free any chunks in this list.

There was also some functionality to read limited files off the remote server when one selected the “Pray for Allah” option in the CaNaKMgF binary, but this function no longer worked in CaNaKMgF_remastered, and I didn’t use it in my exploit for CaNaKMgF, anyway.

Exploit

The main vulnerability in this program is that when a chunk is freed, the associated pointer to the chunk is not removed from alloc_list[]. This allows us to perform use-after-frees and double-frees which we can abuse to corrupt the heap and gain code execution.

To get a libc leak, we can exploit the UAF to allocate 2 small chunks, free the first one, and then print its contents out, since we know the FD and BK pointers of our free’d small chunk will be populated with a pointer to an offset from main_arena in libc. (The purpose of allocating a 2nd small chunk, is to prevent top chunk consolidation.)

To get control of RIP, we can perform a fastbin attack to get malloc() to return an almost arbitrary pointer, overwrite __malloc_hook, and then call our overwritten __malloc_hook function pointer by triggering a double free memory corruption error.

To perform the fastbin attack, we will allocate 2 fast chunks of size 0x68 bytes, and free the 2nd one, then the 1st one, and then the 2nd one again, abusing the fact that we can double-free fast chunks, so long as the head of the freelist that their fast chunk size is associated with, is not the same as the chunk that is being free’d.

To satisfy these constraints, we will abuse the fact that we can make FD point to misaligned addresses as long as they satisfy the valid size metadata field constraint. In our case, since we are targeting fast chunks of size 0x68, the following is a valid address should do the trick.

After two more allocations, our target address should now be at the head of this freelist:

[HEAD]->{target addr}

Then, the next memory allocation of size 0x68 should return a pointer to our target address+0x10 and since we can control the contents of chunks we allocate, we will simply overwrite __malloc_hook with a “magic” one gadget RCE address.

Once we trigger an actual double free corruption error, the program should now spawn a shell.