NtCreateSectionEx
Crea un objeto sección con parámetros extendidos (nodo NUMA, requisitos de dirección, páginas físicas de usuario).
Prototipo
NTSTATUS NtCreateSectionEx( PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER MaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle, PMEM_EXTENDED_PARAMETER ExtendedParameters, ULONG ExtendedParameterCount );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| SectionHandle | PHANDLE | out | Recibe un handle al nuevo objeto sección. |
| DesiredAccess | ACCESS_MASK | in | Máscara de acceso: SECTION_MAP_READ / SECTION_MAP_WRITE / SECTION_MAP_EXECUTE / SECTION_ALL_ACCESS. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Nombre y descriptor de seguridad opcionales. NULL para una sección anónima (uso típico in-process). |
| MaximumSize | PLARGE_INTEGER | in | Requerido para secciones respaldadas por pagefile; opcional (se usa el tamaño del archivo) para secciones de archivo. |
| SectionPageProtection | ULONG | in | Protección a nivel de página aplicada a las vistas mapeadas: PAGE_READONLY / PAGE_READWRITE / PAGE_EXECUTE_READ / PAGE_EXECUTE_READWRITE / PAGE_WRITECOPY. |
| AllocationAttributes | ULONG | in | SEC_COMMIT / SEC_RESERVE / SEC_IMAGE / SEC_IMAGE_NO_EXECUTE / SEC_LARGE_PAGES / SEC_FILE / SEC_NOCACHE / SEC_WRITECOMBINE. |
| FileHandle | HANDLE | in | Handle de archivo opcional para secciones respaldadas por archivo; NULL para pagefile. |
| ExtendedParameters | PMEM_EXTENDED_PARAMETER | in | Array de entradas MEM_EXTENDED_PARAMETER: MemExtendedParameterNumaNode, MemExtendedParameterUserPhysicalHandle, MemExtendedParameterAddressRequirements (layouts resistentes a ASLR), MemExtendedParameterImageMachine (Win11 ARM64EC). |
| ExtendedParameterCount | ULONG | in | Número de entradas en ExtendedParameters; 0 hace que se comporte como NtCreateSection clásico. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1809 | 0xB9 | win10-1809 |
| Win10 1903 | 0xBA | win10-1903 |
| Win10 1909 | 0xBA | win10-1909 |
| Win10 2004 | 0xBE | win10-2004 |
| Win10 20H2 | 0xBE | win10-20h2 |
| Win10 21H1 | 0xBE | win10-21h1 |
| Win10 21H2 | 0xBF | win10-21h2 |
| Win10 22H2 | 0xBF | win10-22h2 |
| Win11 21H2 | 0xC3 | win11-21h2 |
| Win11 22H2 | 0xC4 | win11-22h2 |
| Win11 23H2 | 0xC4 | win11-23h2 |
| Win11 24H2 | 0xC6 | win11-24h2 |
| Server 2019 | 0xB9 | winserver-2019 |
| Server 2022 | 0xC2 | winserver-2022 |
| Server 2025 | 0xC6 | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 C6 00 00 00 mov eax, 0xC6 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
Introducido en Windows 10 RS5 (1809) — de ahí la ausencia de SSNs previos a 1809. `NtCreateSectionEx` extiende el clásico `NtCreateSection` con un array `PMEM_EXTENDED_PARAMETER` que expone la misma familia de atributos usada por `VirtualAlloc2` / `MapViewOfFile3` / `NtAllocateVirtualMemoryEx`: ubicación NUMA, respaldo AWE (páginas físicas de usuario), requisitos de dirección (alineación + límites bajo/alto, usados por allocators CFG-aware y por el loader ARM64EC de Win11) y override de máquina de imagen. El handler de kernel es `MmCreateSection` (o `MmCreateSpecialImageSection` para rutas `SEC_IMAGE`), alcanzado vía `MiCreateSectionCommon`. Los allocators modernos en `ntdll.dll` / `RtlpHpHeapManager` usan cada vez más la variante Ex para aprovechar los requisitos de dirección.
Uso común por malware
Dos casos de uso reales. (1) **Variantes Phantom DLL Hollowing / Process Doppelgänging** que necesitan una sección respaldada por un archivo transaccionado, eliminado o `SEC_IMAGE_NO_EXECUTE` a veces prefieren la forma Ex para especificar un requisito de dirección que coincida con la imagen legítima que están vaciando — colocando la imagen maliciosa exactamente en la base esperada por el loader. (2) **Loaders de shellcode que esquivan CFG / XFG** usan `MemExtendedParameterAddressRequirements` con un `LowestStartingAddress` alto para aterrizar lejos de los mapeos canónicos `KnownDlls`, escapando a escáneres ingenuos que solo recorren la mitad baja del espacio de direcciones. Ninguno es muy común — la mayoría de loaders aún apuntan al `NtCreateSection` clásico porque funciona en todo build soportado, mientras que `NtCreateSectionEx` no está disponible en Server 2016 / Win10 1703-1803.
Oportunidades de detección
Misma postura que `NtCreateSection`: el syscall mismo es muy voluminoso (cada `LoadLibrary` de una DLL aún no conocida acaba pasando por él en builds modernos), así que detectar la *combinación*. Sysmon Event ID 7 (ImageLoad) mostrando una imagen cuyo archivo de respaldo está en `%TEMP%`, `%PROGRAMDATA%`, o en estado transaccionado / pending-delete es la señal fuerte. EDRs que hookean específicamente `NtCreateSectionEx` pueden marcar el raro override `MemExtendedParameterImageMachine` en hosts x64 como anómalo — binarios ARM64EC legítimos en x64 son prácticamente inexistentes.
Ejemplos de syscalls directos
asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtCreateSectionEx (SSN 0xC6 on Win11 24H2)
NtCreateSectionEx PROC
mov r10, rcx ; SectionHandle
mov eax, 0C6h ; SSN — drifts per build
syscall
ret
NtCreateSectionEx ENDPcPagefile-backed section pinned above 0x0000_7000_0000_0000
// CFG-resilient layout: force the section to map high in the address space.
#include <windows.h>
#include <winternl.h>
typedef enum {
MemExtendedParameterAddressRequirements = 1,
} MEM_EXTENDED_PARAMETER_TYPE;
typedef struct _MEM_ADDRESS_REQUIREMENTS {
PVOID LowestStartingAddress;
PVOID HighestEndingAddress;
SIZE_T Alignment;
} MEM_ADDRESS_REQUIREMENTS, *PMEM_ADDRESS_REQUIREMENTS;
typedef struct DECLSPEC_ALIGN(8) _MEM_EXTENDED_PARAMETER {
struct { DWORD64 Type : 8; DWORD64 Reserved : 56; };
union { DWORD64 ULong64; PVOID Pointer; SIZE_T Size;
HANDLE Handle; DWORD ULong; };
} MEM_EXTENDED_PARAMETER, *PMEM_EXTENDED_PARAMETER;
typedef NTSTATUS (NTAPI *pNtCreateSectionEx)(
PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PLARGE_INTEGER,
ULONG, ULONG, HANDLE, PMEM_EXTENDED_PARAMETER, ULONG);
HANDLE MakeHighSection(SIZE_T bytes) {
HANDLE h = NULL;
LARGE_INTEGER size; size.QuadPart = (LONGLONG)bytes;
MEM_ADDRESS_REQUIREMENTS req = {
.LowestStartingAddress = (PVOID)0x00007F0000000000ULL,
.HighestEndingAddress = (PVOID)0x00007FFFFFFFFFFFULL,
.Alignment = 0,
};
MEM_EXTENDED_PARAMETER ep = {0};
ep.Type = MemExtendedParameterAddressRequirements;
ep.Pointer = &req;
pNtCreateSectionEx fn = (pNtCreateSectionEx)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtCreateSectionEx");
if (!fn) return NULL; // pre-1809 — fall back to NtCreateSection
fn(&h, SECTION_ALL_ACCESS, NULL, &size,
PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL, &ep, 1);
return h;
}rustwindows-sys: MapViewOfFile3 fast path (the high-level wrapper)
// MapViewOfFile3 in kernelbase.dll resolves to NtMapViewOfSectionEx, which
// pairs naturally with NtCreateSectionEx for end-to-end extended-parameter use.
use windows_sys::Win32::System::Memory::{MapViewOfFile3,
FILE_MAP_ALL_ACCESS, MEM_EXTENDED_PARAMETER};
unsafe fn map_high(section: isize, bytes: usize) -> *mut core::ffi::c_void {
let mut params: [MEM_EXTENDED_PARAMETER; 0] = [];
MapViewOfFile3(section, 0,
core::ptr::null_mut(),
0, bytes, 0,
FILE_MAP_ALL_ACCESS,
params.as_mut_ptr(), 0)
}Mapeos MITRE ATT&CK
Last verified: 2026-05-20