NtCreateSectionEx
Creates a section object with extended parameters (NUMA node, address-requirements, user-physical pages).
Prototype
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 );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| SectionHandle | PHANDLE | out | Receives a handle to the new section object. |
| DesiredAccess | ACCESS_MASK | in | Access mask: SECTION_MAP_READ / SECTION_MAP_WRITE / SECTION_MAP_EXECUTE / SECTION_ALL_ACCESS. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Optional name + security descriptor. NULL for an unnamed section (typical for in-process use). |
| MaximumSize | PLARGE_INTEGER | in | Required for pagefile-backed sections; optional (file size used) for file-backed sections. |
| SectionPageProtection | ULONG | in | Page-level protection applied to mapped views: 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 | Optional file handle for file-backed sections; NULL for pagefile-backed sections. |
| ExtendedParameters | PMEM_EXTENDED_PARAMETER | in | Array of MEM_EXTENDED_PARAMETER entries: MemExtendedParameterNumaNode, MemExtendedParameterUserPhysicalHandle, MemExtendedParameterAddressRequirements (for ASLR-resistant layouts), MemExtendedParameterImageMachine (Win11 ARM64EC). |
| ExtendedParameterCount | ULONG | in | Number of entries in ExtendedParameters; 0 makes this behave like classic NtCreateSection. |
Syscall IDs by Windows version
| Windows version | Syscall ID | 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 |
Kernel module
Related APIs
Syscall stub
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
Undocumented notes
Introduced in Windows 10 RS5 (1809) — note the absence of pre-1809 SSNs. `NtCreateSectionEx` extends the classic `NtCreateSection` with a `PMEM_EXTENDED_PARAMETER` array that exposes the same family of attributes used by `VirtualAlloc2` / `MapViewOfFile3` / `NtAllocateVirtualMemoryEx`: NUMA node placement, AWE (user-physical) backing, address-requirements (alignment + low/high bounds, used by CFG-aware allocators and by the Win11 ARM64EC loader), and image-machine override. The kernel handler is `MmCreateSection` (or `MmCreateSpecialImageSection` for `SEC_IMAGE` paths), reached through `MiCreateSectionCommon`. Modern allocators in `ntdll.dll` / `RtlpHpHeapManager` increasingly use the Ex variant to take advantage of address-requirements.
Common malware usage
Two real use cases. (1) **Phantom DLL Hollowing / Process Doppelgänging variants** that need a section backed by a transacted, deleted, or `SEC_IMAGE_NO_EXECUTE` file occasionally prefer the Ex form to specify an address-requirement that collides with the legitimate image they're hollowing — placing the malicious image at the exact base address the loader expects. (2) **CFG / XFG-evading shellcode loaders** use `MemExtendedParameterAddressRequirements` with a high `LowestStartingAddress` to land far away from canonical `KnownDlls` mappings so naïve scanners that walk only the low half of the address space miss the payload. Neither use case is particularly common — most loaders still target the classic `NtCreateSection` because it works on every supported build, whereas `NtCreateSectionEx` is unavailable on Server 2016 / Win10 1703-1803.
Detection opportunities
Same posture as `NtCreateSection`: the syscall itself is high-volume (every `LoadLibrary` of a not-yet-known DLL on modern builds eventually reaches it), so detect the *combination*. Sysmon Event ID 7 (ImageLoad) showing a loaded image whose backing file is in `%TEMP%`, `%PROGRAMDATA%`, or a transacted/pending-delete state is the strong signal. EDRs that hook `NtCreateSectionEx` specifically can flag the rare `MemExtendedParameterImageMachine` override on x64 hosts as anomalous — legitimate ARM64EC binaries on x64 are essentially nonexistent.
Direct syscall examples
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)
}MITRE ATT&CK mappings
Last verified: 2026-05-20