# Writeup

## 1. Binary Analysis

First thing first,**checksec**.

FORTIFY : disabled

The differences between original challenge CaNaKMgF are **PIE is ENABLED and RELRO is FULL**.

Also the arbitrary file read in original CaNaKMgF has been replaced with an exit(0).

The major vulnerability is **Dangling pointer**。


## 2.Exploit

### 2.1 Leak
Since we cannot read /proc/self/maps to defeat ASLR,there must be another way.

After the smallbin is freed, there will be a pointer stores at the first QWORD value in this memory.

Function do_read doesn't check if the pointer is freed(In fact this is unable to check), so there are 3 steps to leak libc.

> * malloc a smallbin
> * free this smallbin
> * read the smallbin

Now we have base address of libc, let's play with fastbin!.

### 2.2 Fastbin Attack

This will tricks malloc into returning a nearly-arbitrary pointer by abusing the fastbin freelist.

General process splits in some steps.

> 1. malloc 3 fastbins in exactly same size.
> 2. free the first fastbin.
> 3. free the second fastbin.
> 4. free the first fastbin again!
> 5. malloc a fastbin with same size used before.
> 6. edit the first QWORD in memory just returned (freelist's FD pointer) to an arbitrary pointer.
> 7. malloc second fastbin with same size.
> 8. malloc third fastbin with same size.
> 9. now the arbitrary pointer should be in fastbin freelist!
> 10. another malloc will return the arbitrary porint we just write in step 6!

But this trick returns nearly-arbitrary pointer ,because there should be a corresponding size stores in next QWORD of the pointer you want.

Last time I chose the memory right before the malloc_hook, this time I chose a memory inside stdout in libc.


Yes! memory chunk doesn't need to be aligned!

And 0x7f matches the size 0x70 in fastbin!

Now we can trick malloc to reurn a pointer inside the stdout,cool!

Next we can modify the pointer of vtable, btw the libc version is 2.23 and it doesn't contain a vtable check!

While the puts in print_menu function is called, we will control the rip by modifying vtable in stdout,but this is a one-shoot jump.

First I consider the magic gadgets in libc,but sadly none of this gadgets works.

I suddenly noticed that while we control the rip,the rdi points to stdout pointer!

Why not just control rip to **function gets**?


Now we can modify the whole content of stdout!

-- How to spawn a shell?

-- system("/bin/sh") !

This time we will overwrite the vtable like this:


This will call system('1\x80;/bin/sh;') after next puts called!

What '1\x80;' does here?

Let's see the implementation of puts.


so just put a \x80 there :)

All done! we have a shell!!


Original writeup (https://github.com/Kung-Pao-Chicken/ctf/tree/master/2017_ASIS_CTF/CaNaKMgF_remastered).