exit_hook相关利用
exit_hook相关利用
glibc2.34之前
利用条件:
- 至少有一次任意写
- 程序可以结束(可显式触发
exit
函数 或 主函数由libc_start_main
启动且可正常退出),调用到_dl_fini
函数
写个简单调试代码 , 来看看exit是怎么工作的
1 |
|
首先进入__run_exit_handlers
这里会调用到**_dl_fini函数** ,进入:
_dl_fini函数开头的for循环中就调用到了rtld_lock_default_lock_recursive函数 ,可以看到该函数的地址是直接通过*(rip + 偏移)拿到的:
来看一下_dl_fini源码
1 |
|
综上,只需要覆盖__rtld_lock_lock_recursive 和 _rtld_lock_unlock_recursive其中一个为one_gadget即可getshell,这rdi寄存器的值我们控制不了,除非能申请到chunk,然后往 _rtld_local+2440上面写”/bin/sh”的地址,否则就只能打one_gadget。
下面是一些偏移比赛时可以直接使用
在libc-2.23中
exit_hook = libc_base+0x5f0040+3848
exit_hook = libc_base+0x5f0040+3856
在libc-2.27中
exit_hook = libc_base+0x619060+3840
exit_hook = libc_base+0x619060+3848
这样一来,只要知道libc版本和任意地址的写,我们可以直接写这个指针,执行exit后就可以拿到shell了,不执行也可以正常结束也会返回这个
glibc2.34
在glibc2.34中exit_hook比较难找,相对libc基地址的偏移的
[CISCN 2022 初赛]newest_note | NSSCTF
解题思路
- 利用开始可控制大小,申请一个大于TopChunk大小的chunk,系统会调用mmap 分配,会映射libc地址开辟大小,就可以泄露libc地址
- 利用fastbin 进行 double free , 申请到exit_hook位置的chunk , 用one_gadget
1 |
|