Skip to content
Anti-Analysisintermediate

ThreadHideFromDebugger

Calling NtSetInformationThread with ThreadHideFromDebugger detaches a thread from the debugger so its exceptions stop reaching the analyst.

ThreadHideFromDebugger is the value 0x11 of the THREADINFOCLASS enum passed to the undocumented NtSetInformationThread. When set, the kernel clears the thread's link to the debug object, so debug events generated by that thread — exceptions, breakpoints, single steps — are no longer delivered to an attached debugger.

Malware applies the flag to the thread that runs its sensitive logic, or to every thread it creates, hiding execution from an analyst who is stepping through the code.

How it works

The call takes a thread handle, the information class 0x11, and a NULL information buffer of length 0. On a hidden thread an int 3 no longer breaks into the debugger; instead the unhandled exception terminates the process — which itself can be used as a tripwire.

c
typedef NTSTATUS (NTAPI *pNtSetInformationThread)(
    HANDLE, ULONG, PVOID, ULONG);

#define ThreadHideFromDebugger 0x11

pNtSetInformationThread NtSetInformationThread =
    (pNtSetInformationThread)GetProcAddress(
        GetModuleHandleW(L"ntdll.dll"), "NtSetInformationThread");

// Hide the current thread from any attached debugger.
NtSetInformationThread(GetCurrentThread(),
                       ThreadHideFromDebugger, NULL, 0);

A sample can also self-test: hide the thread, then execute a breakpoint. If the debugger still catches it, the hide failed (an anti-anti-debug plugin is intercepting the call) and the malware can react.

asm
push 0                  ; ThreadInformationLength
push 0                  ; ThreadInformation
push 11h                ; ThreadHideFromDebugger
push -2                 ; GetCurrentThread() pseudo-handle
call NtSetInformationThread

Detection & analysis

Static analysis: Look for imports or dynamic resolution of NtSetInformationThread / ZwSetInformationThread, combined with the immediate constant 0x11 pushed as the information class. The NULL buffer and 0 length are reliable signatures for this specific class.

Dynamic analysis: Set a breakpoint on ntdll!NtSetInformationThread and inspect the second argument. When it equals 0x11, either skip the call or force the return value to a failure so the flag is never applied. ScyllaHide and TitanHide both neutralise this class automatically — TitanHide strips the information class in the kernel before the syscall executes.

Detection rule hint: Flag any call to Nt/ZwSetInformationThread where the ThreadInformationClass argument is 0x11 and the buffer/length are NULL/0. In sandbox API logs, a hide call quickly followed by a thread terminating on an unhandled STATUS_BREAKPOINT is a strong indicator.

Votes

Comments(0)