在之前的文章中,我們介紹了 Heap 分配中的 First Fit 演算法,這種機制透過選擇第一個能夠滿足分配需求的空閒區塊來管理記憶體。這樣的分配策略可以提高效率,但也帶來了潛在的漏洞,例如Use After Free (UAF)。今天我們將繼續深入了解 Heap 漏洞中的 Use After Free,並探討如何利用 First Fit 分配策略來實現攻擊。
當程式動態分配記憶體時,通常會使用像 malloc() 這樣的函數來請求記憶體空間,並在記憶體不再需要時使用 free() 釋放。理論上,釋放後的記憶體應該不可再被存取或修改,否則可能導致意料之外的行為。然而,如果程式在釋放記憶體後,仍然試圖透過釋放前的指標來存取該區塊,就會產生 Use After Free (UAF) 漏洞。
UAF 的危險在於,釋放後的記憶體區塊可能會被其他程序或資料覆寫,而程式不知情的情況下,仍然使用這些被覆寫的數據,進而導致安全問題。
在 First Fit 演算法中,當記憶體被釋放後,這些區塊會進入 Heap 的空閒區塊列表。當下一次有新的記憶體需求時,系統會從這些空閒區塊中挑選第一個符合要求的區塊來使用。這意味著,如果某一個區塊被釋放並重新分配,程式可以再次使用相同的記憶體位址。
這種行為給攻擊者提供了一個可預測的攻擊途徑。如果攻擊者知道一個記憶體區塊在釋放後會被再次分配,他們可以利用這個區塊進行覆寫操作。例如,他們可以釋放一個控制結構所在的記憶體區塊,然後在重新分配時覆寫該結構,從而達到任意代碼執行或控制程序流的目的。
以下範例展示了如何利用 UAF 漏洞與 First Fit 配合,覆寫已經釋放的記憶體內容:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char *a = (char *)malloc(0x512);
char *b = (char *)malloc(0x256);
strcpy(a, "This is A!");
printf("a: %s\n", a);
free(a);
char *c = (char *)malloc(0x500);
strcpy(c, "This is C!");
printf("c: %s\n", c);
printf("a: %s\n", a);
return 0;
}
可以看到我們使用 malloc 分配了兩個區塊 a 和 b。a 分配了 0x512 bytes,b 分配了 0x256 bytes。接著在 a 中寫入字符串 "This is A!",然後釋放 a,該記憶體區塊進入了 Heap 的空閒區塊列表。
接著,我們再次請求 0x500 bytes 的記憶體。由於 First Fit 的原理,Heap 管理器會將這個分配請求分配到最早釋放且能滿足需求的區塊,也就是剛剛釋放的 a 區塊。最後我們在新分配的 c 中寫入字符串 "This is C!"。由於 c 和 a 使用同一塊記憶體,因此,原本在 a 中的資料也被覆寫了。如下: