Anti‐Debug techniques - Arrbat/Veil-Forge GitHub Wiki
Introduction
To analyze software, specialists usually apply static or dynamic analysis. This text focuses on the dynamic approach.
Dynamic analysis involves running an application under a debugger (e.g. OllyDbg, x32dbg, x64dbg), allowing inspection of API calls, assembly code, stack state, loaded DLLs, and more.
To counter this, many applications implement anti-debugging techniques — tricks to detect or disrupt debugging.
These techniques can be grouped into several categories.
Anti-debug techniques groups
Use OS-level flags and fields (e.g. PEB, NtGlobalFlag) that indicate if the process is being debugged.
Involve detection of debugger-related objects like windows, mutexes, or named pipes.
Use structured or vectored exception handling to detect debugger behavior based on how it processes faults or breakpoints.
Measure time between operations to detect slowdowns caused by breakpoints or step-through debugging.
Read or scan memory regions to detect debugger artifacts or modifications.
Leverage low-level CPU instructions (e.g. INT 3, ICEBP, RDTSCP) to detect or break debuggers.
Require human-like input or reaction to trick automated tools and debuggers.
A diverse set of other tricks, like API misuses or undocumented behavior, that don't fit into the categories above.
Project`s context
Project uses:
-
4 Debug Flags techniques:
- IsDebuggerPresent() checks BeingDebugged flag in PEB
- CheckRemoteDebuggerPresent() checks if a debugger is attached to the current process
- _ProcessDebugPort() function which retrieves the port number of the debugger for the process
- _ProcessDebugFlags() function. The kernel structure
EPROCESS
has a fieldNoDebugInherit
. Using the undocumented classProcessDebugFlags
(0x1F), its inverse value can be read — if it returns 0, a debugger is present
-
One timing technique based on
RDTSC
instruction. Technique is derived into 2 functions:- BeginDetectRDTSCBasedDelay()
- EndDetectRDTSCBasedDelay
-
Process memory technique based on patching Debug Break Point. Function called
PatchDbgBreakPoint
Why only these techniques are used?
Overall it's not hard to add other techniques.
Some anti-debug techniques require try-catch
constructs or C++ features, while this project is intentionally written in pure C to keep things simple
Other techniques were not used because they were not needed, as the project is not positioned as a full-fledged production-level security solution.