canary是棧溢出的防護(hù)機制,一般是位于ebp的上方逆巍,用于檢測棧幀是否有溢出狀態(tài)及塘,用圖形表示:
因為一個棧幀往往是ebp作為結(jié)尾的,所以canary一般是尾隨的(也有特殊情況蒸苇,具體看作者的匯編情況)磷蛹,在32位下是4個字節(jié),64位下是8個字節(jié)(最低位都是\x00)
那么這個保護(hù)機制也是很皮的溪烤,它為了防止別人暴力輸出它味咳,于是有個\x00的截斷符庇勃,canary的最低位是0x00,這么做為了防止canary的值泄漏槽驶,舉個64位的例子:
從fs段中取出最初的canary值责嚷,然后從棧中取canary放到edx中,二者異或掂铐,如果不相同則跳轉(zhuǎn)到___stack_chk_fail函數(shù)罕拂,這個函數(shù)底層是這樣的:
可見,__libc_message 的第二個%s輸出的是argv[0]全陨,argv[0]是指向第一個啟動參數(shù)字符串的指針爆班,所以,猜想只要我們能夠輸入足夠長的字符串覆蓋掉argv[0]辱姨,我們就能讓canary保護(hù)輸出我們想要地址上的值柿菩。
canary大概就是這些內(nèi)容,接下來常見的題型是怎么樣的呢雨涛?
一枢舶、通過某些方式泄漏canary:
1、格式化字符串泄露:大體思路就是通過格式化字符串讀取canary的值替久,然后在棧溢出的padding塊把canary所在位置的值用正確的canary替換凉泄,從而繞過canary的檢測。
2蚯根、fork爆破:對fork而言后众,作用相當(dāng)于自我復(fù)制,每一次復(fù)制出來的程序稼锅,內(nèi)存布局都是一樣的吼具,當(dāng)然canary值也一樣。那我們就可以逐位爆破矩距,如果程序GG了就說明這一位不對,如果程序正常就可以接著跑下一位怖竭,直到跑出正確的canary锥债。
3、數(shù)組下標(biāo)越界(待續(xù)痊臭,還沒學(xué)到)
二哮肚、故意觸發(fā)___stack_chk_fail:
1、ssp攻擊:根據(jù)上面學(xué)到的广匙,只要我們能夠輸入足夠長的字符串覆蓋掉argv[0]允趟,我們就能讓canary保護(hù)輸出我們想要地址上的值,舉個例子:
但是有時打印flag的話可能打印不出來(這種情況下一般有副本鸦致,放副本的地址潮剪,打印副本的flag即可)涣楷。
OJ有道題可以試試:
就是棧溢出保護(hù),然后0x600d20的地址里面的東西會變抗碰,我們通過查找發(fā)現(xiàn)它有一個副本狮斗,于是可以利用不變的副本去搞出flag。
從這里我們可以知道那個劃線的就是我們的argv[0]的位置弧蝇,因為可以看到裝的就是我們的程序命名字符串碳褒。這里我們需要找到flag的地址,然后直接覆蓋即可:
所以直接暴力填看疗,肯定會有一個填到的沙峻,最后驗收下:
2、King攻擊(自命名的):通過破壞canary的值两芳,觸發(fā)___stack_chk_fail庫函數(shù)专酗,然后我們只要替換這個函數(shù)的got表為我們的system函數(shù)或者getflag函數(shù)等后門函數(shù),并且故意讓canary檢查失敗就可以劫持程序的控制流了盗扇。(題目來自于hgame祷肯,week2)