NtOpenProcessToken
Öffnet das einem Prozess zugeordnete Zugriffstoken und gibt ein Handle darauf zurück.
Prototyp
NTSTATUS NtOpenProcessToken( HANDLE ProcessHandle, ACCESS_MASK DesiredAccess, PHANDLE TokenHandle );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle auf den Prozess, dessen Token geöffnet wird. Muss PROCESS_QUERY_INFORMATION (oder PROCESS_QUERY_LIMITED_INFORMATION) besitzen. |
| DesiredAccess | ACCESS_MASK | in | Angeforderte Token-Rechte, z. B. TOKEN_QUERY (0x8), TOKEN_DUPLICATE (0x2), TOKEN_ADJUST_PRIVILEGES (0x20), TOKEN_ALL_ACCESS. |
| TokenHandle | PHANDLE | out | Erhält bei Erfolg das Handle auf das geöffnete Token. Muss mit NtClose geschlossen werden. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x114 | win10-1507 |
| Win10 1607 | 0x119 | win10-1607 |
| Win10 1703 | 0x11D | win10-1703 |
| Win10 1709 | 0x11F | win10-1709 |
| Win10 1803 | 0x121 | win10-1803 |
| Win10 1809 | 0x122 | win10-1809 |
| Win10 1903 | 0x123 | win10-1903 |
| Win10 1909 | 0x123 | win10-1909 |
| Win10 2004 | 0x128 | win10-2004 |
| Win10 20H2 | 0x128 | win10-20h2 |
| Win10 21H1 | 0x128 | win10-21h1 |
| Win10 21H2 | 0x129 | win10-21h2 |
| Win10 22H2 | 0x129 | win10-22h2 |
| Win11 21H2 | 0x12F | win11-21h2 |
| Win11 22H2 | 0x131 | win11-22h2 |
| Win11 23H2 | 0x131 | win11-23h2 |
| Win11 24H2 | 0x133 | win11-24h2 |
| Server 2016 | 0x119 | winserver-2016 |
| Server 2019 | 0x122 | winserver-2019 |
| Server 2022 | 0x12E | winserver-2022 |
| Server 2025 | 0x133 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 33 01 00 00 mov eax, 0x133 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
NtOpenProcessToken ist die historische Variante des Token-Öffnungs-Primitivs, aus Quellkompatibilität mit der ursprünglichen NT-API erhalten. Moderne Pfade in `kernel32!OpenProcessToken` rufen tatsächlich `NtOpenProcessTokenEx` mit `HandleAttributes = 0` auf. Der SSN driftet stark zwischen Builds — von `0x114` auf Windows 10 1507 bis `0x133` auf Windows 11 24H2 — was ihn zu einem schlechten Kandidaten für hartkodierte SSNs und zum Lehrbuchbeispiel für dynamische Auflösung über Hell's Gate / Halo's Gate macht. Intern dispatcht der Aufruf über `SeQueryAuthenticationIdToken` und `ObOpenObjectByPointer` gegen den EPROCESS->Token-Pointer.
Häufige Malware-Nutzung
Stets der erste Schritt in einer Token-Diebstahls-Kette: einen Prozess hoher Integrität (winlogon, services.exe, lsass.exe) mit `TOKEN_DUPLICATE | TOKEN_QUERY` öffnen, dann NtDuplicateToken aufrufen, um ein SecurityImpersonation-Token zu fälschen, und schließlich NtSetInformationThread (ThreadImpersonationToken) oder CreateProcessWithTokenW, um unter der gestohlenen Identität zu starten. Das ist das klassische Incognito-/Mimikatz-`token::elevate`-Muster und Grundlage der meisten Post-Exploitation-Lateral-Movement-Aktivitäten in Conti-, BlackCat- und APT29-Vorfällen.
Erkennungsmöglichkeiten
Das Öffnen eines Tokens auf einem fremden Prozess erfordert in den meisten Fällen SeDebugPrivilege — Windows-Security-Event 4672 (Special Privileges Assigned) auf der aufrufenden Logon-Session ist ein starker Vorbote. Event 4663 (Object Access) mit Objekttyp `Token` und 4673 (Sensitive Privilege Use) feuern, wenn die Operation gegen einen privilegierten Prozess erfolgreich ist. Der ETW-Provider `Microsoft-Windows-Kernel-Audit-API-Calls` emittiert `PsOpenProcessToken`-Events. EDRs hooken `ntdll!NtOpenProcessToken`; direkte Syscalls umgehen User-Mode-Hooks, der Kernel erzeugt jedoch weiterhin SE_TOKEN_USER-Object-Manager-Auditing auf geschützten Prozessen.
Direkte Syscall-Beispiele
asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtOpenProcessToken — SSN 0x133 on Win11 24H2
; NOTE: SSN varies across builds; resolve dynamically in production.
NtOpenProcessToken PROC
mov r10, rcx ; ProcessHandle
mov eax, 133h ; SSN (Win11 24H2)
syscall
ret
NtOpenProcessToken ENDPcToken-steal primer (open LSASS token, classic Incognito chain)
// Step 1 of an impersonation chain: open a privileged process token.
// Requires SeDebugPrivilege on the calling thread.
HANDLE hLsass = NULL, hToken = NULL;
OBJECT_ATTRIBUTES oa = { sizeof(oa) };
CLIENT_ID cid = { (HANDLE)(ULONG_PTR)lsassPid, NULL };
NTSTATUS s = NtOpenProcess(&hLsass,
PROCESS_QUERY_LIMITED_INFORMATION,
&oa, &cid);
if (NT_SUCCESS(s)) {
// TOKEN_DUPLICATE so we can later forge an impersonation token.
s = NtOpenProcessToken(hLsass,
TOKEN_DUPLICATE | TOKEN_QUERY,
&hToken);
// -> feed hToken into NtDuplicateToken -> NtSetInformationThread
}rustHell's Gate dynamic SSN lookup
// Resolve NtOpenProcessToken SSN at runtime — SSN moves every Windows build.
use std::arch::asm;
use std::ffi::CString;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::LibraryLoader::{GetModuleHandleA, GetProcAddress};
unsafe fn ssn_from_export(name: &str) -> u32 {
let ntdll = GetModuleHandleA(b"ntdll.dll\0".as_ptr());
let c = CString::new(name).unwrap();
let p = GetProcAddress(ntdll, c.as_ptr() as *const u8) as *const u8;
// Pattern: 4C 8B D1 B8 ?? ?? 00 00
assert_eq!(*p.add(0), 0x4C);
assert_eq!(*p.add(3), 0xB8);
(*p.add(4) as u32) | ((*p.add(5) as u32) << 8)
}
#[unsafe(naked)]
unsafe extern "system" fn syscall_thunk(
_process: HANDLE,
_desired: u32,
_token_out: *mut HANDLE,
_ssn: u32,
) -> i32 {
asm!(
"mov r10, rcx",
"mov eax, r9d", // SSN supplied as 4th arg
"syscall",
"ret",
options(noreturn),
);
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20