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
| Name | Type | Dir | Description |
|---|---|---|---|
| Handle | HANDLE | in | Handle vers un objet noyau nommé portant actuellement l'attribut OBJ_PERMANENT. |
IDs de syscalls par version de Windows
| Version de Windows | ID de syscall | 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 |
Module noyau
APIs liées
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 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
}Mappings MITRE ATT&CK
Last verified: 2026-05-20