Generated banner for Anti Reversing Techniques
Generated logo for Anti Reversing Techniques

Anti Reversing Techniques

Seth HobsonCommunityCreated by Dávid BalatoniDistributed by Seth Hobson

  • Skill
  • Tool integration
  • Security
  • MIT
  • No issues found

From the author

Understand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques, when implementing anti-debugging protections for CTF challenges, when reverse engineering packed binaries, or when building security research tools that need to detect virtualized environments.
— the description by Dávid Balatoni

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured approach to identifying and neutralizing anti-reversing protections in binaries. It covers common evasion patterns including API-based anti-debugging, PEB-based checks, timing-based detection, and code virtualization. The skill is designed for security researchers, malware analysts, and CTF participants to facilitate legitimate analysis by providing identification methods, bypass strategies, and code artifacts for neutralizing protection layers.

What it does

  • Identifies anti-debugging and anti-reversing techniques within binary files.
  • Provides specific bypass strategies for common protection mechanisms.
  • Offers guidance on manual unpacking and OEP identification.
  • Includes scripts for scanning timing-based detection patterns.
  • Explains how to handle virtualization-based code protections.
  • Details platform-specific differences for Windows, Linux, and ARM environments.

When to use it

  • When analyzing malware that employs evasion or anti-analysis techniques.
  • During authorized penetration testing or security research engagements.
  • When reverse engineering packed or protected binaries.
  • When developing security research tools that need to detect or bypass virtualized environments.
  • When implementing or testing anti-debugging protections for CTF challenges.

Advantages

  • Centralizes knowledge on diverse protection mechanisms and their respective bypasses.
  • Provides actionable scripts and command sequences for immediate application.
  • Addresses both static identification and dynamic analysis workflows.
  • Offers clear guidance on handling platform-specific nuances like ARM vs x86.
  • Includes safety and legal warnings for responsible security research.

Usage examples

“Identify potential anti-debugging checks in this Windows binary.”
The agent scans the binary for common API calls like IsDebuggerPresent and PEB-based flags, providing a list of offsets to investigate in a disassembler.
“How do I bypass a timing-based RDTSC check in my target binary?”
The agent explains how to use hardware breakpoints to avoid INT3 overhead or suggests patching the conditional jump following the timing comparison.
“Help me unpack this binary protected with a custom packer.”
The agent guides the user through the ESP trick in x64dbg to find the Original Entry Point (OEP) and suggests using Scylla to fix the import table.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/wshobson/anti-reversing-techniques/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip anti-reversing-techniques.zip -d .agents/skills

Documentation by Dávid Balatoni

AUTHORIZED USE ONLY: This skill contains dual-use security techniques. Before proceeding with any bypass or analysis:

  1. Verify authorization: Confirm you have explicit written permission from the software owner, or are operating within a legitimate security context (CTF, authorized pentest, malware analysis, security research)

  2. Document scope: Ensure your activities fall within the defined scope of your authorization

  3. Legal compliance: Understand that unauthorized bypassing of software protection may violate laws (CFAA, DMCA anti-circumvention, etc.)

Legitimate use cases: Malware analysis, authorized penetration testing, CTF competitions, academic security research, analyzing software you own/have rights to

Anti-Reversing Techniques

Understanding protection mechanisms encountered during authorized software analysis, security research, and malware analysis. This knowledge helps analysts bypass protections to complete legitimate analysis tasks.

For advanced techniques, see references/advanced-techniques.md


Input / Output

What you provide:

  • Binary path or sample: the executable, DLL, or firmware image under analysis

  • Platform: Windows x86/x64, Linux, macOS, ARM — affects which checks apply

  • Goal: bypass for dynamic analysis, identify protection type, build detection code, implement for CTF

What this skill produces:

  • Protection identification: named technique (e.g., RDTSC timing check, PEB BeingDebugged) with location in binary

  • Bypass strategy: specific patch addresses, hook points, or tool commands to neutralize each check

  • Analysis report: structured findings listing each protection layer, severity, and recommended bypass

  • Code artifacts: Python/IDAPython scripts, GDB command sequences, or C stubs for bypassing or implementing checks


Detailed patterns and worked examples

Detailed pattern documentation lives in references/details.md. Read that file when the navigation tier above is insufficient.

Troubleshooting

Detection technique works on x86 but not ARM

RDTSC and CPUID are x86-only. On ARM, use MRS x0, PMCCNTR_EL0 (requires kernel PMU access) or clock_gettime(CLOCK_MONOTONIC). PEB/TEB do not exist on ARM — replace with /proc/self/status (Linux) or task_info (macOS). Rebuild detection logic with platform-specific APIs.

False positive on legitimate debugger or analysis tool

Timing checks fire when Process Monitor or AV hooks inflate syscall latency. Calibrate the threshold at startup: measure the guarded path 3 times and use mean + 3*stddev. For ptrace checks, verify the TracerPid comm name via /proc/<pid>/comm before exiting — it may be an unrelated monitoring tool, not a debugger.

Bypass patch causes crash instead of continuing execution

Before NOPing a conditional jump, trace the "detected" branch fully. If it initializes or frees heap state needed later, patching the jump skips that setup and corrupts state. Instead, patch the comparison operand to the expected "clean" value, or use x64dbg's "Set condition to always false" on the breakpoint rather than modifying bytes.


  • binary-analysis-patterns — static and dynamic analysis workflows for ELF/PE/Mach-O

  • memory-forensics — process memory acquisition, artifact extraction, and live analysis

  • protocol-reverse-engineering — decoding custom binary protocols and encrypted network traffic

Files

references/advanced-techniques.md

Advanced Anti-Reversing Techniques

This reference covers advanced and niche techniques extracted from the core skill to keep SKILL.md focused on common patterns. Refer here for deep-dive analysis of virtualization-based protections, packer internals, and anti-disassembly tricks.


Packing and Encryption

Common Packers
UPX          - Open source, easy to unpack (upx -d)
Themida      - Commercial, VM-based protection with anti-debug
VMProtect    - Commercial, code virtualization with multiple VM architectures
ASPack       - Compression packer, LZSS-based
PECompact    - Compression packer with CRC integrity checks
Enigma       - Commercial protector with key-based licensing
MPRESS       - LZMA-based packer, often used by malware
Obsidium     - Commercial, anti-debug + anti-VM + encryption
Unpacking Methodology
1. Identify packer (DIE, Exeinfo PE, PEiD, detect-it-easy)

2. Static unpacking (if known packer):
   - UPX: upx -d packed.exe
   - Use existing unpacker tools from UnpacMe, MalwareBazaar

3. Dynamic unpacking:
   a. Find Original Entry Point (OEP)
   b. Set breakpoint on OEP
   c. Dump memory when OEP reached
   d. Fix import table (Scylla, ImpREC)

4. OEP finding techniques:
   - Hardware breakpoint on stack (ESP trick)
   - Break on common API calls (GetCommandLineA, GetModuleHandle)
   - Trace and look for typical entry prologue (push ebp / mov ebp, esp)
   - Check for tail jump pattern: jmp <far address>
Manual Unpacking (ESP Trick — x64dbg)
1. Load packed binary in x64dbg
2. Note entry point (packer stub address)
3. Use ESP trick:
   a. Run to entry point (F9 then F8 until PUSHAD)
   b. Right-click ESP value → "Follow in Dump"
   c. Set hardware breakpoint on access (HW BP on [ESP])
   d. Run (F9) — execution breaks after POPAD (stack restored)
4. Look for JMP to OEP (often a far jump to .text section)
5. At OEP, use Scylla plugin:
   - IAT Autosearch → Get Imports
   - Dump process
   - Fix dump with imports
UPX Variant Unpacking
# Standard UPX — direct decompress
upx -d packed.exe -o unpacked.exe

# Modified UPX header (signature patched to evade upx -d):
# 1. Find UPX0/UPX1 section names (may be renamed)
# 2. Restore original UPX magic bytes: 0x55 0x50 0x58
# 3. Then run upx -d

# Python: restore UPX magic for patched header
python3 -c "
import sys
data = open(sys.argv[1], 'rb').read()
# UPX magic at various offsets — search for stub pattern
idx = data.find(b'\x60\xBE')  # PUSHAD; MOV ESI stub
print(f'Stub at: {hex(idx)}')
"

Virtualization-Based Protection

Code Virtualization Architecture
Original x86 code is converted to custom bytecode interpreted by an
embedded virtual machine at runtime.

Original:          VM Protected:
  mov eax, 1    →    push vm_context_ptr
  add eax, 2         call vm_entry
  ret                ; VM dispatcher loop decodes bytecode
                     ; and invokes handler table entries
                     ; equivalent semantics, unrecognizable form
VM Component Identification
1. VM Entry Point:
   - Usually a CALL or JMP to a large function with a loop
   - Look for: load bytecode ptr, load handler table, dispatch loop

2. Handler Table:
   - Array of function pointers (one per virtual opcode)
   - Indexed by decoded opcode byte/word
   - Each handler emulates one instruction

3. Virtual Registers:
   - Stored in a context structure (vm_context)
   - Usually on the stack or in a dedicated heap allocation
   - Map to native registers by handler logic

4. Bytecode Location:
   - Separate section (.vmp0, .vmp1 in VMProtect)
   - Or inline with code (Themida)
   - Encrypted or compressed in some implementations
Devirtualization Analysis Workflow
1. Identify VM entry: look for large functions with indirect dispatch (jmp [reg+offset])

2. Trace execution with logging:
   - Use x64dbg trace log: log handler address and context on each iteration
   - Example trace command in x64dbg: log "{p:rax} {p:rbx}" (on handler dispatch)

3. Map bytecode to operations:
   - Each handler maps to a semantic operation (ADD, LOAD, STORE, JCC, etc.)
   - Build a table: vm_opcode → native semantic

4. Lift to IR:
   - Tools: VMAttack (IDA plugin), SATURN, NoVmp (open source, VMProtect 3)
   - angr: load binary, explore VM entry to extract symbolic semantics
   - Triton: dynamic symbolic execution to lift VM handlers

5. Reconstruct control flow:
   - After lifting, rebuild CFG from recovered semantics
   - Tools output pseudo-C or assembly that is analyzable in IDA/Ghidra
VMProtect-Specific Notes
VMProtect 3.x uses multiple VM architectures in one binary.
Each protected function may use a different VM instance.

Indicators:
- Sections named .vmp0, .vmp1 (or renamed)
- Characteristic dispatcher: movzx eax, byte ptr [esi]; jmp [eax*4+handler_table]
- Functions begin with PUSH of a magic constant, then JMP vm_entry

Tools:
- NoVmp: open-source devirtualizer for VMProtect 3
- SATURN: IDA plugin, handles multiple packer/VM types
- vmp_dumper: extracts bytecode for offline analysis

Advanced Anti-Disassembly Tricks

Overlapping Instructions
; The disassembler decodes one path, but execution takes another.
; Jump lands in the middle of a multi-byte instruction.

eb 01          ; JMP +1  (jumps over next byte)
e8             ; This byte is the "fake" start of CALL — never executed
58             ; POP EAX — this is what executes after the JMP

; Result: linear disassembly shows CALL (e8 58 ...), but at runtime
; execution reaches POP EAX at the byte after JMP target.
Junk Byte Insertion
; Insert bytes that are valid as part of a multi-byte encoding
; but never actually execute (jumped over).

jmp short real_code   ; eb 03 — jump over 3 bytes
db 0xFF, 0x15, 0x00   ; Fake MOV/CALL prefix bytes — confuse disassembler
real_code:
mov eax, 1            ; Actual instruction
Self-Modifying Code Patterns
// Decrypt instruction bytes at runtime
unsigned char code[] = { 0x90 ^ 0xAA, 0xC3 ^ 0xAA };  // Encrypted NOP; RET
void decrypt_and_run(unsigned char *buf, size_t len, unsigned char key) {
    // Mark page executable
    VirtualProtect(buf, len, PAGE_EXECUTE_READWRITE, &old);
    for (size_t i = 0; i < len; i++) buf[i] ^= key;
    ((void(*)())buf)();
}

Analysis Approach:

  • Set memory write breakpoints on the code region to catch decryption

  • Use PIN or DynamoRIO to log executed instruction addresses

  • Dump memory after self-modification to capture the real code

Return-Oriented Programming as Obfuscation
Some protectors use ROP chains not for exploitation but for obfuscation:
- Replace direct CALL/JMP with a crafted stack + RET
- Disassembler cannot follow indirect returns easily

Detection: Look for sequences of POP; RET or ADD ESP, N; RET
Tools: ROPgadget, rp++ can enumerate; angr can follow symbolically

Advanced VM Detection Techniques

RDTSC Delta Calibration
// Calibrate baseline on real hardware, detect anomaly in VM
// VM exits on CPUID/IN instructions inflate RDTSC delta significantly

