[CISCN 2021 初赛]lonelywolf
程序分析:
- main 函数
1 | void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) |
- allocate 函数
1 | unsigned __int64 allocate() |
- edit
1 | unsigned __int64 edit() |
- show
1 | unsigned __int64 show() |
- delete
1 | unsigned __int64 delete() |
free 后没有置 0,存在 UAF 漏洞。
在 glibc 2.27 中,引入了 Tcache 机制来加速内存分配,但在早期的 2.27 版本中,对 Double Free 的安全检查非常薄弱。我们可以利用这一点,结合了 UAF** **漏洞,最终劫持了程序的执行流并拿到了 Shell。
封装函数
1 | def new(size): |
泄露堆基址
1 | new(0x78) |
- ****分配了一个 0x78(实际占用 0x80)的堆块并释放,它会进入对应大小的 Tcache 链表。
- 绕过检查:脚本使用 edit(“a”0x10) 修改了已经被释放的堆块。在 glibc 2.27 的部分修补版本中,Tcache 会通过检查堆块的第二个 8 字节,key 字段来防止 Double Free。这里通过写入 a0x10 破坏了 key 字段,成功绕过了这个检查。
- Double Free:再次 free() 同一个堆块。此时 Tcache 链表形成了环状:Chunk A -> Chunk A。
- 调用 show() 打印该堆块的 fd 指针(现在指向它自己),从而获得了**堆空间的地址 **
1 | free() |
劫持 Tcache (Tcache Poisoning)
1 | head = info - 0x250 |
- 定位目标:堆内存的最开头存放着一个总管家结构体 tcache_perthread_struct。脚本通过泄露的堆地址减去 0x250 偏移,精准定位到了这个管家结构体的内容地址
- ****通过 new 将刚刚 Double Free 的块取出来一个,然后通过 edit 将其 fd 指针修改为 head。
- 连续调用两次 new(0x78)。第一次拿回的是刚刚被篡改指针的堆块,第二次分配则直接分配到了 tcache_perthread_struct 所在的内存区域。至此,我们可以掌握整个 Tcache 的控制权。
泄露 libc 基地址
1 | pad = p64(0)*4+p64(0x0000000007000000) |
- 伪造计数器:当前 Index 0 指向的是tcache_perthread_struct。通过 edit(pad) 写入 0x7000000,意在篡改tcache_perthread_struct 当中的信息,表示 0x78 大小的 Tcachebin 已满
- 对 tcache_perthread_struct 执行 free()。由于它对应的 Tcache 已经被标记为满,这个堆块会被丢进 Unsorted Bin。
1 | free() |
- 进入 Unsorted Bin 的堆块,其 fd 和 bk 指针会被写入 main_arena 的地址。通过 show() 打印出来,再结合偏移量计算,就能算出 libc_base、system 函数和 __free_hook 的真实内存地址。
劫持 hook 获取 shell
1 | new(0x40) |
- 这是一种非常霸道的操作。由于我们再次控制 tcache_perthread_struct 里的 Entries 数组,脚本将大小为 0x50(对应 0x40 用户数据)的 Tcache 链表直接指向了 __free_hook - 8。
- 分配到该位置后,写入 b”/bin/sh\x00” 和 system 函数的地址。
- 内存布局结果:
- __free_hook - 8 的位置存放了字符串 “/bin/sh\x00”
- __free_hook 的位置被替换成了 system 函数的地址。
- 调用 free()。由于我们正准备释放这块内存,系统会先去检查 __free_hook,发现那里有东西,于是就把当前堆块的地址(即 “/bin/sh” 所在的地址)作为参数传给了 Hook 指向的函数(即 system)。最终相当于执行了 system(“/bin/sh”)。
总 EXP:
1 | from pwn import * |
更新: 2026-04-08 20:55:32
原文: https://www.yuque.com/idcm/wnemg9/tp6449o2e4khtqo5