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

概述

GNU obstacks 将分配器状态与两个间接调用目标一并存放:

  • chunkfun (offset +0x38),签名为 void *(*chunkfun)(void *, size_t)
  • freefun (offset +0x40),签名为 void (*freefun)(void *, void *)
  • extra_arguse_extra_arg 标志决定 _obstack_newchunk 是调用 chunkfun(new_size) 还是 chunkfun(extra_arg, new_size)

如果攻击者能够破坏应用持有的 struct obstack * 或其字段,当 obstack 下次增长(即 next_free == chunk_limit)时,会触发通过 chunkfun 的间接调用,从而可能获得代码执行原语。

Primitive: size_t desync → 0-byte allocation → pointer OOB write

一个常见的漏洞模式是使用 32-bit register 来计算 sizeof(ptr) * count,但将逻辑长度记录在 64-bit 的 size_t 中。

  • 示例:elements = obstack_alloc(obs, sizeof(void *) * size); 被编译为 SHL EAX,0x3,表示 size << 3
  • size = 0x20000000sizeof(void *) = 8 时,乘法在 32-bit 下会溢出为 0x0,因此指针数组将是 0 bytes,但记录的 size 仍为 0x20000000
  • 随后的 elements[curr++] = ptr; 写入会对相邻堆对象执行 8-byte OOB pointer stores,从而获得可控的跨对象覆盖原语。

Leaking libc via obstack.chunkfun

  1. 将两个堆对象放置为相邻(例如,使用两个独立 obstack 构建的两份堆栈)。
  2. 利用对象 A 的指针数组 OOB 写入覆盖对象 B 的 elements 指针,使得从 B 的 pop/读取会解引用指向对象 A 的 obstack 内部的地址。
  3. 读取位于偏移 0x38chunkfun(默认指向 malloc)以泄露 libc 函数指针,然后计算 libc_base = leak - malloc_offset 并推导其他符号(例如 system, "/bin/sh")。

Hijacking chunkfun with a fake obstack

覆盖受害者保存的 struct obstack * 指针,使其指向攻击者控制的数据,模拟 obstack 头。最少需要的字段:

  • next_free == chunk_limit —— 在下次 push 时强制触发 _obstack_newchunk
  • chunkfun = system_addr
  • extra_arg = binsh_addr, use_extra_arg = 1,选择两参数调用形式

然后触发对受害者 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

攻击流程

  1. Trigger size wrap 以创建一个具有巨大的逻辑长度的 0-byte pointer array。
  2. Groom adjacency,使一个 OOB pointer store 能够到达包含 obstack pointer 的相邻对象。
  3. Leak libc:通过将 victim pointer 重定向到相邻 obstack 的 chunkfun 并读取 function pointer 来泄露 libc。
  4. 锻造 obstack 数据(受控的 chunkfun/extra_arg),并强制 _obstack_newchunk 落入伪造的 header,从而触发攻击者选择的 function-pointer 调用。

References

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