static inline uint64_t rdtsc(void) {
    unsigned int lo, hi;
    __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
    return ((uint64_t)hi << 32) | lo;
}

int detect_vm_timing(void) {
    uint64_t t1 = rdtsc();
    __asm__ __volatile__("cpuid" ::: "eax","ebx","ecx","edx");
    uint64_t t2 = rdtsc();
    // Bare metal: delta ~150-300 cycles; VM: delta >1000 cycles
    return (t2 - t1) > 750;
}
VMEXIT Side-Channel via IN Instruction
// IN instruction to port 0x5658 (VMware backdoor) causes VM exit
// On bare metal: raises #GP exception; in VMware: returns data
int detect_vmware_backdoor(void) {
    __try {
        __asm {
            push eax
            push ebx
            push ecx
            push edx
            mov eax, 'VMXh'   // VMware magic
            mov ecx, 10       // Get version command
            mov dx,  0x5658   // VMware backdoor port
            in eax, dx
            mov [is_vm], 1
            pop edx
            pop ecx
            pop ebx
            pop eax
        }
    } __except(EXCEPTION_EXECUTE_HANDLER) {
        // Exception = bare metal, IN caused #GP
    }
    return is_vm;
}
Hypervisor Leaf Enumeration
// CPUID leaf 0x40000000–0x4FFFFFFF reserved for hypervisors
void enumerate_hypervisor(void) {
    int info[4];
    __cpuid(info, 0x40000000);
    char sig[13] = {0};
    memcpy(sig,     &info[1], 4);
    memcpy(sig + 4, &info[2], 4);
    memcpy(sig + 8, &info[3], 4);
    // Known signatures:
    // "VMwareVMware" → VMware
    // "Microsoft Hv" → Hyper-V
    // "KVMKVMKVM\0\0\0" → KVM
    // "VBoxVBoxVBox" → VirtualBox
    // "XenVMMXenVMM" → Xen
    printf("Hypervisor: %s\n", sig);
}
Guest Driver / Artifact Detection
// Check for known VM driver files (Windows)
const char *vm_drivers[] = {
    "C:\\Windows\\System32\\drivers\\vmmouse.sys",   // VMware
    "C:\\Windows\\System32\\drivers\\vmhgfs.sys",    // VMware shared folders
    "C:\\Windows\\System32\\drivers\\VBoxMouse.sys", // VirtualBox
    "C:\\Windows\\System32\\drivers\\VBoxGuest.sys", // VirtualBox
    "C:\\Windows\\System32\\drivers\\balloon.sys",   // QEMU/KVM
    NULL
};

int check_vm_files(void) {
    for (int i = 0; vm_drivers[i]; i++) {
        if (GetFileAttributesA(vm_drivers[i]) != INVALID_FILE_ATTRIBUTES)
            return 1;
    }
    return 0;
}

// Registry artifact check
const char *vm_reg_keys[] = {
    "SOFTWARE\\VMware, Inc.\\VMware Tools",
    "SOFTWARE\\Oracle\\VirtualBox Guest Additions",
    "HARDWARE\\ACPI\\DSDT\\VBOX__",
    NULL
};

Packer/Protector Detection Reference

DIE (Detect-It-Easy) Signatures
- Entropy > 7.0 on a section → likely packed/encrypted
- Section name mismatch (e.g., .text has exec+write permissions) → self-modifying
- Import table with only LoadLibrary + GetProcAddress → dynamic API resolution
- Single section with high entropy + no readable strings → heavy packing
PE Anomaly Checklist for Packed Binaries
[ ] Section characteristics: writable + executable = unusual
[ ] Virtual size >> raw size on code section = unpacking stub inflates
[ ] Import table almost empty (only 1-3 imports) = dynamic resolution
[ ] Entry point not in .text section = custom stub
[ ] High entropy (>7.2) in any section = encryption/compression
[ ] Overlay data after EOF of last section = appended payload
[ ] TLS callbacks present = early execution before main EP

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Dávid Balatoni
Publisher
Seth Hobson (Community)
Distributed by
Seth Hobson
Source
wshobson/agents · plugins/reverse-engineering/skills/anti-reversing-techniques · commit 4bde316
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Dávid Balatoni or Seth Hobson.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download anti-reversing-techniques.zip