Heap 漏洞通常與記憶體管理有關,特別是 C 和 C++ 等可以直接操作記憶體語言。當程式使用 malloc()
或 free()
等函數動態分配和釋放記憶體時,會將記憶體區塊存儲在 heap 區域中。由於這些記憶體分配過程並沒有自動進行嚴格的邊界檢查,容易導致一些漏洞。
當程式分配一個記憶體區塊,但寫入的資料超過該區塊範圍時,就會發生 heap overflow,導致鄰近記憶體區塊的資料遭到覆寫,可能造成程式控制流或資料的破壞。
利用方式:
覆寫控制結構:heap 一般會維護一些控制結構,如分配表和指標。攻擊者可以透過覆寫這些結構,改變記憶體分配的行為,進而操控程式的執行。
覆寫函數指標:若鄰近記憶體區域包含函數指標,攻擊者可覆寫這些指標,讓程式跳轉到惡意代碼區執行。
舉例來說:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *buffer1 = (char *)malloc(8); // 分配 8 個字節的記憶體
char *buffer2 = (char *)malloc(8); // 分配另一個 8 個字節的記憶體
strcpy(buffer1, "AAAAAAAAAAAAAAAA"); // 將 16 個字節的資料寫入 buffer1
printf("Buffer2: %s\n", buffer2); // buffer2 可能已經被覆寫
free(buffer1);
free(buffer2);
return 0;
}
buffer1
只分配了 8 個字節,但程式寫入了 16 個字節,導致資料覆寫到 buffer2
所屬的記憶體區域。這可能讓鄰近的記憶體區塊(例如 buffer2)被覆蓋,造成意料外的行為。
攻擊者可以利用這個漏洞來覆寫相鄰的控制資料或函數指標,進而操控程式執行惡意代碼。
那我們開始今天的 Lab 吧~
Lab_1 - heap 0
我們先使用 nc
指令進到題目
觀察題目的程式片段,發現只要讓 bico != pico
。那利用上面的 heap 漏洞,讓輸入的值覆蓋掉原本記憶體上的值,進而讓程式發生錯誤。
void check_win() {
if (strcmp(safe_var, "bico") != 0) {
printf("\nYOU WIN\n");
// Print flag
char buf[FLAGSIZE_MAX];
FILE *fd = fopen("flag.txt", "r");
fgets(buf, FLAGSIZE_MAX, fd);
printf("%s\n", buf);
fflush(stdout);
exit(0);
} else {
printf("Looks like everything is still secure!\n");
printf("\nNo flag for you :(\n");
fflush(stdout);
}
}
輸入一串長長的字串
再次看現在記憶體的狀況
最後查看記憶體內容,成功拿到 flag
Lab_2 - heap 1
這題一樣查看程式碼,發現要讓下面的 bico
變成 pico
輸入 32 個字元後開始寫入我們想要的內容,成功拿到 flag
練習就到這邊,以下是參考資料,請搭配服用:
內文如有錯誤,還請不吝指教~