根據《Windows核心編程》,用戶態進程的 4GB 虛擬空間(32位系統)劃分為:
| 地址範圍 | 大小 | 用途 | 備註 |
|---|---|---|---|
| 0x00000000 - 0x0000FFFF | 64 KB | 空指針賦值分區 | 捕獲 NULL 指針解引用 |
| 0x00010000 - 0x7FFEFFFF | ~2 GB | 用戶模式分區 | 應用程序代碼、數據、堆、棧、DLL 映射 |
| 0x7FFF0000 - 0x7FFFFFFF | 64 KB | 禁入分區 | 防止訪問越界觸及內核空間 |
| 0x80000000 - 0xFFFFFFFF | 2 GB | 內核模式分區 | 系統空間,用戶態不可直接訪問 |
(註:啟動 /3GB 啟動選項後,用戶/內核分界線移至 0xC0000000,用戶空間擴至 3GB。)
使用 VirtualQueryEx 遍歷用戶模式分區,獲取每個內存區域的屬性(基址、大小、狀態、類型、保護屬性等)。
SYSTEM_INFO sysInfo;
MEMORY_BASIC_INFORMATION mbi;
MEMORY_BASIC_INFORMATION mbiBlocks[1000];
int nCount = 0;
HANDLE hProcess = GetCurrentProcess();
GetSystemInfo(&sysInfo);
DWORD dwAddr = (DWORD)sysInfo.lpMinimumApplicationAddress; // 0x10000
do {
VirtualQueryEx(hProcess, (LPCVOID)dwAddr, &mbi, sizeof(mbi));
memcpy(&mbiBlocks[nCount++], &mbi, sizeof(mbi));
dwAddr += mbi.RegionSize; // 跳轉到下一塊
} while (dwAddr < (DWORD)sysInfo.lpMaximumApplicationAddress); // 0x7FFE0000
// 輸出 mbiBlocks 表格...
print_block_table(mbiBlocks, nCount);
typedef struct _MEMORY_BASIC_INFORMATION {
PVOID BaseAddress; // 區域基址
PVOID AllocationBase; // 分配基址(VirtualAlloc 返回地址)
DWORD AllocationProtect; // 初始保護屬性
SIZE_T RegionSize; // 區域大小
DWORD State; // 狀態:MEM_COMMIT/MEM_RESERVE/MEM_FREE
DWORD Protect; // 當前保護屬性:PAGE_READWRITE/EXECUTE/NOACCESS...
DWORD Type; // 類型:MEM_IMAGE/MEM_MAPPED/MEM_PRIVATE
} MEMORY_BASIC_INFORMATION;

Type=MEM_IMAGE),包含代碼段、數據段、資源段,通常 State=MEM_COMMIT,保護屬性區分可讀/可執行/可寫。Type=MEM_PRIVATE,State=MEM_COMMIT,Protect=PAGE_READWRITE。默認進程堆、CRT 堆、自定義堆。Type=MEM_PRIVATE,Protect=PAGE_READWRITE(或 PAGE_GUARD 頁作為增長觸發)。Type=MEM_MAPPED,如內存映射文件、共享內存區段。State=MEM_RESERVE 或 MEM_FREE,地址空間預留或完全未使用。!address、!vad、!heap 深度調試。下一篇將深入剖析:堆管理器細節、棧增長機制、DLL 重定位與 ASLR、線程本地存儲 (TLS)、纖程、內存映射文件共享內存 等進階主題,並結合調試實戰定位內存洩漏、碎片化、越界訪問等疑難雜癥。
理解用戶態地址空間佈局是 Windows 逆向、調試、性能優化、漏洞利用的基石。VirtualQueryEx 枚舉提供宏觀視角,配合工具深入微觀,構建完整內存認知體系。