# Winesap's Blog

## TMCTF 2017 Rev400

DelayExecution 第二個參數 (rdx) 是指向一個 uint64 值，是負值代表要 delay 幾 ns。Patch 好之後 continue，就會發現它跑得飛快了。

7z 解出來後是 stub.exe，這個就是很簡單的 reverse 了。16 位密碼每位是獨立的，直接暴出來就行:

## Plaid CTF 2015 PlaidDB Writeup

My exploit source code: https://gist.github.com/33d6e03d0c9a8c13f3ba

This challange is a ELF64 binary pwnable, which the libc.so library is also provided. The service provides some key-value operations, GET, PUT, DUMP and DEL, by a red-black tree (we spent lots of time on checking the implementation of the tree but nothing there). First we found an input sequence that may cause heap corruption:

The bug is in the function at 0x1040. The length of the buffer for the row key is not enough for the trailing '\0'. The last row key in the input above, which is exactly 24 bytes, causes an off-by-one null byte overwriting into the size entry of the next chunk in heap memory. This makes the next chunk shrink and clears the inuse bit so that the current chunk seems already freed. Since the row key buffer will not be freed when the row is not found in DEL operation, we use DEL to trigger this bug to avoid unwanted memory corruption and also overwrite the prevsize entry of the next chunk. After then, free the next chunk which the prevsize is overwrited and its forward chunk is also unlinked. The result is to put a large chunk which crosses over other chunks into the unsorted bin and we can get it back by malloc a data buffer with matching size later.

Since the data buffer is overlapping with other node structures, we can use GET to leak information on these structures or use PUT to overwrite them. Note that the PUT operation creates a new data buffer. So we have to call PUT twice to swap the current buffer back and fill it up. By overwriting the data pointer in the node struture, we are able to dump memory at arbitrary address by apply GET to the node (see the leak() function in my exploit). First we can leak heap base address by reading the pointer in node strutures.

There is a trick to defeat ASLR for the libc base address. In the libc implementation, malloc() call mmap instead for large size (0x21000 is enough). In general, these pages will be placed at the address just before the .tls section. There are some useful information on .tls, such as the address of main_arena, the canary value of stackguard and a pointer which points to somewhere on stack with fixed offset.

However, the data buffer pointer can not be used as arbitrary memory writing, since the PUT operation always create a new buffer. Thus we have to make malloc() return the address which we want to overwrite and fill it by node data. There are two approaches: free a fake chunk with the target address or corrupt the fastbin. Since free() check both head and foot of the chunk, corrupt fastbin is easier and the only sanity checking is the chunk size in malloc(). We can free a chunk in fastbin range and then overwrite its fd pointer with the target address. Then after malloc() called twice, the fake chunk at the target address should be return, if the chunk size has been set correctly. (See the fastbin path in libc source for more details, which start from line 3331 to 3358)

We decided to overwrite the stack start from a return address entry with ROP chain. Thus we have to setup a valid chunk size on stack somewhere, which is before but close enough to a return address so that a tiny fastbin chunk can successfully cover it. We found that there is a buffer on stack in the PUT function at 0x1240. The buffer stores the data size and the rest space (total 16 bytes) is large enough for a 8 bytes size value. Also the address (start from [rbp-0x38]) is close to the return address entry. The valid length of ROP chain is only 16 bytes, which is not enough for a system('/bin/sh') call, but its enough for jump to a leave; ret gadget and migrate stack to second ROP chain which placed on heap in advance. Note that the stackgaurd canary should be overwrite with correct value.

Cat the flag by shell: flag{one_null_byte_t0_rul3_them_all_4ecd68f0}

## 0ctf 2015 Freenote Write Up

Double free 漏洞利用，順便來試試之前想到的某個好用的 unlink() 利用法，建議對 heap exploitation 先有一些瞭解。

1. FD = p->fd = &p - 3, BK = p->bk = &p - 2
2. 檢查 FD->bk != p || BK->fd != p，不過因為 *(FD + 3) == p && *(BK + 2) == p 所以順利通過
3. FD->bk = BK，即 p = &p - 2
4. BK->fd = FD，即 p = &p - 3

#### 任意位址讀寫

Exploit: freenote.py

## Codegate CTF Preliminary 2015

#### sokoban

1. rand() 的 offset@libc 是 0x3d060，在 ASLR 下有 1/16 的機會隨機到 ?0060，這個 0 byte 位在 0x60C121
2. 0x3e260@libc 是一個神奇的 gadget: add rsp, 0x28; (pop XX)*6; ret
3. rand() 在重新隨機盤面時會被呼叫，然後 rsp 偏移 0x58 byte 的結果是... stack 頂端的值剛好是原本要 return 回 0x401A9A 的這個位址
4. 更瞎的地方是，有個隱藏的功能: 按 v 鍵可以把 0x60C121 處的值加 0x12。看來沒什麼用，不過 e260 和 d060 剛好差 0x12 ... 所以如果補成 1260 的話剛好可以跳到這個 gadget