> Windows Syscalls
ntoskrnl.exeT1055.012T1055T1106

NtUnmapViewOfSection

Desmapea una vista de sección previamente mapeada del espacio de direcciones de un proceso.

Prototipo

NTSTATUS NtUnmapViewOfSection(
  HANDLE ProcessHandle,
  PVOID  BaseAddress
);

Argumentos

NameTypeDirDescription
ProcessHandleHANDLEinHandle al proceso cuya vista se desmapea. Requiere PROCESS_VM_OPERATION.
BaseAddressPVOIDinDirecció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 WindowsID de syscallBuild
Win10 15070x2Awin10-1507
Win10 16070x2Awin10-1607
Win10 17030x2Awin10-1703
Win10 17090x2Awin10-1709
Win10 18030x2Awin10-1803
Win10 18090x2Awin10-1809
Win10 19030x2Awin10-1903
Win10 19090x2Awin10-1909
Win10 20040x2Awin10-2004
Win10 20H20x2Awin10-20h2
Win10 21H10x2Awin10-21h1
Win10 21H20x2Awin10-21h2
Win10 22H20x2Awin10-22h2
Win11 21H20x2Awin11-21h2
Win11 22H20x2Awin11-22h2
Win11 23H20x2Awin11-23h2
Win11 24H20x2Awin11-24h2
Server 20160x2Awinserver-2016
Server 20190x2Awinserver-2019
Server 20220x2Awinserver-2022
Server 20250x2Awinserver-2025

Módulo del kernel

ntoskrnl.exeNtUnmapViewOfSection

APIs relacionadas

UnmapViewOfFileUnmapViewOfFile2NtMapViewOfSectionNtMapViewOfSectionExNtUnmapViewOfSectionExNtCreateSection

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 ENDP

cProcess 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