Programs cannot touch RAM directly, so each program is given virtual memory
Example: when a program says "I want what is at 400 Main Street", Windows checks its translation table and knows where that really is in RAM. The program never knows where its data physically lives, and it does not need to.
Page state
Each state, with its constant, an analogy and whether it can be used:
Free (MEM_FREE): An empty parking space with no owner. No: touching it raises an access violation
Reserved (MEM_RESERVE): A space with your name on it, but no car. Not yet: nobody else can take it
Committed (MEM_COMMIT): A space with the car parked. Yes, if the permissions allow it
c
#include <Windows.h>#include <stdio.h>intmain() {
DWORD dwProcessId = 34760;
HANDLE hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, // Permissions we request: query info + read memory
FALSE, // Do child processes inherit this handle? No
dwProcessId // PID of the target process
);
if (hProcess == NULL) {
DWORD dwError = GetLastError();
if (dwError == ERROR_ACCESS_DENIED) {
printf("[!] No permissions on PID %lu\n", dwProcessId);
}
elseif (dwError == ERROR_INVALID_PARAMETER) {
printf("[!] PID %lu does not exist\n", dwProcessId);
}
elseprintf("[!] OpenProcess failed with error: %lu\n", dwError);
return -1;
}
MEMORY_BASIC_INFORMATION Mbi = { 0 };
PBYTE pAddress = NULL;
// Same as VirtualQuery, but "Ex" = on another process (that is why it takes the handle)if (VirtualQueryEx(hProcess, pAddress, &Mbi, sizeof(Mbi))) {
// Only show committed regions (the ones backed by real memory)if (Mbi.State == MEM_COMMIT) {
printf("0x%p %10zu bytes %s %s Protect: 0x%08lX\n",
Mbi.BaseAddress,
Mbi.RegionSize,
StateText(Mbi.State),
TypeText(Mbi.Type),
Mbi.Protect);
}
// Jump to the end of this region = start of the next one
pAddress = (PBYTE)Mbi.BaseAddress + Mbi.RegionSize;
}
CloseHandle(hProcess);
return0;
}
Protection
PAGE_NOACCESS: Nothing: any access raises an error
PAGE_READONLY (R): Read only
PAGE_READWRITE (RW): Read and write (normal data)
PAGE_EXECUTE_READ (RX): Read and execute (normal code)
PAGE_EXECUTE_READWRITE (RWX): Everything
PAGE_GUARD (modifier): One-shot alarm
Type
MEM_PRIVATE: memory that belongs only to that process. It includes what you reserve with VirtualAlloc, the heap and the stack.
MEM_MAPPED: comes from a mapped section that is not an executable, for example with CreateFileMapping + MapViewOfFile. It can be shared between processes. The module comes back to it later with Mapping Injection.
MEM_IMAGE: comes from a loaded .exe or .dll. Each PE section is mapped with its own permissions: .text (the code) as RX, the data sections as RW, etc.
Windows protections
DEP (Data Execution Prevention): Windows does not allow code to run in areas marked as data only; if an attacker runs code in an RW area, the program crashes
ASLR (Address Space Layout Randomization): Every time a program starts, Windows places things at different addresses. It is as if the street numbers changed every day. Many attacks need to know exactly where something is in memory; with ASLR that address changes, so the attacker cannot target it without finding it out first.