NtCloseObjectAuditAlarm
Emits the Security event-log entry that pairs with an earlier audit-alarm open, marking a handle's close.
Prototype
NTSTATUS NtCloseObjectAuditAlarm( PUNICODE_STRING SubsystemName, PVOID HandleId, BOOLEAN GenerateOnClose );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| SubsystemName | PUNICODE_STRING | in | Subsystem name, must match the value used in the original NtAccessCheck*AuditAlarm call. |
| HandleId | PVOID | in | Opaque handle ID used to correlate with the earlier open event. |
| GenerateOnClose | BOOLEAN | in | TRUE if the earlier NtAccessCheck*AuditAlarm call returned GenerateOnClose=TRUE; FALSE is a no-op. |
Syscall IDs by Windows version
| Windows version | Syscall ID | Build |
|---|---|---|
| Win10 1507 | 0x3B | win10-1507 |
| Win10 1607 | 0x3B | win10-1607 |
| Win10 1703 | 0x3B | win10-1703 |
| Win10 1709 | 0x3B | win10-1709 |
| Win10 1803 | 0x3B | win10-1803 |
| Win10 1809 | 0x3B | win10-1809 |
| Win10 1903 | 0x3B | win10-1903 |
| Win10 1909 | 0x3B | win10-1909 |
| Win10 2004 | 0x3B | win10-2004 |
| Win10 20H2 | 0x3B | win10-20h2 |
| Win10 21H1 | 0x3B | win10-21h1 |
| Win10 21H2 | 0x3B | win10-21h2 |
| Win10 22H2 | 0x3B | win10-22h2 |
| Win11 21H2 | 0x3B | win11-21h2 |
| Win11 22H2 | 0x3B | win11-22h2 |
| Win11 23H2 | 0x3B | win11-23h2 |
| Win11 24H2 | 0x3B | win11-24h2 |
| Server 2016 | 0x3B | winserver-2016 |
| Server 2019 | 0x3B | winserver-2019 |
| Server 2022 | 0x3B | winserver-2022 |
| Server 2025 | 0x3B | winserver-2025 |
Kernel module
Related APIs
Syscall stub
4C 8B D1 mov r10, rcx B8 3B 00 00 00 mov eax, 0x3B 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
Generates Security event 4658 ("The handle to an object was closed"). It must be invoked when a prior NtAccessCheck*AuditAlarm call returned GenerateOnClose=TRUE, so the open/close pair is correctly correlated in the Security log. The function is *not* called automatically by NtClose — the audited subsystem (LSASS, the SAM, the SCM, third-party SACL-aware services) is responsible for the bookkeeping. Missing close events for a known-open audited handle indicate either an unclean process exit (handle reaped by the kernel without subsystem notification) or active log tampering. SSN `0x3B` has been stable since Windows 10 1507.
Common malware usage
Effectively none. The syscall is a logging primitive — calling it adds Security-log entries, the opposite of what malware wants. No commodity family is observed invoking it. The interesting direction is the *missing* 4658: a 4656 (open) without its matching 4658 in the same session is a high-confidence indicator of audit-subsystem disruption (often via stopping the EventLog service or overflowing the channel with NtFlushKey + registry pressure).
Detection opportunities
Pair every 4656 (handle requested with SACL-monitored access) with a 4658 (handle closed). The lag distribution is dominated by short-lived handles (< 1s for files, < 100ms for registry keys). Persistent 4656-without-4658 on SACL'd objects (LSASS process, AdminSDHolder, Defender registry keys) is a strong tampering signal. Sysmon Event ID 13 (registry value set) and 16 (Sysmon config changed) plus EVENT_TRACE_FLAG_REGISTRY ETW give parallel telemetry that doesn't depend on the Security channel itself.
Direct syscall examples
asmx64 direct stub
; Direct syscall stub for NtCloseObjectAuditAlarm (SSN 0x3B, Win10 1507+)
NtCloseObjectAuditAlarm PROC
mov r10, rcx ; syscall convention
mov eax, 3Bh ; SSN
syscall
ret
NtCloseObjectAuditAlarm ENDPcPair with NtAccessCheckByTypeAndAuditAlarm
// Bookkeeping pattern used by SACL-aware services.
UNICODE_STRING sub = RTL_CONSTANT_STRING(L"Security");
BOOLEAN gen_on_close = FALSE;
ACCESS_MASK granted = 0;
NTSTATUS access_status = STATUS_ACCESS_DENIED;
NtAccessCheckByTypeAndAuditAlarm(
&sub, (PVOID)hHandleId,
&type_name, &obj_name,
pSd, NULL,
FILE_GENERIC_READ,
AuditEventObjectAccess, 0,
pObjectTypeList, otl_len,
&g_FileMapping, FALSE,
&granted, &access_status, &gen_on_close);
// ... use the handle ...
if (gen_on_close) {
NtCloseObjectAuditAlarm(&sub, (PVOID)hHandleId, TRUE);
// -> Security event 4658 with the same HandleId for correlation.
}
NtClose(hFile);rustWin32 ObjectCloseAuditAlarmW wrapper
use windows_sys::Win32::Security::Authorization::ObjectCloseAuditAlarmW;
unsafe {
let ok = ObjectCloseAuditAlarmW(
windows_sys::w!("Security"),
handle_id as *mut _,
gen_on_close as i32,
);
// ok != 0 -> 4658 emitted.
}MITRE ATT&CK mappings
Last verified: 2026-05-20