NtAccessCheckByTypeAndAuditAlarm
Realiza una comprobación de acceso tipada y registra una entrada de alarma de auditoría en el log de Seguridad.
Prototipo
NTSTATUS NtAccessCheckByTypeAndAuditAlarm( PUNICODE_STRING SubsystemName, PVOID HandleId, PUNICODE_STRING ObjectTypeName, PUNICODE_STRING ObjectName, PSECURITY_DESCRIPTOR SecurityDescriptor, PSID PrincipalSelfSid, ACCESS_MASK DesiredAccess, AUDIT_EVENT_TYPE AuditType, ULONG Flags, POBJECT_TYPE_LIST ObjectTypeList, ULONG ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, BOOLEAN ObjectCreation, PACCESS_MASK GrantedAccess, PNTSTATUS AccessStatus, PBOOLEAN GenerateOnClose );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| SubsystemName | PUNICODE_STRING | in | Identifica el subsistema que realiza la comprobación, p. ej. L"Security" o L"WinLogon". Se registra en el evento de auditoría. |
| HandleId | PVOID | in | Identificador opaco aportado por el llamante para el handle del objeto comprobado; aparece en el registro de auditoría para correlación. |
| ObjectTypeName | PUNICODE_STRING | in | Nombre de tipo legible (p. ej. L"File", L"RegistryKey") registrado en el evento de auditoría. |
| ObjectName | PUNICODE_STRING | in | Nombre de la instancia del objeto a registrar en el evento de auditoría, p. ej. la ruta del archivo. |
| SecurityDescriptor | PSECURITY_DESCRIPTOR | in | Descriptor de seguridad del objeto objetivo; la SACL impulsa la generación de auditoría. |
| PrincipalSelfSid | PSID | in | SID opcional sustituido por el marcador PRINCIPAL_SELF cuando el objeto representa un principal (p. ej. un objeto de usuario en AD). |
| DesiredAccess | ACCESS_MASK | in | Derechos de acceso solicitados por el llamante, contrastados con la DACL. |
| AuditType | AUDIT_EVENT_TYPE | in | AuditEventObjectAccess o AuditEventDirectoryServiceAccess — selecciona la categoría de auditoría. |
| Flags | ULONG | in | Reservado / modificadores de comportamiento (p. ej. AUDIT_ALLOW_NO_PRIVILEGE). |
| ObjectTypeList | POBJECT_TYPE_LIST | in | Lista jerárquica de tipos de objeto (p. ej. objeto AD + property sets) sobre los que se aplica la comprobación. |
| ObjectTypeListLength | ULONG | in | Número de entradas en ObjectTypeList. |
| GenericMapping | PGENERIC_MAPPING | in | Mapeo por tipo de objeto de GENERIC_READ/WRITE/EXECUTE/ALL a derechos específicos. |
| ObjectCreation | BOOLEAN | in | TRUE si la comprobación es para creación de objeto (registrado como CreateObject), FALSE para apertura de objeto existente. |
| GrantedAccess | PACCESS_MASK | out | Recibe la máscara de bits de los derechos de acceso realmente concedidos. |
| AccessStatus | PNTSTATUS | out | STATUS_SUCCESS si se concedió el acceso, STATUS_ACCESS_DENIED en caso contrario. El valor de retorno de la función reporta la validez de la llamada, no la decisión de acceso. |
| GenerateOnClose | PBOOLEAN | out | Se establece a TRUE cuando el kernel quiere también un evento de auditoría al cerrarse el handle; el llamante debe recordarlo y llamar a NtCloseObjectAuditAlarm más tarde. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0x59 | win10-1507 |
| Win10 1607 | 0x59 | win10-1607 |
| Win10 1703 | 0x59 | win10-1703 |
| Win10 1709 | 0x59 | win10-1709 |
| Win10 1803 | 0x59 | win10-1803 |
| Win10 1809 | 0x59 | win10-1809 |
| Win10 1903 | 0x59 | win10-1903 |
| Win10 1909 | 0x59 | win10-1909 |
| Win10 2004 | 0x59 | win10-2004 |
| Win10 20H2 | 0x59 | win10-20h2 |
| Win10 21H1 | 0x59 | win10-21h1 |
| Win10 21H2 | 0x59 | win10-21h2 |
| Win10 22H2 | 0x59 | win10-22h2 |
| Win11 21H2 | 0x59 | win11-21h2 |
| Win11 22H2 | 0x59 | win11-22h2 |
| Win11 23H2 | 0x59 | win11-23h2 |
| Win11 24H2 | 0x59 | win11-24h2 |
| Server 2016 | 0x59 | winserver-2016 |
| Server 2019 | 0x59 | winserver-2019 |
| Server 2022 | 0x59 | winserver-2022 |
| Server 2025 | 0x59 | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 59 00 00 00 mov eax, 0x59 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
Variante con auditoría de NtAccessCheckByType. La variante sin alarma devuelve la decisión de acceso y termina; esta además escribe una entrada de auditoría en el log de Seguridad si la SACL del objeto lo solicita (o si AuditType + Flags lo fuerzan). La función requiere SeAuditPrivilege — solo los llamantes que lo poseen (LSASS, el Security Reference Monitor, subsistemas kernel-mode) pueden invocarla útilmente. El SSN ha permanecido estable en `0x59` desde Windows 10 1507, lo cual es inusual pero consistente con que todos los syscalls `*AuditAlarm` preceden a las renumeraciones post-1909.
Uso común por malware
Insignificante. Por diseño, cada llamada exitosa produce una entrada en el log de Seguridad — lo opuesto a lo que quiere la mayoría del malware. Las pocas referencias in-the-wild son LSASS haciendo lo suyo (comportamiento legítimo de `lsass.exe` durante decisiones de acceso a objetos AD). Ninguna familia commodity es conocida por abusarlo. El ángulo defensivo interesante es la *ausencia* de llamadas audit-alarm esperadas cuando se toca un objeto bajo SACL, posible señal de que el atacante manipuló la SACL o el camino de dispatch del SRM.
Oportunidades de detección
Estas llamadas *son* el log de Seguridad para acceso a objetos. Los Event IDs 4656 (handle solicitado), 4658 (handle cerrado), 4660 (objeto eliminado), 4663 (intento de acceso), 4690 (handle duplicado) provienen todos de la familia NtAccessCheck*AuditAlarm + NtCloseObjectAuditAlarm + NtDeleteObjectAuditAlarm. Los defensores deben asegurar que las SACL en objetos de alto valor (proceso LSASS, contextos de nombrado AD, almacén de claves maestras DPAPI) están configuradas para activar comprobaciones audit-alarm, y tratar la ausencia de eventos esperados como señal de manipulación. El proveedor ETW Microsoft-Windows-Security-Auditing transporta los mismos datos con más detalle que el canal Eventlog heredado.
Ejemplos de syscalls directos
asmx64 direct stub
; Direct syscall stub for NtAccessCheckByTypeAndAuditAlarm (SSN 0x59, Win10 1507+)
; 16 args -> 4 in regs + 12 on stack per x64 calling convention.
NtAccessCheckByTypeAndAuditAlarm PROC
mov r10, rcx ; syscall convention
mov eax, 59h ; SSN
syscall
ret
NtAccessCheckByTypeAndAuditAlarm ENDPcLSASS-style audited check (illustrative)
// Sketch of how a SACL-monitored AD object access is dispatched inside LSASS.
// In production this is reached through AccessCheckByTypeAndAuditAlarmW;
// shown here against the Nt-level for clarity.
UNICODE_STRING subsystem = RTL_CONSTANT_STRING(L"Security");
UNICODE_STRING objectType = RTL_CONSTANT_STRING(L"DS-Object");
UNICODE_STRING objectName = RTL_CONSTANT_STRING(L"CN=Administrator,CN=Users,DC=contoso,DC=com");
ACCESS_MASK granted = 0;
NTSTATUS access_status = STATUS_ACCESS_DENIED;
BOOLEAN gen_on_close = FALSE;
NTSTATUS s = NtAccessCheckByTypeAndAuditAlarm(
&subsystem,
(PVOID)hHandleId,
&objectType,
&objectName,
pSd,
NULL,
READ_CONTROL | ADS_RIGHT_DS_READ_PROP,
AuditEventDirectoryServiceAccess,
0,
pObjectTypeList, objectTypeListCount,
&g_DsGenericMapping,
FALSE,
&granted,
&access_status,
&gen_on_close);
// On STATUS_SUCCESS, the SRM emitted Event 4662 ("An operation was performed on an
// object") into the Security log. If gen_on_close==TRUE remember to call
// NtCloseObjectAuditAlarm when releasing the handle.rustwindows-sys typed-access audit (advapi32 wrapper)
// The public Win32 wrapper is AccessCheckByTypeAndAuditAlarmW.
// windows-sys exposes it under Win32::Security::Authorization.
use windows_sys::Win32::Security::Authorization::AccessCheckByTypeAndAuditAlarmW;
use windows_sys::Win32::Security::*;
use windows_sys::core::PCWSTR;
unsafe {
let mut granted: u32 = 0;
let mut access_status: i32 = 0;
let mut gen_on_close: i32 = 0;
let rc = AccessCheckByTypeAndAuditAlarmW(
windows_sys::w!("Security"),
handle_id as *mut _,
windows_sys::w!("DS-Object"),
windows_sys::w!("CN=Administrator,..."),
sd_ptr,
std::ptr::null_mut(),
desired_access,
object_type_list.as_ptr(),
object_type_list.len() as u32,
0, // ObjectCreation == FALSE
&mut granted,
&mut access_status,
&mut gen_on_close,
);
// rc != 0 means the *call* succeeded; access_status == 0 means it was granted.
}Mapeos MITRE ATT&CK
Last verified: 2026-05-20