Rating: 5.0

# DragonCTF

as a member of TSG (28th).

## Heap Hop

This service has two functions

- create a buffer with a specified size and write some data whose size is equal to the given size
- free a buffer by specifying object id

We call the data structured used in this chall "Chunk", which has the following elements.

```
0 +--------+
+ size +
4 +--------+
+ flags +
16 +--------+
+ offset +
size +--------+
+ data[1]+
2 * size +--------+
+data[1:]+
+ ... +
```

Each chunk contains 96 (= 12 * 8). The first element of each chunk is used for managing each chunk. `size` is 16-bytes aligned. Each bit of `flags` corresponds to each buffer the chunk has.
The program has an array of chunks, and when it is asked to create a buffer with some size S, it searches for a chunk whose size is S.
If it cannot find it, then it creates a new chunk and registers it to the array.
Also, when the user frees a buffer, and the program finds the buffer is the last element in a chunk, it frees the chunk.

### Vulnerabilities

There are two vulnerabilities.
- When the program creates a new chunk, it does not clear the buffer with 0. So, we can leak the libc address by observing `chunk_id`
- We can free the first element of a chunk, which is used for managing each chunk. By using this, we can change `size` and `flags` elements by re-allocating the first element, which leads to heap overflow.

### How to solve

Quickly, we can get a libc-address by the first vulnerability.

Since the smallest size we can create is 96 * 0x10, we cannot use some techniques related to tcache/smallbins.

Our approach is to create a mmap buffer on the top of libc-region like

```
0x00007f10ca528000 0x00007f10ca54d000 rw-p mapped <-- this one
0x00007f10ca54d000 0x00007f10ca572000 r--p /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x00007f10ca572000 0x00007f10ca6ea000 r-xp /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x00007f10ca6ea000 0x00007f10ca734000 r--p /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x00007f10ca734000 0x00007f10ca735000 ---p /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x00007f10ca735000 0x00007f10ca738000 r--p /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x00007f10ca738000 0x00007f10ca73b000 rw-p /usr/lib/x86_64-linux-gnu/libc-2.31.so
0x00007f10ca73b000 0x00007f10ca741000 rw-p mapped
```

Then we re-allocate the first element of that chunk so that the last element of the chunk is in the rw-region of libc-region.
We can overwrite `__free_hook` by creating a buffer at the last element of that chunk, which leads to getting a shell.

### Solver

[heap_hop.py](heap_hop.py)

## BabyShell

### Observation

There is a qemu-sandbox in which a server is running. We have a shell to connect to the sandbox, but we can use only busybox.

### How to solve

I analyzed the server application (and busybox, which is not required for this chall :( ), and found that it was enough to communicate with server application, which was started by `/init`.
This server application uses SSL. We can get the flag by `openssl s_client -connect localhost:4433`

The main challenge is that it is difficult to do an arbitrary execution since the filesystem is readonly and we cannot send any program to the sandbox.
I asked for help [kcz146](https://twitter.com/kcz146), who is a linux-pro, and he immediately found that we could use nc and gave me a nice command: `cat | xargs -I{} printf '\x{}' | busybox nc localhost 4433 | hexdump -v -e '1/1 "X%02x\n"'`.

So I wrote a proxy and solved it.

Original writeup (https://github.com/moratorium08/ctf_writeups/tree/master/2020/dragon).