Skip to content

FindWindow Debugger Detection

Malware enumerates top-level windows looking for the class names of known analyst tools such as OllyDbg, x64dbg, WinDbg and Process Monitor to detect an analysis environment.

Reverse-engineering tools register windows with well-known class names. Malware uses FindWindowW/FindWindowExW (a direct lookup by class) or EnumWindows (walk every top-level window and compare) to spot those class names. If a debugger, disassembler, or monitoring tool window exists, the sample assumes it is being analysed and refuses to run or alters its behaviour.

This is a beginner-level GUI-based check that requires no special privileges and is trivial to add to any sample.

How it works

The malware queries for each known class name; a non-NULL handle means the tool is running.

c
#include <windows.h>

const wchar_t *kToolClasses[] = {
    L"OLLYDBG",               // OllyDbg
    L"WinDbgFrameClass",      // WinDbg
    L"x64dbg",                // x64dbg / x32dbg
    L"ID",                    // Immunity Debugger
    L"PROCMON_WINDOW_CLASS",  // Process Monitor
};

BOOL AnalysisToolPresent(void)
{
    for (int i = 0; i < 5; i++)
        if (FindWindowW(kToolClasses[i], NULL) != NULL)
            return TRUE;
    return FALSE;
}

The EnumWindows variant passes a callback that calls GetClassNameW on every window and string-compares against the same list, which avoids importing FindWindowW directly and is harder to spot statically.

Detection & bypass

  • Static — Grep in IDA/Ghidra for imports of FindWindowW/FindWindowExW/EnumWindows/GetClassNameW, and for the literal class strings OLLYDBG, WinDbgFrameClass, x64dbg, ID, PROCMON_WINDOW_CLASS. These strings are often obfuscated, so also check for stack-string construction near FindWindow calls.
  • Dynamic — In x64dbg, breakpoint on user32!FindWindowW and user32!EnumWindows; inspect the class-name argument to learn exactly what the sample looks for. The return value (rax) reveals whether a match was found.
  • Patch / bypass — Rename the debugger window/class so the lookup misses (x64dbg supports changing its window title/class via plugins), or hook FindWindowW/EnumWindows/GetClassNameW to return NULL/no-match. Simplest: NOP or invert the conditional jump that acts on the result.
  • Tools — ScyllaHide and HideWindow-style x64dbg plugins that hide or rename the debugger window; Frida Interceptor on FindWindowW/EnumWindows; running analysis tools under renamed window classes.
Votes

Comments(0)