NtQuerySection
Retrieves basic or image-specific metadata about a section object.
Prototype
NTSTATUS NtQuerySection( HANDLE SectionHandle, SECTION_INFORMATION_CLASS SectionInformationClass, PVOID SectionInformation, SIZE_T SectionInformationLength, PSIZE_T ResultLength );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| SectionHandle | HANDLE | in | Handle to the section object, requiring SECTION_QUERY access. |
| SectionInformationClass | SECTION_INFORMATION_CLASS | in | Info class enum: SectionBasicInformation = 0 (BaseAddress, AllocationAttributes, MaximumSize), SectionImageInformation = 1 (full IMAGE_INFORMATION: EntryPoint, StackReserve/Commit, ImageType, Machine, CheckSum, ...), SectionRelocationInformation = 2, SectionOriginalBaseInformation = 3. |
| SectionInformation | PVOID | out | Caller-supplied buffer receiving the SECTION_BASIC_INFORMATION or SECTION_IMAGE_INFORMATION structure. |
| SectionInformationLength | SIZE_T | in | Size in bytes of the SectionInformation buffer. |
| ResultLength | PSIZE_T | out | Optional; receives the size actually written or required. |
Syscall IDs by Windows version
| Windows version | Syscall ID | Build |
|---|---|---|
| Win10 1507 | 0x51 | win10-1507 |
| Win10 1607 | 0x51 | win10-1607 |
| Win10 1703 | 0x51 | win10-1703 |
| Win10 1709 | 0x51 | win10-1709 |
| Win10 1803 | 0x51 | win10-1803 |
| Win10 1809 | 0x51 | win10-1809 |
| Win10 1903 | 0x51 | win10-1903 |
| Win10 1909 | 0x51 | win10-1909 |
| Win10 2004 | 0x51 | win10-2004 |
| Win10 20H2 | 0x51 | win10-20h2 |
| Win10 21H1 | 0x51 | win10-21h1 |
| Win10 21H2 | 0x51 | win10-21h2 |
| Win10 22H2 | 0x51 | win10-22h2 |
| Win11 21H2 | 0x51 | win11-21h2 |
| Win11 22H2 | 0x51 | win11-22h2 |
| Win11 23H2 | 0x51 | win11-23h2 |
| Win11 24H2 | 0x51 | win11-24h2 |
| Server 2016 | 0x51 | winserver-2016 |
| Server 2019 | 0x51 | winserver-2019 |
| Server 2022 | 0x51 | winserver-2022 |
| Server 2025 | 0x51 | winserver-2025 |
Kernel module
Related APIs
Syscall stub
4C 8B D1 mov r10, rcx B8 51 00 00 00 mov eax, 0x51 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
SSN `0x51` on every Windows 10 / 11 / Server build — perfectly stable, making it a safe hardcoded-SSN target. There is no public Win32 wrapper; consumers go through the Nt name or the undocumented `ZwQuerySection`. `SectionBasicInformation` returns a `SECTION_BASIC_INFORMATION { PVOID BaseAddress; ULONG AllocationAttributes; LARGE_INTEGER MaximumSize; }` — the AllocationAttributes carries SEC_IMAGE / SEC_COMMIT / SEC_RESERVE / SEC_NOCACHE / SEC_LARGE_PAGES flags. `SectionImageInformation` returns a much larger `SECTION_IMAGE_INFORMATION` mirroring the PE OPTIONAL_HEADER (entry point, stack/heap reserve/commit, subsystem, machine, checksum, image characteristics) — equivalent to what `LdrQueryImageFileExecutionOptions` learns from disk plus the loader's resolution decisions.
Common malware usage
The fingerprint primitive in **unhooking** loaders. A typical flow: open the on-disk `ntdll.dll` (`NtCreateFile`), wrap it as an SEC_IMAGE section (`NtCreateSection`), call `NtQuerySection(SectionImageInformation)` to learn the clean `BaseOfCode` / `SizeOfCode` / `EntryPoint` for the disk image, map the section read-only (`NtMapViewOfSection`), then byte-compare the clean `.text` against the in-memory hooked ntdll's `.text` to identify EDR-installed inline hooks, finally overwriting the hooked bytes from the clean copy. Variants do the same against `kernel32.dll`, `kernelbase.dll`, and `win32u.dll`. Tools that use this pattern include Perun's Fart, RefleXXion, Hell's Hall, the Adwind/jRAT unhooker plugin, several Cobalt Strike UDRLs, and the public PoCs that ship with most red-team courses. A secondary use is forensic-evasion: zero out the SECTION_IMAGE_INFORMATION.GpValue / CheckSum fields of an injected PE before further mapping to defeat naive PE-anomaly detection.
Detection opportunities
By itself, NtQuerySection is ordinary — the Windows loader and CLR runtime call it constantly during DLL load. Detection has to be contextual. The unhooker signature: a process that has just opened `\Device\HarddiskVolumeN\Windows\System32\ntdll.dll`, mapped it as SEC_IMAGE, queried SectionImageInformation, then issued `NtProtectVirtualMemory` followed by `NtWriteVirtualMemory` against its own loaded ntdll's `.text` — that is the unmistakable unhook chain. Kernel-mode EDRs (Defender's WdFilter, CrowdStrike's CSAgent, MDE's MsSense kernel sensor) detect the *NtProtect/NtWrite-to-system-DLL* step rather than NtQuerySection itself, which is why most unhooker authors fully expect the call to be invisible and rely on the rest of the chain staying below the radar. ETW Threat Intelligence will surface the `.text` write on PG-protected systems.
Direct syscall examples
asmx64 direct stub
; Direct syscall stub for NtQuerySection (SSN 0x51, all builds)
NtQuerySection PROC
mov r10, rcx ; syscall convention
mov eax, 51h ; SSN
syscall
ret
NtQuerySection ENDPcUnhooker: get clean ntdll .text from disk
// Open disk ntdll, map as SEC_IMAGE, query its image info, then
// memcmp against the in-memory ntdll to spot EDR inline hooks.
#include <windows.h>
typedef struct _SECTION_IMAGE_INFORMATION {
PVOID TransferAddress;
ULONG ZeroBits;
SIZE_T MaximumStackSize;
SIZE_T CommittedStackSize;
ULONG SubSystemType;
USHORT SubSystemMinorVersion;
USHORT SubSystemMajorVersion;
ULONG GpValue;
USHORT ImageCharacteristics;
USHORT DllCharacteristics;
USHORT Machine;
BOOLEAN ImageContainsCode;
UCHAR ImageFlags;
ULONG LoaderFlags;
ULONG ImageFileSize;
ULONG CheckSum;
} SECTION_IMAGE_INFORMATION;
typedef NTSTATUS (NTAPI *pNtQuerySection)(HANDLE, ULONG, PVOID, SIZE_T, PSIZE_T);
NTSTATUS GetCleanImageInfo(HANDLE h_section, SECTION_IMAGE_INFORMATION *out) {
pNtQuerySection NtQuerySection = (pNtQuerySection)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtQuerySection");
SIZE_T ret = 0;
return NtQuerySection(h_section, /* SectionImageInformation */ 1,
out, sizeof *out, &ret);
}cBasic info: section size and attributes
// Cheap sanity check on a section we don't own: how big, what flags?
#include <windows.h>
typedef struct _SECTION_BASIC_INFORMATION {
PVOID BaseAddress;
ULONG AllocationAttributes; // SEC_IMAGE / SEC_COMMIT / ...
LARGE_INTEGER MaximumSize;
} SECTION_BASIC_INFORMATION;
typedef NTSTATUS (NTAPI *pNtQuerySection)(HANDLE, ULONG, PVOID, SIZE_T, PSIZE_T);
LONGLONG SectionSize(HANDLE h_section) {
pNtQuerySection NtQuerySection = (pNtQuerySection)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtQuerySection");
SECTION_BASIC_INFORMATION bi = {0};
SIZE_T ret = 0;
if (NtQuerySection(h_section, /* SectionBasicInformation */ 0,
&bi, sizeof bi, &ret) != 0) return -1;
return bi.MaximumSize.QuadPart;
}MITRE ATT&CK mappings
Last verified: 2026-05-20