NtQueryInformationProcess
Liest eine Informationsklasse über einen Prozess aus — universelles Back-End von GetProcessInformation und Arbeitspferd vieler Anti-Debug-Checks.
Prototyp
NTSTATUS NtQueryInformationProcess( HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle auf den Zielprozess. Erforderlicher Zugriff hängt von der Klasse ab (oft PROCESS_QUERY_LIMITED_INFORMATION). |
| ProcessInformationClass | PROCESSINFOCLASS | in | Enum, der die Informationsklasse wählt. Bemerkenswert: ProcessBasicInformation=0, ProcessDebugPort=7, ProcessWow64Information=26, ProcessImageFileName=27, ProcessDebugObjectHandle=30, ProcessDebugFlags=31, ProcessProtectionInformation=61. |
| ProcessInformation | PVOID | out | Vom Aufrufer bereitgestellter Puffer, der die Klassendaten empfängt. Layout variiert je Klasse. |
| ProcessInformationLength | ULONG | in | Größe des ProcessInformation-Puffers in Bytes. |
| ReturnLength | PULONG | out | Optionaler Zeiger, der die Anzahl geschriebener (bzw. bei STATUS_INFO_LENGTH_MISMATCH benötigter) Bytes empfängt. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x19 | win10-1507 |
| Win10 1607 | 0x19 | win10-1607 |
| Win10 1703 | 0x19 | win10-1703 |
| Win10 1709 | 0x19 | win10-1709 |
| Win10 1803 | 0x19 | win10-1803 |
| Win10 1809 | 0x19 | win10-1809 |
| Win10 1903 | 0x19 | win10-1903 |
| Win10 1909 | 0x19 | win10-1909 |
| Win10 2004 | 0x19 | win10-2004 |
| Win10 20H2 | 0x19 | win10-20h2 |
| Win10 21H1 | 0x19 | win10-21h1 |
| Win10 21H2 | 0x19 | win10-21h2 |
| Win10 22H2 | 0x19 | win10-22h2 |
| Win11 21H2 | 0x19 | win11-21h2 |
| Win11 22H2 | 0x19 | win11-22h2 |
| Win11 23H2 | 0x19 | win11-23h2 |
| Win11 24H2 | 0x19 | win11-24h2 |
| Server 2016 | 0x19 | winserver-2016 |
| Server 2019 | 0x19 | winserver-2019 |
| Server 2022 | 0x19 | winserver-2022 |
| Server 2025 | 0x19 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 19 00 00 00 mov eax, 0x19 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
Undokumentierte Hinweise
NtQueryInformationProcess ist einer der am stärksten überladenen Syscalls in Windows: über 100 PROCESSINFOCLASS-Werte sind in modernen Builds definiert, von harmlos (ProcessTimes=4, ProcessHandleCount=20) bis tief sicherheitsrelevant (ProcessDebugPort=7, ProcessDebugObjectHandle=30, ProcessDebugFlags=31, ProcessMitigationPolicy=52, ProcessProtectionInformation=61, ProcessImageFileName=27). Die SSN selbst ist seit Windows 10 1507 felsenfest 0x19 — Microsoft hat diesen Slot bewusst gehalten, weil sehr viel In-Tree- und Drittanbieter-Code ihn aufruft. Der Klassennummern-Raum hingegen ändert sich häufig; in 24H2 hinzugefügte Werte fehlen in 1809 und liefern auf älteren Kerneln STATUS_INVALID_INFO_CLASS.
Häufige Malware-Nutzung
Die meistgerufene Anti-Debug-Primitive in Windows. ProcessDebugPort (7) liefert ein Nicht-Null-Handle, wenn ein User-Mode-Debugger angebunden ist — genutzt von NTDLL-basierten IsDebuggerPresent-Ersätzen und den meisten kommerziellen Protectors (VMProtect, Themida, Enigma). ProcessDebugObjectHandle (30) liefert das DebugObject direkt — nötig, weil erfahrene Analysten den Legacy-DebugPort nullen. ProcessDebugFlags (31) liefert die Inverse von NoDebugInherit; ein gelesener Wert 0 bedeutet, dass irgendwann ein Debugger angebunden war. Kombiniert: ein Muster von drei aufeinanderfolgenden NtQueryInformationProcess-Aufrufen mit Klassen 7, 30, 31 gegen NtCurrentProcess() ist ein nahezu sicherer Anti-Debug-Fingerabdruck. Loader nutzen außerdem ProcessBasicInformation (0), um das PEB zu erhalten und geladene Module zu durchlaufen, ohne das offensichtliche LdrEnumerateLoadedModules anzufassen; ProcessImageFileName (27) für Sandbox-/Emulator-Namensprüfungen.
Erkennungsmöglichkeiten
Das Volumen ist riesig — dieser Syscall feuert ständig im Normalbetrieb, rohe Zählungen sind nutzlos. Unterscheidung kommt aus (a) der verwendeten Klasse, (b) dem Ziel-Handle (selbst vs. remote) und (c) der Aufrufsequenz. ETW Microsoft-Windows-Kernel-Audit-API-Calls bringt die Klasse *nicht* hoch — nötig ist ein User-Mode-Shim (ntdll-Inline-Hook, ETW-Provider pro Klasse) oder ein Kernel-Callback. Faustregel: jeder Prozess, der die Klassen 7, 30, 31 in enger Abfolge auf sich selbst aufruft, betreibt Anti-Debug. EDRs, die das interessieren, instrumentieren den Dispatch üblicherweise per Instrumentation-Callbacks (PsSetLoadImageNotifyRoutine + NtSetInformationProcess(ProcessInstrumentationCallback)) oder per TI-ETW EtwTiLogReadWriteVm-artigen Hooks auf benachbarten Operationen.
Direkte Syscall-Beispiele
cTriple-class anti-debug check
// The canonical anti-debug fingerprint: classes 7, 30, 31 against self.
HANDLE hProc = NtCurrentProcess();
DWORD_PTR debugPort = 0;
HANDLE debugObj = NULL;
ULONG debugFlags = 0;
ULONG ret;
NtQueryInformationProcess(hProc, ProcessDebugPort, &debugPort, sizeof(debugPort), &ret);
NtQueryInformationProcess(hProc, ProcessDebugObjectHandle, &debugObj, sizeof(debugObj), &ret);
NtQueryInformationProcess(hProc, ProcessDebugFlags, &debugFlags, sizeof(debugFlags), &ret);
if (debugPort != 0 || debugObj != NULL || debugFlags == 0) {
// Debugger present (or has been). Bail.
NtTerminateProcess(hProc, 0);
}cPEB walk via ProcessBasicInformation
PROCESS_BASIC_INFORMATION pbi = { 0 };
ULONG ret;
NtQueryInformationProcess(NtCurrentProcess(),
ProcessBasicInformation,
&pbi, sizeof(pbi), &ret);
PPEB peb = pbi.PebBaseAddress;
// Now walk peb->Ldr->InMemoryOrderModuleList to enumerate modules
// without calling LdrEnumerateLoadedModules / EnumProcessModules.asmx64 stub (stable across builds)
; SSN 0x19 — stable Win10 1507 .. Win11 24H2.
NtQueryInformationProcess PROC
mov r10, rcx
mov eax, 19h
syscall
ret
NtQueryInformationProcess ENDPMITRE ATT&CK-Mappings
Last verified: 2026-05-20