改变 dl_fini 劫持程序流
复制本地路径 | 在线编辑
exit 函数执行退出时有一条调用链是 exit->_dl_fini.
_dl_fini (void) {
// ...
for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns) {
/* Protect against concurrent loads and unloads. */
// 关键点
__rtld_lock_lock_recursive (GL(dl_load_lock));
unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
// ...
}
}
里面用到的 __rtld_lock_lock_recursive 是可以利用的函数, 其定义如下
# define __rtld_lock_lock_recursive(NAME) \
GL(dl_rtld_lock_recursive) (&(NAME).mutex)
# if IS_IN (rtld)
# define GL(name) _rtld_local._##name
# else
# define GL(name) _rtld_global._##name
# endif
最后这个函数相当于 _rtld_global._##name, 调试后发现偏移量为 3848, 不保证一定正确, 可以自行调试.
而 _rtld_global 是 ld 的一个结构体, ld 和 libc 的偏移也是可以调试出来.
因此对于 exit 改变程序流, 其中一个思路是利用 dl_fini:
- 找到
libc偏移量, 调试得到ld的偏移量, 因此可以获取_rtld_global的实际位置. - 找到
_rtld_global._##name的偏移量, 修改其为one_gadget即可.