NtCreateSectionEx
Crée un objet section avec des paramètres étendus (nœud NUMA, contraintes d'adresse, pages physiques utilisateur).
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 | Reçoit un handle vers le nouvel objet section. |
| DesiredAccess | ACCESS_MASK | in | Masque d'accès : SECTION_MAP_READ / SECTION_MAP_WRITE / SECTION_MAP_EXECUTE / SECTION_ALL_ACCESS. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Nom et descripteur de sécurité optionnels. NULL pour une section anonyme (usage in-process typique). |
| MaximumSize | PLARGE_INTEGER | in | Requis pour les sections adossées au pagefile ; optionnel (taille du fichier utilisée) pour les sections fichier. |
| SectionPageProtection | ULONG | in | Protection au niveau page appliquée aux vues mappées : 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 fichier optionnel pour les sections adossées à un fichier ; NULL pour le pagefile. |
| ExtendedParameters | PMEM_EXTENDED_PARAMETER | in | Tableau d'entrées MEM_EXTENDED_PARAMETER : MemExtendedParameterNumaNode, MemExtendedParameterUserPhysicalHandle, MemExtendedParameterAddressRequirements (layouts résistants à ASLR), MemExtendedParameterImageMachine (Win11 ARM64EC). |
| ExtendedParameterCount | ULONG | in | Nombre d'entrées dans ExtendedParameters ; 0 fait se comporter comme NtCreateSection classique. |
IDs de syscalls par version de Windows
| Version 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 |
Module noyau
APIs liées
Stub du 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
Notes non documentées
Introduit dans Windows 10 RS5 (1809) — d'où l'absence de SSNs antérieurs à 1809. `NtCreateSectionEx` étend le classique `NtCreateSection` avec un tableau `PMEM_EXTENDED_PARAMETER` qui expose la même famille d'attributs utilisée par `VirtualAlloc2` / `MapViewOfFile3` / `NtAllocateVirtualMemoryEx` : placement NUMA, backing AWE (pages physiques utilisateur), contraintes d'adresse (alignement + bornes basse/haute, utilisées par les allocateurs CFG-aware et par le loader Win11 ARM64EC) et override de machine d'image. Le handler noyau est `MmCreateSection` (ou `MmCreateSpecialImageSection` pour les chemins `SEC_IMAGE`), atteint via `MiCreateSectionCommon`. Les allocateurs modernes dans `ntdll.dll` / `RtlpHpHeapManager` utilisent de plus en plus la variante Ex pour exploiter les contraintes d'adresse.
Usage courant par les malwares
Deux cas d'usage réels. (1) **Variantes Phantom DLL Hollowing / Process Doppelgänging** qui ont besoin d'une section adossée à un fichier transacté, supprimé ou `SEC_IMAGE_NO_EXECUTE` préfèrent parfois la forme Ex pour spécifier une contrainte d'adresse qui coïncide avec l'image légitime qu'elles creusent — plaçant l'image malicieuse exactement à la base attendue par le loader. (2) **Loaders de shellcode esquivant CFG / XFG** utilisent `MemExtendedParameterAddressRequirements` avec un `LowestStartingAddress` élevé pour atterrir loin des mappages canoniques `KnownDlls`, échappant aux scanners naïfs qui ne parcourent que la moitié basse de l'espace d'adressage. Aucun n'est très courant — la plupart des loaders ciblent encore le `NtCreateSection` classique car il fonctionne sur chaque build supporté, alors que `NtCreateSectionEx` est indisponible sur Server 2016 / Win10 1703-1803.
Opportunités de détection
Même posture que `NtCreateSection` : le syscall lui-même est très volumineux (chaque `LoadLibrary` d'une DLL non encore connue finit par y passer sur les builds récents), donc détecter la *combinaison*. Sysmon Event ID 7 (ImageLoad) montrant une image dont le fichier source est dans `%TEMP%`, `%PROGRAMDATA%`, ou en état transacté / pending-delete est le signal fort. Les EDR qui hookent spécifiquement `NtCreateSectionEx` peuvent marquer l'override rare `MemExtendedParameterImageMachine` sur des hôtes x64 comme anormal — les binaires ARM64EC légitimes sur x64 sont quasi inexistants.
Exemples de syscalls directs
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)
}Mappings MITRE ATT&CK
Last verified: 2026-05-20