$npx -y skills add ShulkwiSEC/bb-huge --skill anti-debugging-techniquesAnti-debugging detection and bypass playbook. Use when reversing protected binaries that detect debuggers via ptrace, PEB flags, timing checks, or signal/exception handlers on Linux and Windows.
| 1 | # SKILL: Anti-Debugging Techniques — Detection & Bypass Playbook |
| 2 | |
| 3 | > **AI LOAD INSTRUCTION**: Expert anti-debug techniques across Linux and Windows. Covers ptrace, PEB flags, NtQueryInformationProcess, timing attacks, signal-based detection, TLS callbacks, VEH tricks, and all corresponding bypass methods. Base models often miss the distinction between user-mode and kernel-mode detection and the correct patching strategy for each. |
| 4 | |
| 5 | ## 0. RELATED ROUTING |
| 6 | |
| 7 | - [code-obfuscation-deobfuscation](../code-obfuscation-deobfuscation/SKILL.md) when the binary also uses control flow flattening, VM protection, or string encryption |
| 8 | - [vm-and-bytecode-reverse](../vm-and-bytecode-reverse/SKILL.md) when the anti-debug sits inside a custom VM dispatcher |
| 9 | - [symbolic-execution-tools](../symbolic-execution-tools/SKILL.md) when you want to symbolically skip anti-debug checks entirely |
| 10 | |
| 11 | ### Advanced Reference |
| 12 | |
| 13 | Also load [ANTI_DEBUG_MATRIX.md](./ANTI_DEBUG_MATRIX.md) when you need: |
| 14 | - Complete cross-reference matrix of technique × OS × detection method × bypass method |
| 15 | - Per-technique reliability ratings and false-positive notes |
| 16 | - Tool compatibility chart (GDB, x64dbg, WinDbg, Frida, ScyllaHide) |
| 17 | |
| 18 | ### Quick bypass picks |
| 19 | |
| 20 | | Detection Class | First Bypass | Backup | |
| 21 | |---|---|---| |
| 22 | | ptrace-based (Linux) | `LD_PRELOAD` hook `ptrace()` → return 0 | Kernel module to hide tracer | |
| 23 | | PEB.BeingDebugged (Windows) | Patch PEB byte at `fs:[0x30]+0x2` | ScyllaHide auto-patch | |
| 24 | | Timing check (rdtsc) | Conditional BP after rdtsc, fix registers | Frida hook `rdtsc` return | |
| 25 | | IsDebuggerPresent | NOP the call / hook return 0 | x64dbg built-in hide | |
| 26 | | INT 2D / UD2 exception | Set VEH to handle gracefully | TitanHide driver | |
| 27 | |
| 28 | --- |
| 29 | |
| 30 | ## 1. LINUX ANTI-DEBUG TECHNIQUES |
| 31 | |
| 32 | ### 1.1 ptrace(PTRACE_TRACEME) |
| 33 | |
| 34 | The classic self-attach: a process calls `ptrace(PTRACE_TRACEME, 0, 0, 0)`. If a debugger is already attached, the call fails (returns -1). |
| 35 | |
| 36 | ```c |
| 37 | if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) { |
| 38 | exit(1); // debugger detected |
| 39 | } |
| 40 | ``` |
| 41 | |
| 42 | **Bypass methods**: |
| 43 | |
| 44 | | Method | How | |
| 45 | |---|---| |
| 46 | | `LD_PRELOAD` shim | Compile shared lib: `long ptrace(int r, ...) { return 0; }` and set `LD_PRELOAD` | |
| 47 | | Binary patch | NOP the `ptrace` call or patch return value check | |
| 48 | | GDB catch | `catch syscall ptrace` → modify `$rax` to 0 on return | |
| 49 | | Kernel module | Hook `sys_ptrace` to allow multiple tracers | |
| 50 | |
| 51 | ### 1.2 /proc/self/status — TracerPid |
| 52 | |
| 53 | ```c |
| 54 | FILE *f = fopen("/proc/self/status", "r"); |
| 55 | // parse TracerPid: if non-zero → debugger attached |
| 56 | ``` |
| 57 | |
| 58 | **Bypass**: Mount a FUSE filesystem over `/proc/self`, or `LD_PRELOAD` hook `fopen`/`fread` to filter `TracerPid` to 0. |
| 59 | |
| 60 | ### 1.3 Timing Checks (rdtsc / clock_gettime) |
| 61 | |
| 62 | Measures elapsed time between two points; debugger single-stepping causes noticeable delay. |
| 63 | |
| 64 | ```asm |
| 65 | rdtsc |
| 66 | mov ebx, eax ; save low 32 bits |
| 67 | ; ... protected code ... |
| 68 | rdtsc |
| 69 | sub eax, ebx |
| 70 | cmp eax, 0x1000 ; threshold |
| 71 | ja debugger_detected |
| 72 | ``` |
| 73 | |
| 74 | **Bypass**: Set hardware breakpoint after second `rdtsc`, modify `eax` to pass the comparison. Or use Frida to replace the timing function. |
| 75 | |
| 76 | ### 1.4 Signal-Based Detection (SIGTRAP) |
| 77 | |
| 78 | ```c |
| 79 | volatile int caught = 0; |
| 80 | void handler(int sig) { caught = 1; } |
| 81 | signal(SIGTRAP, handler); |
| 82 | raise(SIGTRAP); |
| 83 | if (!caught) exit(1); // debugger swallowed the signal |
| 84 | ``` |
| 85 | |
| 86 | When a debugger is attached, `SIGTRAP` is consumed by the debugger rather than delivered to the handler. **Bypass**: In GDB, use `handle SIGTRAP nostop pass` to forward the signal. |
| 87 | |
| 88 | ### 1.5 /proc/self/maps & LD_PRELOAD Detection |
| 89 | |
| 90 | Checks for injected libraries or memory regions characteristic of debuggers/instrumentation. |
| 91 | |
| 92 | ```c |
| 93 | FILE *f = fopen("/proc/self/maps", "r"); |
| 94 | while (fgets(buf, sizeof(buf), f)) { |
| 95 | if (strstr(buf, "frida") || strstr(buf, "LD_PRELOAD")) |
| 96 | exit(1); |
| 97 | } |
| 98 | ``` |
| 99 | |
| 100 | **Bypass**: Hook `fopen("/proc/self/maps")` to return a filtered version, or rename Frida's agent library. |
| 101 | |
| 102 | ### 1.6 Environment Variable Checks |
| 103 | |
| 104 | Some protections check for `LD_PRELOAD`, `LINES`, `COLUMNS` (set by GDB's terminal), or debugger-specific env vars. |
| 105 | |
| 106 | **Bypass**: Unset suspicious env vars before launch, or hook `getenv()`. |
| 107 | |
| 108 | --- |
| 109 | |
| 110 | ## 2. WINDOWS ANTI-DEBUG TECHNIQUES |
| 111 | |
| 112 | ### 2.1 IsDebuggerPresent / CheckRemoteDebuggerPresent |
| 113 | |
| 114 | ```c |
| 115 | if (IsDebuggerPresent()) ExitProcess(1); |
| 116 | |
| 117 | BOOL debugged = FALSE; |
| 118 | CheckRemoteDebuggerPresent(GetCurrentProcess(), &debugged); |
| 119 | if (debugged) ExitProcess(1); |
| 120 | ``` |
| 121 | |
| 122 | **Bypass**: Hook `kernel32!IsDebuggerPresent` to return 0, or patch PEB directly. |
| 123 | |
| 124 | ### 2.2 PEB Flags |
| 125 | |
| 126 | | Field | Offset (x64) | Debugged Value | Normal Value | |
| 127 | |---|---|---|---| |
| 128 | | `BeingDebugged` | `PEB+0x02` | 1 | 0 | |
| 129 | | `NtGlobalFlag` | `PEB+0xBC` | `0x70` (FLG_HEAP_*) | 0 | |
| 130 | | `ProcessHeap.Flags` | Heap+0x40 | `0x40000062` | `0x00000002` | |
| 131 | | `ProcessHeap.ForceFlags` | H |