> Windows Syscalls
ntoskrnl.exeT1069T1087T1106

NtQuerySecurityObject

Recupera un SECURITY_DESCRIPTOR auto-relativo de cualquier objeto del kernel expuesto por un handle.

Prototipo

NTSTATUS NtQuerySecurityObject(
  HANDLE               Handle,
  SECURITY_INFORMATION SecurityInformation,
  PSECURITY_DESCRIPTOR SecurityDescriptor,
  ULONG                Length,
  PULONG               LengthNeeded
);

Argumentos

NameTypeDirDescription
HandleHANDLEinHandle a cualquier objeto asegurable (archivo, clave de registro, proceso, token, named pipe, etc.) abierto con READ_CONTROL.
SecurityInformationSECURITY_INFORMATIONinMáscara de bits de partes a obtener: OWNER_SECURITY_INFORMATION | GROUP_ | DACL_ | SACL_ | LABEL_ | ATTRIBUTE_.
SecurityDescriptorPSECURITY_DESCRIPTORoutBúfer asignado por el llamador que recibe el descriptor de seguridad auto-relativo.
LengthULONGinTamaño de SecurityDescriptor en bytes.
LengthNeededPULONGoutRecibe el tamaño realmente escrito, o el tamaño requerido en STATUS_BUFFER_TOO_SMALL.

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
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

Módulo del kernel

ntoskrnl.exeNtQuerySecurityObject

APIs relacionadas

GetSecurityInfoGetKernelObjectSecurityGetUserObjectSecurityGetFileSecurityWNtSetSecurityObjectNtAccessCheck

Stub del syscall

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

Notas no documentadas

Accesor universal a descriptores de seguridad para todos los tipos de objeto. Leer la SACL requiere SE_SECURITY_NAME (ACCESS_SYSTEM_SECURITY) — la mayoría de los llamadores omiten por tanto SACL_SECURITY_INFORMATION. Devuelve STATUS_BUFFER_TOO_SMALL con el tamaño requerido en LengthNeeded; el patrón estándar es una llamada sonda con Length=0 seguida de una asignación. Los wrappers Win32 GetSecurityInfo / GetKernelObjectSecurity / GetUserObjectSecurity acaban aquí.

Uso común por malware

Paso de reconocimiento que casi siempre precede a un SetSecurityObject — el implante lee el SDDL actual de un objetivo (clave de registro de servicio, fichero de tarea programada, directorio de instalación de EDR) para saber qué fusionar o quitar. También lo usan herramientas de descubrimiento de privilegios como el equivalente a Get-DomainObjectAcl de PowerSploit para detectar ACL débiles (p. ej. una clave de registro de servicio escribible por Authenticated Users) explotables sin tocar nada. En cadenas de robo de credenciales, NtQuerySecurityObject contra un handle de LSASS confirma qué privilegios y bits de acceso obtuvo realmente el operador.

Oportunidades de detección

Por sí solo, volumen extremadamente alto — cada diálogo Abrir, cada ventana Propiedades, cada prompt UAC lo invoca. La barra de detección es el *contexto*: NtQuerySecurityObject sobre `HKLM\SYSTEM\CurrentControlSet\Services\<EDR>` o sobre `lsass.exe` desde un proceso no confiable es interesante. La auditoría de acceso a objetos (Event 4663 con `Accesses: Read SD`) cubre la mayoría de los casos pero es ruidosa hasta ajustarla. Los EDR que median las aperturas fichero/proceso ven el READ_CONTROL del handle del que depende NtQuerySecurityObject. La detección estilo Bluespawn se centra en el SetSecurityObject *emparejado* que sigue.

Ejemplos de syscalls directos

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);
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20