Los programas no pueden tocar memoria RAM directamente, por eso se le da cada programa una memoria virtual
Ejemplo: Cuando un programa dice "quiero lo que hay en la calle 400", Windows mira su tabla de traducción y sabe que en realidad eso está en tal sitio de la RAM. El programa nunca sabe dónde está físicamente su información, ni le hace falta.
Estado de Página
Cada estado, con su constante, una analogía y si se puede usar:
Libre (MEM_FREE): Plaza vacía y sin dueño. No: tocarla da access violation
Reservada (MEM_RESERVE): Plaza con tu nombre, pero sin coche. No todavía: nadie más puede cogerla
Comprometida (MEM_COMMIT): Plaza con el coche aparcado. Sí, si los permisos lo dejan
c
#include <Windows.h>#include <stdio.h>intmain() {
DWORD dwProcesoId = 34760;
HANDLE hProceso = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, // Permisos que pedimos: consultar info + leer memoria
FALSE, // ¿Heredan este handle los procesos hijos? No
dwProcesoId // PID del proceso objetivo
);
if (hProceso == NULL) {
DWORD dwError = GetLastError();
if (dwError == ERROR_ACCESS_DENIED) {
printf("[!] Sin permisos sobre el PID %lu\n", dwProcesoId);
}
elseif (dwError == ERROR_INVALID_PARAMETER) {
printf("[!] El PID %lu no existe\n", dwProcesoId);
}
elseprintf("[!] OpenProcess fallo con error: %lu\n", dwError);
return -1;
}
MEMORY_BASIC_INFORMATION Mbi = { 0 };
PBYTE pDireccion = NULL;
// Igual que VirtualQuery, pero con "Ex" = sobre otro proceso (por eso recibe el handle)if (VirtualQueryEx(hProceso, pDireccion, &Mbi, sizeof(Mbi))) {
// Solo mostramos las regiones comprometidas (las que tienen memoria de verdad)if (Mbi.State == MEM_COMMIT) {
printf("0x%p %10zu bytes %s %s Protect: 0x%08lX\n",
Mbi.BaseAddress,
Mbi.RegionSize,
EstadoTexto(Mbi.State),
TipoTexto(Mbi.Type),
Mbi.Protect);
}
// Saltamos al final de esta región = inicio de la siguiente
pDireccion = (PBYTE)Mbi.BaseAddress + Mbi.RegionSize;
}
CloseHandle(hProceso);
return0;
}
Protección
PAGE_NOACCESS: Nada: cualquier acceso da error
PAGE_READONLY (R): Solo leer
PAGE_READWRITE (RW): Leer y escribir (datos normales)
PAGE_EXECUTE_READ (RX): Leer y ejecutar (código normal)
PAGE_EXECUTE_READWRITE (RWX): Todo
PAGE_GUARD (modificador): Alarma de un solo uso
Tipo
MEM_PRIVATE: memoria solo de ese proceso. Incluye lo que reservas con VirtualAlloc, el heap y la pila.
MEM_MAPPED: viene de una sección mapeada que no es un ejecutable, por ejemplo con CreateFileMapping + MapViewOfFile. Puede compartirse entre procesos. El módulo lo retoma más adelante con Mapping Injection.
MEM_IMAGE: viene de un .exe o .dll cargado. Cada sección del PE se mapea con sus permisos: .text (el código) como RX, las de datos como RW, etc.
Protecciones de Windows
DEP (Data Execution Prevention): Windows no deja ejecutar código en zonas marcadas solo para datos, si un atacante ejecuta código en zona RW se cuelga el programa
ASLR (Address Space Layout Randomization): Cada vez que aranca un programa. Windows coloca las cosas en direcciones distintas. Es como si cada día cambiaran los números de las calles. Muchos ataques necesitan saber exactamente dónde está algo en memoria; con ASLR esa dirección cambia, así que el atacante no puede apuntar a ella sin antes averiguarla.