NtAccessCheckByTypeResultListAndAuditAlarm
Typed access check returning a per-type result list, while writing audit-alarm entries to the Security event log.
Prototype
NTSTATUS NtAccessCheckByTypeResultListAndAuditAlarm( 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 GrantedAccessList, PNTSTATUS AccessStatusList, PBOOLEAN GenerateOnClose );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| SubsystemName | PUNICODE_STRING | in | Subsystem identifier, e.g. L"Security". Stored in every emitted audit event. |
| HandleId | PVOID | in | Opaque correlation handle ID surfaced in the audit event. |
| ObjectTypeName | PUNICODE_STRING | in | Top-level object type name, e.g. L"DS-Object", L"File". |
| ObjectName | PUNICODE_STRING | in | Object instance name (DN, path, kernel-object name) recorded in the audit event. |
| SecurityDescriptor | PSECURITY_DESCRIPTOR | in | Security descriptor with DACL + SACL — both are consulted (DACL for access, SACL for audit). |
| PrincipalSelfSid | PSID | in | Optional SID substituted for PRINCIPAL_SELF placeholders in the DACL/SACL. |
| DesiredAccess | ACCESS_MASK | in | Access rights to evaluate per object-type-list entry. |
| AuditType | AUDIT_EVENT_TYPE | in | AuditEventObjectAccess or AuditEventDirectoryServiceAccess — picks the audit category. |
| Flags | ULONG | in | Reserved / behavior modifiers (e.g. AUDIT_ALLOW_NO_PRIVILEGE). |
| ObjectTypeList | POBJECT_TYPE_LIST | in | Hierarchy-flattened list of types (object + property sets + properties). |
| ObjectTypeListLength | ULONG | in | Number of ObjectTypeList entries; sizes the two output arrays. |
| GenericMapping | PGENERIC_MAPPING | in | Per-type GENERIC_* -> specific-rights mapping. |
| ObjectCreation | BOOLEAN | in | TRUE for object creation (logged as create), FALSE for opening an existing object. |
| GrantedAccessList | PACCESS_MASK | out | Per-entry granted access masks. |
| AccessStatusList | PNTSTATUS | out | Per-entry NTSTATUS (STATUS_SUCCESS / STATUS_ACCESS_DENIED). |
| GenerateOnClose | PBOOLEAN | out | TRUE if the caller must later invoke NtCloseObjectAuditAlarm to emit the matching close event. |
Syscall IDs by Windows version
| Windows version | Syscall ID | Build |
|---|---|---|
| Win10 1507 | 0x65 | win10-1507 |
| Win10 1607 | 0x65 | win10-1607 |
| Win10 1703 | 0x65 | win10-1703 |
| Win10 1709 | 0x65 | win10-1709 |
| Win10 1803 | 0x65 | win10-1803 |
| Win10 1809 | 0x65 | win10-1809 |
| Win10 1903 | 0x65 | win10-1903 |
| Win10 1909 | 0x65 | win10-1909 |
| Win10 2004 | 0x65 | win10-2004 |
| Win10 20H2 | 0x65 | win10-20h2 |
| Win10 21H1 | 0x65 | win10-21h1 |
| Win10 21H2 | 0x65 | win10-21h2 |
| Win10 22H2 | 0x65 | win10-22h2 |
| Win11 21H2 | 0x65 | win11-21h2 |
| Win11 22H2 | 0x65 | win11-22h2 |
| Win11 23H2 | 0x65 | win11-23h2 |
| Win11 24H2 | 0x65 | win11-24h2 |
| Server 2016 | 0x65 | winserver-2016 |
| Server 2019 | 0x65 | winserver-2019 |
| Server 2022 | 0x65 | winserver-2022 |
| Server 2025 | 0x65 | winserver-2025 |
Kernel module
Related APIs
Syscall stub
4C 8B D1 mov r10, rcx B8 65 00 00 00 mov eax, 0x65 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
Undocumented notes
Among the longest-prototype syscalls in the Native API — 15 arguments, owing to the combination of typed access checking (object + property-set hierarchy) with audit-alarm emission. It is the union of NtAccessCheckByTypeResultList (result vector) and NtAccessCheckByTypeAndAuditAlarm (audit emission). Used almost exclusively by ntdsa.dll inside lsass.exe to evaluate Active Directory object reads/writes where the result must be both per-property-set AND logged. The SACL of the AD object drives whether any Security event 4662 ("An operation was performed on an object") is emitted; the per-entry decision drives whether the operation is rejected. SSN `0x65` has been stable since Windows 10 1507.
Common malware usage
Essentially zero. The function is too specialized — caller must marshal a valid OBJECT_TYPE_LIST, hold SeAuditPrivilege, and every successful call generates a 4662 in the Security log. Commodity malware does the opposite: it either bypasses access checks entirely (token theft via NtImpersonateThread + SeDebugPrivilege) or, on a DC, abuses Replication Get-Changes-All via legitimate RPC paths (DCSync) so the SACL evaluation happens on ntdsa's behalf with logs going to the *defenders*. No in-the-wild malware family is known to invoke this syscall directly.
Detection opportunities
This syscall is the engine behind Active Directory object-access auditing (Event 4662, 4663, 4690). Defenders should ensure Advanced Audit Policy `Audit Directory Service Access` and `Audit Directory Service Changes` are enabled on every domain controller, with SACLs configured on sensitive containers (Domain NC head, AdminSDHolder, Krbtgt account). A sudden drop in 4662 volume on a DC, especially during otherwise-busy hours, is a strong signal of audit subsystem tampering (T1562.002) — possibly via NtFlushKey on the Eventlog hive, registry edits to SACL, or driver-based SRM hooks.
Direct syscall examples
asmx64 direct stub
; Direct syscall stub for NtAccessCheckByTypeResultListAndAuditAlarm (SSN 0x65)
NtAccessCheckByTypeResultListAndAuditAlarm PROC
mov r10, rcx ; syscall convention
mov eax, 65h ; SSN
syscall
ret
NtAccessCheckByTypeResultListAndAuditAlarm ENDPcWin32 wrapper (advapi32)
// AccessCheckByTypeResultListAndAuditAlarmW marshals OBJECT_TYPE_LIST_W and
// dispatches to the Nt-level entry point.
UNICODE_STRING sub = RTL_CONSTANT_STRING(L"Security");
UNICODE_STRING tname= RTL_CONSTANT_STRING(L"DS-Object");
UNICODE_STRING oname= RTL_CONSTANT_STRING(L"CN=krbtgt,CN=Users,DC=contoso,DC=com");
ACCESS_MASK granted[2] = {0};
NTSTATUS statuses[2] = {STATUS_ACCESS_DENIED, STATUS_ACCESS_DENIED};
BOOLEAN gen_on_close = FALSE;
NTSTATUS rc = NtAccessCheckByTypeResultListAndAuditAlarm(
&sub,
(PVOID)0xABCD1234,
&tname, &oname,
pSd, NULL,
READ_CONTROL | ADS_RIGHT_DS_READ_PROP,
AuditEventDirectoryServiceAccess,
0,
pObjectTypeList, 2,
&g_DsGenericMapping,
FALSE,
granted, statuses,
&gen_on_close);
// Each successful entry emits a 4662 carrying the object DN and the GUID
// of the property set evaluated.rustwindows-sys Win32 advapi32 wrapper
// AccessCheckByTypeResultListAndAuditAlarmW in windows-sys::Win32::Security::Authorization.
use windows_sys::Win32::Security::Authorization::*;
use windows_sys::Win32::Security::*;
unsafe {
let mut granted = [0u32; 2];
let mut status = [0i32; 2];
let mut gen_on_close: i32 = 0;
let rc = AccessCheckByTypeResultListAndAuditAlarmW(
windows_sys::w!("Security"),
handle_id as *mut _,
windows_sys::w!("DS-Object"),
windows_sys::w!("CN=krbtgt,CN=Users,DC=contoso,DC=com"),
sd_ptr, std::ptr::null_mut(),
ADS_RIGHT_DS_READ_PROP.0 as u32 | READ_CONTROL,
otl.as_ptr(), otl.len() as u32,
0, // ObjectCreation == FALSE
granted.as_mut_ptr(), status.as_mut_ptr(),
&mut gen_on_close,
);
}MITRE ATT&CK mappings
Last verified: 2026-05-20