CTFHub House of Einherjar
程序分析:
main
1 | int __fastcall __noreturn main(int argc, const char **argv, const char **envp) |
add
1 | int add() |
show
1 | unsigned __int64 show() |
delete
1 | __int64 delete() |
edit
1 | int edit() |
- 堆布局与 Off-By-Null: 连续分配几个 Chunk,利用
edit功能在 Chunk 1 中写入过多数据,溢出一个\x00字节,到紧邻的 Chunk 2 的头部,覆盖掉PREV_INUSE标志位。 - 触发向后合并 : 同时伪造 Chunk 2 的
prev_size。当释放 Chunk 2 时,glibc 会认为前面的很大一块内存包含已被释放的 Chunk 0 和正在使用的 Chunk 1都是空闲的,将它们合并成一个巨大的 Unsortedbin - 信息泄露 (Libc Leak): 因为 Chunk 1 被包含在了这个巨大的 Unsorted Bin 中,当我们重新分配 Chunk 0 时,Chunk 1 的数据区就会被写入 main_arena 的地址(Unsorted Bin 的 fd 和 bk 指针)。打印 Chunk 1 即可泄露 libc 基址。
- Fastbin 投毒与 Hook 劫持: 释放处于巨大 Chunk 内部的 Fastbin 大小的块,利用重叠的指针修改其 fd,使其指向 __malloc_hook 附近的伪造块。
- Realloc 栈帧调整与 One Gadget: 将
__malloc_hook劫持为realloc+16,将紧挨着的__realloc_hook劫持为one_gadget。最后调用malloc触发执行链,成功 Get Shell。
EXP 思路:
堆布局与触发 Off-By-Null
1 | add(0, 0xf0) # Chunk 0 |
- 修改 chunk2 prev_size 和 prev_inuse 分别为 0x170 和 0,触发堆块向后合并,chunk012 进行合并。
泄露 Libc 基址
1 | add(0, 0xf0) # 0 |
4. 准备 Fastbin 投毒 (Fastbin Attack)
1 | fake_size = malloc_hook - 0x23 |
- 由于 Chunk 1 还可以编辑,并且它和被释放的 Chunk 4 是重叠的。我们直接修改 Chunk 1,实际上就修改了已被放入 Fastbin 的 Chunk 4 的 fd 指针。我们将其 fd 指针改为了 fake_chunk (malloc_hook - 0x23)。
5. 劫持 Hook 与 Realloc 调整栈帧
1 | add(4, 0x68) |
add(5,0x68)之前:由于 fastbin 当中存放着 malloc_hook - 0x23,再次 add 的时候就会分配出来
- __realloc_hook 在 malloc_hook - 0x8 的位置,__malloc_hook 无法满足 gadgets 的条件
- 在 __malloc_hook 的地址上填充 realloc_hook + 16
- 这里对为什么+16 进行了详细解释:https://www.yuque.com/idcm/wnemg9/dfg3cdnir7uc2mp1
6. add、触发 Shell
1 | add(6, 0x10) |
Remote EXP:
1 | from pwn import * |
Local EXP:
1 | from pwn import * |
更新: 2026-04-27 19:03:44
原文: https://www.yuque.com/idcm/wnemg9/rm9lztbtgps8cz57