NtUnmapViewOfSection
Desmapea una vista de sección previamente mapeada del espacio de direcciones de un proceso.
Prototipo
NTSTATUS NtUnmapViewOfSection( HANDLE ProcessHandle, PVOID BaseAddress );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle al proceso cuya vista se desmapea. Requiere PROCESS_VM_OPERATION. |
| BaseAddress | PVOID | in | Dirección base de la vista a desmapear. Debe coincidir con el valor retornado por NtMapViewOfSection. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0x2A | win10-1507 |
| Win10 1607 | 0x2A | win10-1607 |
| Win10 1703 | 0x2A | win10-1703 |
| Win10 1709 | 0x2A | win10-1709 |
| Win10 1803 | 0x2A | win10-1803 |
| Win10 1809 | 0x2A | win10-1809 |
| Win10 1903 | 0x2A | win10-1903 |
| Win10 1909 | 0x2A | win10-1909 |
| Win10 2004 | 0x2A | win10-2004 |
| Win10 20H2 | 0x2A | win10-20h2 |
| Win10 21H1 | 0x2A | win10-21h1 |
| Win10 21H2 | 0x2A | win10-21h2 |
| Win10 22H2 | 0x2A | win10-22h2 |
| Win11 21H2 | 0x2A | win11-21h2 |
| Win11 22H2 | 0x2A | win11-22h2 |
| Win11 23H2 | 0x2A | win11-23h2 |
| Win11 24H2 | 0x2A | win11-24h2 |
| Server 2016 | 0x2A | winserver-2016 |
| Server 2019 | 0x2A | winserver-2019 |
| Server 2022 | 0x2A | winserver-2022 |
| Server 2025 | 0x2A | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 2A 00 00 00 mov eax, 0x2A F6 04 25 08 03 FE 7F 01 test byte ptr [0x7FFE0308], 1 75 03 jne short +3 0F 05 syscall C3 ret CD 2E int 2Eh C3 ret
Notas no documentadas
NtUnmapViewOfSection mantiene el SSN `0x2A` en todos los builds de Windows 10 / 11 / Server observados. NtUnmapViewOfSectionEx (añadido en Win10 1809) es un syscall distinto que acepta un parámetro Flags. Internamente la llamada despacha vía MmUnmapViewOfSection y recorre el árbol VAD del proceso objetivo para localizar la entrada SECTION_OBJECT_POINTERS — eso hace tan confiable la primitiva de hollowing: desmapear la imagen principal del propio proceso está soportado y no requiere más privilegio que un handle PROCESS_VM_OPERATION.
Uso común por malware
Piedra angular del process hollowing (T1055.012). La receta clásica: CreateProcess(target, CREATE_SUSPENDED) → NtQueryInformationProcess para obtener la base de imagen del PEB → NtUnmapViewOfSection sobre esa base → NtAllocateVirtualMemory en la base original (preferida) → escribir las secciones de la imagen maliciosa → ajustar SetThreadContext RIP/RAX/EAX → ResumeThread. Stuxnet, Dridex, Hancitor, FormBook, Agent Tesla y droppers modernos como SmokeLoader y Amadey entregan variantes. NtUnmapViewOfSection también se usa post-inyección para borrar la vista de una DLL de EDR de un proceso host, de modo que futuras LoadLibrary toquen una copia limpia sin hooks inline.
Oportunidades de detección
Un NtUnmapViewOfSection cross-process con ProcessHandle != propio es raro en software legítimo (rutas de detach del depurador y unos pocos gestores de runtimes side-by-side, poco más). Sysmon Event ID 25 (`ProcessTampering: Image is replaced`) apunta explícitamente al patrón unmap-luego-alloc del hollowing. El proveedor ETW Threat Intelligence emite eventos de modificación de imagen de proceso desde Win10 RS5 que se disparan al desmapear la imagen ejecutable principal. Correlacionar con un proceso hijo cuya imagen en disco difiera de la imagen en memoria (comparar la ruta del módulo con el encabezado de sección en ImageBaseAddress del PEB).
Ejemplos de syscalls directos
asmx64 direct stub
; Direct syscall stub for NtUnmapViewOfSection (SSN 0x2A, all builds)
NtUnmapViewOfSection PROC
mov r10, rcx ; syscall convention
mov eax, 2Ah ; SSN
syscall
ret
NtUnmapViewOfSection ENDPcProcess hollowing skeleton
// Classic RunPE / process hollowing skeleton. Error handling omitted.
#include <windows.h>
#include <winternl.h>
typedef NTSTATUS (NTAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
void Hollow(LPCWSTR target, PVOID malicious_image, SIZE_T image_size,
PVOID preferred_base) {
STARTUPINFOW si = { sizeof si };
PROCESS_INFORMATION pi;
CreateProcessW(target, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED,
NULL, NULL, &si, &pi);
// Resolve PEB->ImageBaseAddress of the suspended child.
PROCESS_BASIC_INFORMATION pbi;
NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation,
&pbi, sizeof pbi, NULL);
PVOID remote_base;
ReadProcessMemory(pi.hProcess,
(BYTE*)pbi.PebBaseAddress + 0x10, // ImageBaseAddress
&remote_base, sizeof remote_base, NULL);
// Tear down the legitimate image mapping.
pNtUnmapViewOfSection NtUnmap = (pNtUnmapViewOfSection)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection");
NtUnmap(pi.hProcess, remote_base);
// Re-allocate at preferred base and copy the malicious image, then
// patch the new entry point into the suspended thread's CONTEXT.
// (Section copy + relocations + SetThreadContext + ResumeThread omitted.)
}rustntapi safe wrapper
// Cargo: ntapi = "0.4", windows-sys = "0.59"
use ntapi::ntmmapi::NtUnmapViewOfSection;
use windows_sys::Win32::Foundation::HANDLE;
pub unsafe fn unmap_image(proc_handle: HANDLE, base: *mut core::ffi::c_void)
-> Result<(), i32>
{
let status = NtUnmapViewOfSection(proc_handle, base);
if status >= 0 { Ok(()) } else { Err(status) }
}Mapeos MITRE ATT&CK
Last verified: 2026-05-20