NtQuerySecurityObject
Liest einen self-relativen SECURITY_DESCRIPTOR aus einem beliebigen Kernel-Objekt, das über ein Handle erreichbar ist.
Prototyp
NTSTATUS NtQuerySecurityObject( HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor, ULONG Length, PULONG LengthNeeded );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| Handle | HANDLE | in | Handle auf ein beliebiges sicherbares Objekt (Datei, Registry-Schlüssel, Prozess, Token, Named Pipe usw.), geöffnet mit READ_CONTROL. |
| SecurityInformation | SECURITY_INFORMATION | in | Bitmaske der zu lesenden Bestandteile: OWNER_SECURITY_INFORMATION | GROUP_ | DACL_ | SACL_ | LABEL_ | ATTRIBUTE_. |
| SecurityDescriptor | PSECURITY_DESCRIPTOR | out | Vom Aufrufer allokierter Puffer, der den self-relativen Security Descriptor empfängt. |
| Length | ULONG | in | Größe von SecurityDescriptor in Bytes. |
| LengthNeeded | PULONG | out | Empfängt die tatsächlich geschriebene Größe oder die bei STATUS_BUFFER_TOO_SMALL benötigte Größe. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x142 | win10-1507 |
| Win10 1607 | 0x148 | win10-1607 |
| Win10 1703 | 0x14E | win10-1703 |
| Win10 1709 | 0x151 | win10-1709 |
| Win10 1803 | 0x153 | win10-1803 |
| Win10 1809 | 0x154 | win10-1809 |
| Win10 1903 | 0x155 | win10-1903 |
| Win10 1909 | 0x155 | win10-1909 |
| Win10 2004 | 0x15B | win10-2004 |
| Win10 20H2 | 0x15B | win10-20h2 |
| Win10 21H1 | 0x15B | win10-21h1 |
| Win10 21H2 | 0x15C | win10-21h2 |
| Win10 22H2 | 0x15C | win10-22h2 |
| Win11 21H2 | 0x163 | win11-21h2 |
| Win11 22H2 | 0x166 | win11-22h2 |
| Win11 23H2 | 0x166 | win11-23h2 |
| Win11 24H2 | 0x168 | win11-24h2 |
| Server 2016 | 0x148 | winserver-2016 |
| Server 2019 | 0x154 | winserver-2019 |
| Server 2022 | 0x161 | winserver-2022 |
| Server 2025 | 0x168 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 68 01 00 00 mov eax, 0x168 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
Universeller Accessor für Security Descriptors aller Objekttypen. Das Lesen der SACL erfordert SE_SECURITY_NAME (ACCESS_SYSTEM_SECURITY) — die meisten Aufrufer lassen SACL_SECURITY_INFORMATION daher weg. Liefert STATUS_BUFFER_TOO_SMALL mit der benötigten Größe in LengthNeeded; das Standardmuster ist ein Probe-Aufruf mit Length=0 gefolgt von Allokation. Die Win32-Wrapper GetSecurityInfo / GetKernelObjectSecurity / GetUserObjectSecurity landen alle hier.
Häufige Malware-Nutzung
Recon-Schritt, der einem SetSecurityObject fast immer vorausgeht — der Implant liest die aktuelle SDDL eines Ziels (Service-Registry-Schlüssel, geplante Task-Datei, EDR-Installationsverzeichnis), um zu wissen, was zu mergen oder zu strippen ist. Auch genutzt von Privileg-Discovery-Tools wie dem PowerSploit-Get-DomainObjectAcl-Äquivalent, um schwache ACLs (z. B. ein für Authenticated Users beschreibbarer Service-Registry-Schlüssel) zu finden, die berührungsfrei ausgenutzt werden können. In Credential-Theft-Ketten bestätigt NtQuerySecurityObject gegen ein LSASS-Handle, welche Privilegien und Access-Bits der Operator tatsächlich erhalten hat.
Erkennungsmöglichkeiten
Für sich genommen extrem hohes Volumen — jeder Öffnen-Dialog, jedes Eigenschaften-Fenster, jeder UAC-Prompt ruft es auf. Die Detection-Hürde ist der *Kontext*: NtQuerySecurityObject auf `HKLM\SYSTEM\CurrentControlSet\Services\<EDR>` oder auf `lsass.exe` aus einem nicht vertrauenswürdigen Prozess ist interessant. Object-Access-Auditing (Event 4663 mit `Accesses: Read SD`) deckt die meisten Fälle ab, ist aber ungetunt laut. EDRs, die Datei-/Prozess-Opens vermitteln, sehen das READ_CONTROL auf dem Handle, von dem NtQuerySecurityObject abhängt. Bluespawn-artige Detection fokussiert auf das gepaarte folgende SetSecurityObject.
Direkte Syscall-Beispiele
cProbe-then-alloc pattern
// Read the DACL of a service registry key in two calls.
ULONG needed = 0;
NTSTATUS st = NtQuerySecurityObject(hSvcKey, DACL_SECURITY_INFORMATION,
NULL, 0, &needed);
if (st == STATUS_BUFFER_TOO_SMALL) {
PVOID sd = RtlAllocateHeap(RtlProcessHeap(), 0, needed);
st = NtQuerySecurityObject(hSvcKey, DACL_SECURITY_INFORMATION,
sd, needed, &needed);
// Now walk the DACL and decide what to weaken.
}asmx64 direct stub (Win11 24H2 SSN 0x168)
NtQuerySecurityObject PROC
mov r10, rcx
mov eax, 168h
syscall
ret
NtQuerySecurityObject ENDPrustRead DACL of EDR install dir before tampering
// Cargo: ntapi = "0.4", windows-sys = "0.59"
let mut needed: u32 = 0;
let st = unsafe {
NtQuerySecurityObject(h_dir,
DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
null_mut(), 0, &mut needed)
};
assert_eq!(st, STATUS_BUFFER_TOO_SMALL as i32);
let mut buf = vec![0u8; needed as usize];
unsafe {
NtQuerySecurityObject(h_dir,
DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
buf.as_mut_ptr() as _, buf.len() as u32, &mut needed);
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20