GCC 中使用以下參數設置 Canary:
-fstack-protector 啓用保護,不過只爲局部變量中含有數組的函數插入保護
-fstack-protector-all 啓用保護,爲所有函數插入保護
-fstack-protector-strong -fstack-protector-explicit 只對有明確 stack_protect attribute 的函數開啓保護
-fno-stack-protector 禁用保護
Canary 繞過技術
序言
Canary 是一種十分有效的解決棧溢出問題的漏洞緩解措施。但是並不意味着 Canary 就能夠阻止所有的棧溢出利用,在這裏給出了常見的存在 Canary 的棧溢出利用思路,請注意每種方法都有特定的環境要求。
泄露棧中的 Canary
Canary 設計爲以字節 \x00
結尾,本意是爲了保證 Canary 可以截斷字符串。 泄露棧中的 Canary 的思路是覆蓋 Canary 的低字節,來打印出剩餘的 Canary 部分。 這種利用方式需要存在合適的輸出函數,並且可能需要第一溢出泄露 Canary,之後再次溢出控制執行流程。
源碼:
// ex2.c #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> void getshell(void) { system("/bin/sh"); } void init() { setbuf(stdin, NULL); setbuf(stdout, NULL); setbuf(stderr, NULL); } void vuln() { char buf[100]; for(int i=0;i<2;i++){ read(0, buf, 0x200); printf(buf); } } int main(void) { init(); puts("Hello Hacker!"); vuln(); return 0; }
編譯爲 32bit 程序並關閉 PIE 保護 (默認開啓 NX,ASLR,Canary 保護)
gcc -m32 -no-pie ex2.c -o ex2
我們使用gdb-peda,嘗試獲取溢出的偏移值,發現程序報錯了SIGABR
SIGABRT是中止一個程序,它可以被捕捉,但不能被阻塞。處理函數返回後,所有打開的文件描述符將會被關閉,流也會被flush。
這裏我的理解是我們開啓了canary,我們輸入的字符覆蓋了canary插入的cookie,被檢測出來了,程序就終止了。