NtQuerySection
Recupera metadatos básicos o específicos de imagen de un section object.
Prototipo
NTSTATUS NtQuerySection( HANDLE SectionHandle, SECTION_INFORMATION_CLASS SectionInformationClass, PVOID SectionInformation, SIZE_T SectionInformationLength, PSIZE_T ResultLength );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| SectionHandle | HANDLE | in | Handle al section object, requiriendo acceso SECTION_QUERY. |
| SectionInformationClass | SECTION_INFORMATION_CLASS | in | Enum de clase de info: SectionBasicInformation = 0 (BaseAddress, AllocationAttributes, MaximumSize), SectionImageInformation = 1 (IMAGE_INFORMATION completo: EntryPoint, StackReserve/Commit, ImageType, Machine, CheckSum, ...), SectionRelocationInformation = 2, SectionOriginalBaseInformation = 3. |
| SectionInformation | PVOID | out | Buffer proporcionado por el llamador que recibe la estructura SECTION_BASIC_INFORMATION o SECTION_IMAGE_INFORMATION. |
| SectionInformationLength | SIZE_T | in | Tamaño en bytes del buffer SectionInformation. |
| ResultLength | PSIZE_T | out | Opcional; recibe el tamaño realmente escrito o requerido. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | 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 |
Módulo del kernel
APIs relacionadas
Stub del syscall
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
Notas no documentadas
SSN `0x51` en todos los builds de Windows 10 / 11 / Server — perfectamente estable, lo que lo convierte en un objetivo seguro de SSN hardcodeado. No hay wrapper Win32 público; los consumidores van por el nombre Nt o por el `ZwQuerySection` no documentado. `SectionBasicInformation` retorna un `SECTION_BASIC_INFORMATION { PVOID BaseAddress; ULONG AllocationAttributes; LARGE_INTEGER MaximumSize; }` — los AllocationAttributes portan flags SEC_IMAGE / SEC_COMMIT / SEC_RESERVE / SEC_NOCACHE / SEC_LARGE_PAGES. `SectionImageInformation` retorna un `SECTION_IMAGE_INFORMATION` mucho más grande que refleja el PE OPTIONAL_HEADER (entry point, stack/heap reserve/commit, subsistema, machine, checksum, características de imagen) — equivalente a lo que `LdrQueryImageFileExecutionOptions` aprende del disco más las decisiones de resolución del loader.
Uso común por malware
La primitiva de fingerprint en loaders de **unhooking**. Un flujo típico: abrir el `ntdll.dll` en disco (`NtCreateFile`), envolverlo como sección SEC_IMAGE (`NtCreateSection`), llamar `NtQuerySection(SectionImageInformation)` para aprender el `BaseOfCode` / `SizeOfCode` / `EntryPoint` limpios de la imagen de disco, mapear la sección read-only (`NtMapViewOfSection`), luego comparar byte a byte el `.text` limpio contra el `.text` del ntdll hookeado en memoria para identificar hooks inline instalados por el EDR, finalmente sobrescribiendo los bytes hookeados desde la copia limpia. Variantes hacen lo mismo contra `kernel32.dll`, `kernelbase.dll` y `win32u.dll`. Herramientas que usan este patrón incluyen Perun's Fart, RefleXXion, Hell's Hall, el plugin unhooker Adwind/jRAT, varios UDRL de Cobalt Strike y los PoC públicos que vienen con la mayoría de cursos red-team. Uso secundario: evasión forense — poner a cero los campos SECTION_IMAGE_INFORMATION.GpValue / CheckSum de un PE inyectado antes de un mapeo posterior para vencer detecciones de anomalía PE ingenuas.
Oportunidades de detección
Por sí solo, NtQuerySection es ordinario — el loader de Windows y el runtime CLR lo llaman constantemente durante la carga de DLL. La detección debe ser contextual. La firma de unhooker: un proceso que acaba de abrir `\Device\HarddiskVolumeN\Windows\System32\ntdll.dll`, lo mapeó como SEC_IMAGE, consultó SectionImageInformation, luego emitió `NtProtectVirtualMemory` seguido de `NtWriteVirtualMemory` contra el `.text` de su propio ntdll cargado — esa es la cadena de unhook inconfundible. Los EDR kernel-mode (WdFilter de Defender, CSAgent de CrowdStrike, el sensor kernel MsSense de MDE) detectan el paso *NtProtect/NtWrite-a-DLL-sistema* en lugar de NtQuerySection en sí, razón por la que la mayoría de autores de unhooker esperan plenamente que la llamada sea invisible y confían en que el resto de la cadena se mantenga bajo el radar. ETW Threat Intelligence sacará a la luz la escritura `.text` en sistemas PG-protegidos.
Ejemplos de syscalls directos
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;
}Mapeos MITRE ATT&CK
Last verified: 2026-05-20