Skip to content

改变 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_globalld 的一个结构体, ldlibc 的偏移也是可以调试出来.

因此对于 exit 改变程序流, 其中一个思路是利用 dl_fini:

  1. 找到 libc 偏移量, 调试得到 ld 的偏移量, 因此可以获取 _rtld_global 的实际位置.
  2. 找到 _rtld_global._##name 的偏移量, 修改其为 one_gadget 即可.

Comments