> Windows Syscalls
ntoskrnl.exeT1622T1106

NtSetInformationObject

Sets handle-level attributes (inheritance, protect-from-close) on a kernel object handle.

Prototype

NTSTATUS NtSetInformationObject(
  HANDLE                   Handle,
  OBJECT_INFORMATION_CLASS ObjectInformationClass,
  PVOID                    ObjectInformation,
  ULONG                    ObjectInformationLength
);

Arguments

NameTypeDirDescription
HandleHANDLEinHandle whose attributes are to be modified.
ObjectInformationClassOBJECT_INFORMATION_CLASSinTypically ObjectHandleFlagInformation (4) — the only class accepted by NtSetInformationObject.
ObjectInformationPVOIDinPointer to OBJECT_HANDLE_FLAG_INFORMATION { BOOLEAN Inherit; BOOLEAN ProtectFromClose; }.
ObjectInformationLengthULONGinSize of the input buffer; sizeof(OBJECT_HANDLE_FLAG_INFORMATION) == 2.

Syscall IDs by Windows version

Windows versionSyscall IDBuild
Win10 15070x5Cwin10-1507
Win10 16070x5Cwin10-1607
Win10 17030x5Cwin10-1703
Win10 17090x5Cwin10-1709
Win10 18030x5Cwin10-1803
Win10 18090x5Cwin10-1809
Win10 19030x5Cwin10-1903
Win10 19090x5Cwin10-1909
Win10 20040x5Cwin10-2004
Win10 20H20x5Cwin10-20h2
Win10 21H10x5Cwin10-21h1
Win10 21H20x5Cwin10-21h2
Win10 22H20x5Cwin10-22h2
Win11 21H20x5Cwin11-21h2
Win11 22H20x5Cwin11-22h2
Win11 23H20x5Cwin11-23h2
Win11 24H20x5Cwin11-24h2
Server 20160x5Cwinserver-2016
Server 20190x5Cwinserver-2019
Server 20220x5Cwinserver-2022
Server 20250x5Cwinserver-2025

Kernel module

ntoskrnl.exeNtSetInformationObject

Related APIs

SetHandleInformationNtQueryObjectNtCloseNtDuplicateObject

Syscall stub

4C 8B D1            mov r10, rcx
B8 5C 00 00 00      mov eax, 0x5C
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

SSN `0x5C` is stable across every covered build. NtSetInformationObject only meaningfully accepts class **ObjectHandleFlagInformation (4)** with a 2-byte structure: two BOOLEANs, `Inherit` and `ProtectFromClose`. It is the kernel-side primitive behind Win32 `SetHandleInformation`. Flipping `ProtectFromClose=TRUE` causes subsequent NtClose calls on that handle to return STATUS_HANDLE_NOT_CLOSABLE without freeing the reference — the kernel still maintains the entry, and a subsequent re-flip back to FALSE allows close. Inherit only matters at CreateProcess time (handle goes into the child's table).

Common malware usage

Best known as the kill switch for the classic `NtClose(0xDEADBEEF) -> STATUS_INVALID_HANDLE` anti-debug probe: malware sets `ProtectFromClose` on its own real handles before defensively calling NtClose on them, so that even if a debugger pollutes the close path, the protected handles survive (Themida and VMProtect packers ship this trick). It is also part of the **anti-NtClose anti-debug counter-counter** — flipping `ProtectFromClose=TRUE` on a known-bad handle silences STATUS_INVALID_HANDLE under attached debuggers. More obscure use: handle-inheritance manipulation right before a CreateProcessAsUser to control exactly which handles leak into a sandboxed child (used by some sandbox-aware loaders to hand a privileged token down without granting the child PROCESS_DUP_HANDLE rights).

Detection opportunities

Very low call volume in legitimate software outside of Office, WSL, and console hosts. Sysmon does not currently log this syscall, but it is exposed via ETW Microsoft-Windows-Kernel-Audit-API-Calls and reachable from ObRegisterCallbacks. The high-value detection is **ProtectFromClose=TRUE applied to standard handles (0xFFFFFFFE/-1 = current process pseudo) or to handles inside a process whose parent process recently mapped ntdll suspiciously** — both are extreme outliers. Vendors also correlate ProtectFromClose flips immediately followed by NtClose calls that return non-zero (the anti-debug pattern).

Direct syscall examples

asmx64 direct stub

; Direct syscall stub for NtSetInformationObject (SSN 0x5C, all builds)
NtSetInformationObject PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 5Ch          ; SSN
    syscall
    ret
NtSetInformationObject ENDP

cProtect a handle from NtClose tampering

// Defeat NtClose-based anti-debug probes by marking the handle non-closable
// before any defensive NtClose() call.
#include <windows.h>

#define ObjectHandleFlagInformation 4

typedef struct _OBJECT_HANDLE_FLAG_INFORMATION {
    BOOLEAN Inherit;
    BOOLEAN ProtectFromClose;
} OBJECT_HANDLE_FLAG_INFORMATION;

typedef NTSTATUS (NTAPI *pNtSetInformationObject)(
    HANDLE, ULONG, PVOID, ULONG);

BOOL ProtectHandle(HANDLE h) {
    pNtSetInformationObject NtSetInformationObject = (pNtSetInformationObject)
        GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtSetInformationObject");
    OBJECT_HANDLE_FLAG_INFORMATION info = { FALSE, TRUE };
    NTSTATUS s = NtSetInformationObject(h, ObjectHandleFlagInformation,
                                        &info, sizeof(info));
    return NT_SUCCESS(s);
}

rustStrip inherit flag before sandbox spawn

// Cargo: ntapi = "0.4"
// Make a privileged token handle non-inheritable just before spawning a
// low-integrity child via CreateProcessAsUser. Combined with bInheritHandles=
// FALSE this gives belt-and-braces leak control.
use ntapi::ntobapi::NtSetInformationObject;

const ObjectHandleFlagInformation: u32 = 4;

#[repr(C)]
struct ObjectHandleFlagInfo { inherit: u8, protect_from_close: u8 }

pub unsafe fn strip_inherit(h: isize) {
    let info = ObjectHandleFlagInfo { inherit: 0, protect_from_close: 0 };
    let _ = NtSetInformationObject(
        h as _,
        ObjectHandleFlagInformation as _,
        &info as *const _ as _,
        std::mem::size_of::<ObjectHandleFlagInfo>() as u32,
    );
}

MITRE ATT&CK mappings

Last verified: 2026-05-20