NtMakeTemporaryObject
Clears the OBJ_PERMANENT attribute so the kernel object is freed once its last handle closes.
Prototype
NTSTATUS NtMakeTemporaryObject( HANDLE Handle );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| Handle | HANDLE | in | Handle to a named kernel object that currently carries the OBJ_PERMANENT attribute. |
Syscall IDs by Windows version
| Windows version | Syscall ID | Build |
|---|---|---|
| Win10 1507 | 0xFE | win10-1507 |
| Win10 1607 | 0x103 | win10-1607 |
| Win10 1703 | 0x107 | win10-1703 |
| Win10 1709 | 0x108 | win10-1709 |
| Win10 1803 | 0x109 | win10-1803 |
| Win10 1809 | 0x109 | win10-1809 |
| Win10 1903 | 0x10A | win10-1903 |
| Win10 1909 | 0x10A | win10-1909 |
| Win10 2004 | 0x10F | win10-2004 |
| Win10 20H2 | 0x10F | win10-20h2 |
| Win10 21H1 | 0x10F | win10-21h1 |
| Win10 21H2 | 0x110 | win10-21h2 |
| Win10 22H2 | 0x110 | win10-22h2 |
| Win11 21H2 | 0x116 | win11-21h2 |
| Win11 22H2 | 0x117 | win11-22h2 |
| Win11 23H2 | 0x117 | win11-23h2 |
| Win11 24H2 | 0x119 | win11-24h2 |
| Server 2016 | 0x103 | winserver-2016 |
| Server 2019 | 0x109 | winserver-2019 |
| Server 2022 | 0x115 | winserver-2022 |
| Server 2025 | 0x119 | winserver-2025 |
Kernel module
Related APIs
Syscall stub
4C 8B D1 mov r10, rcx B8 19 01 00 00 mov eax, 0x119 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
Strict counterpart to `NtMakePermanentObject`: calls `ObSetPermanentObject(object, FALSE)` and drops the extra reference Ob held to keep the object alive past handle-count zero. Required access on the handle is `DELETE`. Does *not* require `SeCreatePermanentPrivilege` — converting a permanent object back to temporary is asymmetric in that sense. Once stripped, the kernel checks whether any handles or references remain; if not, the object enters the deferred-delete queue immediately. Mostly used by service shutdown paths (e.g. csrss tearing down session-scope named objects) and by Win32 itself when `CloseHandle` is the last operation on what was originally an `OBJ_PERMANENT` object created by a now-exited process.
Common malware usage
Low malware signal. Two appearances worth noting: (1) **forensic / EDR cleanup utilities** call it to reap rogue permanent objects left by previous payloads — `WinObj` itself uses this path when you right-click a permanent object and choose Make Temporary, then Close. (2) Some implant designs use it defensively to *destroy* their own staging objects before exit, denying a defender the chance to dump them post-mortem — e.g. a permanent section was used to hand a payload to a higher-integrity helper, the helper consumed it, and the implant then issues `NtMakeTemporaryObject` followed by `NtClose` to ensure no residue remains in `\BaseNamedObjects`. The call is otherwise inert.
Detection opportunities
No dedicated ETW event. Reviewing the *consequences* — disappearance of expected named objects from `\BaseNamedObjects` — is more practical than alerting on this syscall. Correlate kernel-object handle close events with object naming to spot named objects that vanish before their owning service is supposed to shut down. The pairing `NtMakePermanentObject` (or create-with-`OBJ_PERMANENT`) followed by `NtMakeTemporaryObject` from the same process within a short window is the canonical IPC-stage-and-wipe pattern.
Direct syscall examples
asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtMakeTemporaryObject (SSN 0x119 on Win11 24H2 / Server 2025)
NtMakeTemporaryObject PROC
mov r10, rcx ; syscall convention
mov eax, 119h ; SSN — drifts; resolve dynamically for portability
syscall
ret
NtMakeTemporaryObject ENDPcForensic-style reap of a rogue permanent object
// Cleanup pattern: open a permanent named event/section/mutex with DELETE
// access, strip OBJ_PERMANENT, then drop our handle so it's freed.
UNICODE_STRING name; RtlInitUnicodeString(&name, L"\\BaseNamedObjects\\Global\\__rogue__");
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL);
HANDLE h;
if (NT_SUCCESS(NtOpenEvent(&h, DELETE, &oa))) {
NtMakeTemporaryObject(h); // clear OBJ_PERMANENT
NtClose(h); // last close -> object freed
}MITRE ATT&CK mappings
Last verified: 2026-05-20