當程式對一個固定大小的緩衝區進行資料寫入時,如果超過了該緩衝區的容量,那麼多出來的資料會覆蓋相鄰的記憶體區域。這些相鄰的區域可能是程式的其他變數、控制程式執行流程(如返回位址)或其他數據。當這些區域的內容被攻擊者控制後,可能會導致程式異常崩潰,或是允許攻擊者執行任意程式碼。
發現有漏洞的緩衝區:
程式可能在未驗證輸入長度的情況下,將輸入數據寫入固定大小的緩衝區。攻擊者可以利用這個弱點來傳遞過多的數據。
覆蓋關鍵區域:
如果攻擊者輸入的數據超過緩衝區的大小,這些數據可能會覆蓋一些關鍵的記憶體區域,例如堆疊上的返回地址。
控制流程轉向:
如果攻擊者能夠覆蓋返回位址,則在該函數結束時,程式將跳轉到攻擊者指定的位址執行。通常,攻擊者會在輸入數據中嵌入惡意的 shellcode,並使程式跳轉到這段 shellcode 的位置。
以下是舉例程式碼
#include <stdio.h>
#include <string.h>
void vulnerable_function(char *input) {
char buffer[50];
strcpy(buffer, input); // 沒有檢查輸入長度
printf("Input: %s\n", buffer);
}
int main() {
char input[100];
printf("Enter input: ");
gets(input); // 使用不安全的函數
vulnerable_function(input);
return 0;
}
gets()
函數,不會檢查輸入長度,容易導致溢出。strcpy()
也不會檢查 input 的長度,直接將輸入複製到 buffer。為了防止 Buffer Overflow,以下是幾種常見的防禦措施:
使用安全的函數:
使用 fgets()
、strncpy()
等函數來限制輸入長度,避免使用像 gets()
、strcpy()
這類不檢查輸入長度的函數。
現代編譯器和作業系統通常內建了一些安全機制來減少 Buffer Overflow 的風險,例如:
進入到今天的解題環節
Lab_1 - buffer overflow 0
先觀察題目附上的程式碼片段,可以發現 buf1 的大小雖然可接受 100,但進到 vuln()
後 buf2 的大小只有 16,所以只要輸入超過就會發生溢位問題。
void sigsegv_handler(int sig) {
printf("%s\n", flag);
fflush(stdout);
exit(1);
}
void vuln(char *input){
char buf2[16];
strcpy(buf2, input);
}
// ...... 中略
int main(int argc, char **argv){
fgets(flag,FLAGSIZE_MAX,f);
signal(SIGSEGV, sigsegv_handler); // Set up signal handler
har buf1[100];
gets(buf1);
vuln(buf1);
於是我們使用 nc
指令進入題目後,輸入 111111111122222222223333
的字串後成功拿到 flag。第 17~20 個字元需要覆蓋掉一些控制資料,所以輸入大於等於 20 的長度才能成功。
練習就到這邊,以下是參考資料,請搭配服用:
Buffer Overflow
buffer overflow 是什麼?
緩衝區溢位攻擊之一(Buffer Overflow)
內文如有錯誤,還請不吝指教~