GNU obstack function-pointer hijack
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をサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
概要
GNU obstack はアロケータの状態を埋め込み、以下の2つの間接呼び出し先を持ちます:
chunkfun(オフセット+0x38) — シグネチャvoid *(*chunkfun)(void *, size_t)freefun(オフセット+0x40) — シグネチャvoid (*freefun)(void *, void *)extra_argとuse_extra_argフラグは_obstack_newchunkがchunkfun(new_size)を呼ぶかchunkfun(extra_arg, new_size)を呼ぶかを選択します
もし攻撃者がアプリケーション所有の struct obstack * やそのフィールドを破壊できれば、obstack が次に成長する(next_free == chunk_limit のとき)と chunkfun を通した間接呼び出しが発生し、コード実行のプリミティブが得られます。
プリミティブ: size_t のズレ → 0 バイト割当 → ポインタ OOB 書き込み
一般的なバグパターンは、論理長を 64-bit の size_t に保存しているのに、sizeof(ptr) * count の計算に 32ビットレジスタ を使っていることです。
- 例:
elements = obstack_alloc(obs, sizeof(void *) * size);はsize << 3のためにSHL EAX,0x3としてコンパイルされます。 size = 0x20000000、sizeof(void *) = 8の場合、32ビットで乗算がラップして0x0になり、ポインタ配列は 0 バイト となりますが、記録されるsizeは0x20000000のままです。- 続く
elements[curr++] = ptr;の書き込みは、隣接するヒープオブジェクトへ 8 バイトの OOB ポインタ書き込み を行い、制御されたクロスオブジェクト上書きプリミティブを与えます。
Leaking libc via obstack.chunkfun
- 2つのヒープオブジェクトを隣接させる(例えば、別々の obstack で作った2つのスタック)。
- オブジェクト A からのポインタ配列の OOB 書き込みを使い、オブジェクト B の
elementsポインタを上書きして、B からのpop/読み出しがオブジェクト A の obstack 内部のアドレスを参照するようにする。 - オフセット
0x38にあるchunkfun(デフォルトではmalloc)を読み出して libc の関数ポインタを漏らし、libc_base = leak - malloc_offsetを計算して他のシンボル(例:system,"/bin/sh")を導出する。
Hijacking chunkfun with a fake obstack
被害者が保持している struct obstack * を上書きして、obstack ヘッダを模した攻撃者制御のデータを指すようにします。必要最小限のフィールド:
- 次回 push 時に
_obstack_newchunkを強制するためにnext_free == chunk_limit chunkfun = system_addrextra_arg = binsh_addr,use_extra_arg = 1で2引数呼び出し形を選択
その後、被害者の obstack 上で割り当てをトリガーすると、間接呼び出しを通じて system("/bin/sh") が実行されます。
Example fake obstack layout (glibc 2.42 offsets):
fake = b""
fake += p64(0x1000) # chunk_size
fake += p64(heap_leak) # chunk
fake += p64(heap_leak) # object_base
fake += p64(heap_leak) # next_free == chunk_limit
fake += p64(heap_leak) # chunk_limit
fake += p64(0xF) # alignment_mask
fake += p64(0) # temp
fake += p64(system_addr) # chunkfun
fake += p64(0) # freefun
fake += p64(binsh_addr) # extra_arg
fake += p64(1) # use_extra_arg flag set
攻撃手順
- Trigger size wrap — 巨大な論理長を持つ0バイトのポインタ配列を作成する。
- Groom adjacency — OOB ポインタ書き込みが obstack ポインタを含む隣接オブジェクトに届くように整える。
- Leak libc — 隣接する obstack の
chunkfunに対象ポインタを向け、関数ポインタを読み取ることで行う。 - Forge obstack — 制御された
chunkfun/extra_argを持つ obstack データを偽造し、_obstack_newchunkが偽造ヘッダ内に到達するよう強制して、攻撃者が選んだ関数ポインタ呼び出しを引き起こす。
参考
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をサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。


