NtMakeTemporaryObject
Löscht das Attribut OBJ_PERMANENT, sodass das Kernel-Objekt freigegeben wird, sobald das letzte Handle schließt.
Prototyp
NTSTATUS NtMakeTemporaryObject( HANDLE Handle );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| Handle | HANDLE | in | Handle auf ein benanntes Kernel-Objekt, das aktuell das Attribut OBJ_PERMANENT trägt. |
Syscall-IDs pro 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-Modul
Verwandte 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
Undokumentierte Hinweise
Striktes Gegenstück zu `NtMakePermanentObject`: ruft `ObSetPermanentObject(object, FALSE)` und gibt die zusätzliche Referenz frei, die Ob hielt, um das Objekt über Handle-Count null hinaus am Leben zu halten. Erforderlicher Zugriff auf das Handle: `DELETE`. Erfordert *kein* `SeCreatePermanentPrivilege` — die Rückwandlung eines permanenten Objekts in ein temporäres ist insofern asymmetrisch. Nach Entfernen prüft der Kernel, ob noch Handles oder Referenzen bestehen; falls nicht, geht das Objekt sofort in die Deferred-Delete-Queue. Hauptsächlich genutzt von Service-Shutdown-Pfaden (z. B. csrss baut Session-scope-benannte Objekte ab) und von Win32 selbst, wenn `CloseHandle` die letzte Operation auf einem ursprünglich mit `OBJ_PERMANENT` erzeugten Objekt eines mittlerweile beendeten Prozesses ist.
Häufige Malware-Nutzung
Geringes Malware-Signal. Zwei nennenswerte Vorkommen: (1) **Forensik-/EDR-Cleanup-Utilities** rufen es auf, um rogue permanente Objekte, die frühere Payloads hinterlassen haben, einzusammeln — `WinObj` selbst nutzt diesen Pfad, wenn man auf einem permanenten Objekt Make Temporary und dann Close wählt. (2) Einige Implant-Designs nutzen es defensiv, um eigene Staging-Objekte vor dem Beenden zu *zerstören* und Defendern die Möglichkeit zu nehmen, sie post-mortem zu dumpen — z. B. wurde eine permanente Section genutzt, um ein Payload an einen Higher-Integrity-Helper zu reichen, der Helper hat es konsumiert, und das Implant setzt dann `NtMakeTemporaryObject` gefolgt von `NtClose` ab, um sicherzustellen, dass in `\BaseNamedObjects` kein Rest verbleibt. Der Aufruf ist ansonsten inert.
Erkennungsmöglichkeiten
Kein dediziertes ETW-Event. Die *Folgen* zu prüfen — Verschwinden erwarteter benannter Objekte in `\BaseNamedObjects` — ist praktischer als auf diesen Syscall zu alarmieren. Kernel-Object-Handle-Close-Events mit Objekt-Naming korrelieren, um benannte Objekte zu finden, die verschwinden, bevor ihr Owner-Service eigentlich heruntergefahren werden soll. Die Paarung `NtMakePermanentObject` (oder Erzeugung mit `OBJ_PERMANENT`) gefolgt von `NtMakeTemporaryObject` aus demselben Prozess in einem kurzen Zeitfenster ist das kanonische Stage-IPC-und-Wipe-Muster.
Direkte Syscall-Beispiele
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