---
# System prepended metadata

title: Heap Exploitation
tags: [pwn]

---

# Heap Exploitation

- **基於NTU Computer Security Fall 2019所寫的筆記**
 
[yuawn NTU-Computer-Security](https://github.com/yuawn/NTU-Computer-Security)

## Heap workflow

- **通過 `nmmap`或 `brk`跟kernel要memory**

![image](https://hackmd.io/_uploads/ryc5o5DC1g.png)

- **跟kernel要了memory會放在glibc再透過`malloc`來跟glibc要memory**

![image](https://hackmd.io/_uploads/B1o8n5DCkg.png)

## **chunks**
- 注意heap是以16 bytes唯一排
`Allocated chunk` malloc拿到的
`Free chunk` free掉的
`Top Chunk` 未分配的

---

![image](https://hackmd.io/_uploads/SkWcNFPxgx.png)


 ### Allocated chunk
 
 - **`chunk header`也可叫`metadata`**
 - **! `pointer`會指向user data的頭而不是header**
 - **`size`跟`N` `M` `P`中間有個byte不做使用**
 ![image](https://hackmd.io/_uploads/Hk8H-hDAJe.png)

---
 - **`prev_size/data` 連續記憶體上⼀塊如是 free chunk，則紀錄該size，
若是 allocated chunk 則同時為它的 data。**

- **`size` 該memory的大小(佔4bytes)** 
 
-  **`(P) PREV_INUSE` 上⼀個 chunk 是否使⽤中**

-  **`(M) IS_MMAPED` chunk 是否透過 mmap 出來的**
  
-  **`(N) NON_MAIN_ARENA` 該 chunk 是否不屬於 main arena**
 
 ![image](https://hackmd.io/_uploads/BkFJjsPC1g.png)
 
 
 ### Free Chunk
 
 - **連續記憶體下⼀塊的 `P flag` 為0**
 ---
 
 - **`(fd) forward pointer` 指向同⼀ bin 中的前⼀塊 chunk (linked list)**
 
 -  **`(bk) backward pointer` 指向同⼀ bin 中的後⼀塊 chunk (linked list)**
 
 ![image](https://hackmd.io/_uploads/H1uSQhvC1x.png)
 
 ### Top Chunk
 
 - **第⼀次`malloc`後，剩下的空間為 `top chunk`，分配空間時視情況從 `top chunk` 切割分配**

- **free `Top chunk 連續記憶體上⼀塊chunk`時，若不是 `fastbin` 則會與 `Top chunk` merge，`top chunk` `P` 恆為1。**
 
 ![image](https://hackmd.io/_uploads/rkYbL3vRJx.png)
 
 ## bins
 - **回收 Free chunk 的資料結構**

- **主要依據 `size` ⼤⼩，分為：**
**`tcache bin`**
**`fast bin`**
`small bin` 
`large bin`
`unsorted bin`
---
### Fast bin


- **Size < `0x90` bytes**
- **bin 中依據 `size` 又會劃分為，0x20, 0x30, 0x40 ...**
- **`global_max_fast` = 0x80(在判定中是<=0x80)**
- **Singly linked list，`fd` 指向前⼀個，`bk` 沒⽤到**
- **LIFO (Last in, First out)**
- **! free 時`不會`將下⼀塊 `chunk P flag` 設成 `0`**

---
### Small bin


**• 僅在malloc時被切割才會放到這
• Circular doubly linked list
• 依據 size 劃分為 62 個bin
• 0x20, 0x30 ~ 0x3f0
• 0x20 ~ 0x80 的⼤⼩與 fast bin 重疊，會根據機制放到fast bin或small bin
• FIFO (First in, First out)
• free 掉時會將下⼀塊chunk P 設為0**

---
### Large bin


**• 僅在malloc時被切割才會放到這
• Circular doubly linked list (依據⼤⼩遞減排序)
• size >= 1024 bytes (0x400)
• 63 bins
• 細節可以參考 source code 
• header
• fd_nextsize
• bk_nextsize** 

![image](https://hackmd.io/_uploads/rJL8rxOA1l.png)

---
### Unsorted bin


- **Circular doubly linked list**
- **free 的 chunk `size` ⼤於 `fast bin` 時，不會直接放到對應的 `bin` 裡，會先丟到
`unsorted bin` 中。**
- **`malloc` `fast bin` `size` ⼤⼩時會先去 `fast bin` `list` 裡找，若沒有則會⾄ `unsorted bin`找，如找到⼀樣⼤⼩則回傳，若無但找到⼤⼩⼤於所需⼤⼩的 `chunk` 則切割回傳，剩下的部分會丟回 `unsorted bin`，若都沒有則從 `top chunk` 切出來回傳。**

- **在`malloc`時會因為`unsorted bin`的切割而造成`small bin`也有`fast bin`的`size`。**

---

### Tcache
- **`glibc` >= `2.26`**
- **小於 `0x408`  ⼤⼩範圍的 `chunk` 都會使⽤ `tcache`**
- **`Tcache` 中，當滿 `7` 個時，再 `free` 才會再放⾄ `fastbin` 中。**
- **`tcache fd` 是指向 `user data`。**
- **`malloc` 時沒有檢查 `size` 是否合法**
- **bypass `double free` check fill up the tcache bins list in same size(7) then free the same chunk from tcache again it will be put to the type(`fastbin`/`small bin`/`large bin`) of its size instead of catching double free**
![image](https://hackmd.io/_uploads/HkHWlSARge.png)

## malloc
- **`malloc` `fast bin` `size` ⼤⼩時會先去 `fast bin` `list` 裡找，若沒有則會⾄ `unsorted bin`找，如找到⼀樣⼤⼩則回傳，若無但找到⼤⼩⼤於所需⼤⼩的 `chunk` 則切割回傳，剩下的部分會丟回 `unsorted bin`，若都沒有則從 `top chunk` 切出來回傳。**

## Hooks

- **`glibc` 中存在許多 `function hooks`，會是個很好的寫入目標**
**__malloc_hook
__free_hook
__realloc_hook**
- **執⾏該 `function` 時，發現該 `function hook` 有值，則當作 `function pointer` 跳上去執⾏。**
![image](https://hackmd.io/_uploads/S15JbJIWxl.png)




 ## Use After Free (UAF)
 
- **`free( ptr )`**

- **`free` 完 `pointer` 後未將 `ptr` 清空 `( ptr = NULL )`，稱之 `dangling pointer` 。**

- **`information leak`**


- **`fast bin` leak `heap address`**
- **`unsorted bin` leak `libc address`**

## Fastbin attack

- **fastbin 在檢查 double free 時，cmp `linked list` 第⼀個 `chunk` 即將要 `free` 掉的 `chunk`**

- **bypass `free(A) free(B) free(A)`**

![image](https://hackmd.io/_uploads/rk9ENFwxlg.png)

- **malloc(0x70)**
 
![image](https://hackmd.io/_uploads/B1ewDKPlex.png)
![image](https://hackmd.io/_uploads/HyWKwYDexl.png)

- **write `s` to fake `fd`**

![image](https://hackmd.io/_uploads/BJC2PKPeex.png)

- **`malloc`到`fake chunk`**

![image](https://hackmd.io/_uploads/S1AO_Yvelx.png)

- **write everywhere!**

![image](https://hackmd.io/_uploads/ByQhdKwgex.png)

### **constraints**

- **`malloc` check `chunk size`是否正確**

- **bypass by using aslr address like 0x7f which is
size 0x70 N=true M=true P=true if u ignore the 0xc6**
![image](https://hackmd.io/_uploads/SkSXYnKele.png)
























 




