> Windows Syscalls
ntoskrnl.exeT1069T1087T1106

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

NameTypeDirDescription
HandleHANDLEinHandle auf ein beliebiges sicherbares Objekt (Datei, Registry-Schlüssel, Prozess, Token, Named Pipe usw.), geöffnet mit READ_CONTROL.
SecurityInformationSECURITY_INFORMATIONinBitmaske der zu lesenden Bestandteile: OWNER_SECURITY_INFORMATION | GROUP_ | DACL_ | SACL_ | LABEL_ | ATTRIBUTE_.
SecurityDescriptorPSECURITY_DESCRIPTORoutVom Aufrufer allokierter Puffer, der den self-relativen Security Descriptor empfängt.
LengthULONGinGröße von SecurityDescriptor in Bytes.
LengthNeededPULONGoutEmpfängt die tatsächlich geschriebene Größe oder die bei STATUS_BUFFER_TOO_SMALL benötigte Größe.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070x142win10-1507
Win10 16070x148win10-1607
Win10 17030x14Ewin10-1703
Win10 17090x151win10-1709
Win10 18030x153win10-1803
Win10 18090x154win10-1809
Win10 19030x155win10-1903
Win10 19090x155win10-1909
Win10 20040x15Bwin10-2004
Win10 20H20x15Bwin10-20h2
Win10 21H10x15Bwin10-21h1
Win10 21H20x15Cwin10-21h2
Win10 22H20x15Cwin10-22h2
Win11 21H20x163win11-21h2
Win11 22H20x166win11-22h2
Win11 23H20x166win11-23h2
Win11 24H20x168win11-24h2
Server 20160x148winserver-2016
Server 20190x154winserver-2019
Server 20220x161winserver-2022
Server 20250x168winserver-2025

Kernel-Modul

ntoskrnl.exeNtQuerySecurityObject

Verwandte APIs

GetSecurityInfoGetKernelObjectSecurityGetUserObjectSecurityGetFileSecurityWNtSetSecurityObjectNtAccessCheck

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.

Erkennungs­mö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 ENDP

rustRead 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