> Windows Syscalls
ntoskrnl.exeT1106T1070

NtMakeTemporaryObject

Efface l'attribut OBJ_PERMANENT pour que l'objet noyau soit libéré dès la fermeture du dernier handle.

Prototype

NTSTATUS NtMakeTemporaryObject(
  HANDLE Handle
);

Arguments

NameTypeDirDescription
HandleHANDLEinHandle vers un objet noyau nommé portant actuellement l'attribut OBJ_PERMANENT.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070xFEwin10-1507
Win10 16070x103win10-1607
Win10 17030x107win10-1703
Win10 17090x108win10-1709
Win10 18030x109win10-1803
Win10 18090x109win10-1809
Win10 19030x10Awin10-1903
Win10 19090x10Awin10-1909
Win10 20040x10Fwin10-2004
Win10 20H20x10Fwin10-20h2
Win10 21H10x10Fwin10-21h1
Win10 21H20x110win10-21h2
Win10 22H20x110win10-22h2
Win11 21H20x116win11-21h2
Win11 22H20x117win11-22h2
Win11 23H20x117win11-23h2
Win11 24H20x119win11-24h2
Server 20160x103winserver-2016
Server 20190x109winserver-2019
Server 20220x115winserver-2022
Server 20250x119winserver-2025

Module noyau

ntoskrnl.exeNtMakeTemporaryObject

APIs liées

NtMakePermanentObjectNtCloseNtOpenSectionNtOpenEvent

Stub du syscall

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

Notes non documentées

Pendant strict de `NtMakePermanentObject` : appelle `ObSetPermanentObject(object, FALSE)` et lâche la référence supplémentaire qu'Ob retenait pour garder l'objet vivant au-delà du handle-count zéro. L'accès requis sur le handle est `DELETE`. Ne *requiert pas* `SeCreatePermanentPrivilege` — reconvertir un objet permanent en temporaire est asymétrique en ce sens. Une fois retiré, le noyau vérifie s'il reste des handles ou références ; sinon, l'objet entre immédiatement dans la file de suppression différée. Surtout utilisé par les chemins d'arrêt de service (ex. csrss démontant les objets nommés de portée session) et par Win32 lui-même quand `CloseHandle` est la dernière opération sur ce qui était à l'origine un objet `OBJ_PERMANENT` créé par un processus désormais sorti.

Usage courant par les malwares

Faible signal malware. Deux apparitions à noter : (1) **utilitaires de cleanup forensic / EDR** l'appellent pour recycler les objets permanents rogue laissés par des payloads précédents — `WinObj` lui-même utilise ce chemin quand on clique droit sur un objet permanent et qu'on choisit Make Temporary, puis Close. (2) Certains designs d'implant l'utilisent défensivement pour *détruire* leurs propres objets de staging avant la sortie, refusant au défenseur la chance de les dumper post-mortem — ex. une section permanente a servi à passer un payload à un helper d'intégrité supérieure, le helper l'a consommé, puis l'implant émet `NtMakeTemporaryObject` suivi de `NtClose` pour s'assurer qu'aucun résidu ne reste dans `\BaseNamedObjects`. L'appel est par ailleurs inerte.

Opportunités de détection

Aucun événement ETW dédié. Examiner les *conséquences* — disparition des objets nommés attendus dans `\BaseNamedObjects` — est plus pratique qu'alerter sur ce syscall. Corréler les événements de fermeture de handle d'objet noyau avec le nommage d'objet pour repérer les objets nommés qui disparaissent avant que leur service propriétaire ne soit censé s'arrêter. La paire `NtMakePermanentObject` (ou création avec `OBJ_PERMANENT`) suivie de `NtMakeTemporaryObject` depuis le même processus dans une courte fenêtre est le pattern canonique de stage-IPC-puis-wipe.

Exemples de syscalls directs

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 ENDP

cForensic-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
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20