
Anti Reversing Techniques
- 8.3k installs
- 38.3k repo stars
- Updated July 22, 2026
- wshobson/agents
anti-reversing-techniques is an agent skill that Understand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques.
About
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. --- name: anti-reversing-techniques description: 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. --- > **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 auth.
- Anti-Reversing Techniques
- **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
- **Protection identification**: named technique (e.g., RDTSC timing check, PEB BeingDebugged) with location in binary
Anti Reversing Techniques by the numbers
- 8,312 all-time installs (skills.sh)
- +167 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #191 of 2,184 Testing & QA skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
anti-reversing-techniques capabilities & compatibility
- Capabilities
- anti reversing techniques · **binary path or sample**: the executable, dll, · **platform**: windows x86/x64, linux, macos, arm · **goal**: bypass for dynamic analysis, identify · **protection identification**: named technique (
- Use cases
- documentation
What anti-reversing-techniques says it does
--- name: anti-reversing-techniques description: Understand anti-reversing, obfuscation, and protection techniques encountered during software analysis.
--- > **AUTHORIZED USE ONLY**: This skill contains dual-use security techniques.
Before proceeding with any bypass or analysis: > > 1.
**Document scope**: Ensure your activities fall within the defined scope of your authorization > 3.
npx skills add https://github.com/wshobson/agents --skill anti-reversing-techniquesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 8.3k |
|---|---|
| repo stars | ★ 38.3k |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 22, 2026 |
| Repository | wshobson/agents ↗ |
What problem does anti-reversing-techniques solve for developers using this skill?
Understand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques, when implementing anti-debugging prote
Who is it for?
Developers who need anti-reversing-techniques patterns described in the cached skill documentation.
Skip if: Skip when docs are empty or the task is outside the skill's documented scope.
When should I use this skill?
Understand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques, when implementing anti-debugging prote
What you get
Actionable workflows and conventions from SKILL.md for anti-reversing-techniques.
- packer configuration plan
- anti-debug protection strategy
By the numbers
- Documents 6 binary packers: UPX, Themida, VMProtect, ASPack, PECompact, and Enigma
Files
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.
---
Related Skills
binary-analysis-patterns— static and dynamic analysis workflows for ELF/PE/Mach-Omemory-forensics— process memory acquisition, artifact extraction, and live analysisprotocol-reverse-engineering— decoding custom binary protocols and encrypted network traffic
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 + encryptionUnpacking 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 importsUPX 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 formVM 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 implementationsDevirtualization 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/GhidraVMProtect-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 instructionSelf-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 packingPE 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 EPanti-reversing-techniques — detailed patterns and worked examples
Anti-Debugging Techniques
Windows Anti-Debugging
API-Based Detection
// IsDebuggerPresent
if (IsDebuggerPresent()) {
exit(1);
}
// CheckRemoteDebuggerPresent
BOOL debugged = FALSE;
CheckRemoteDebuggerPresent(GetCurrentProcess(), &debugged);
if (debugged) exit(1);
// NtQueryInformationProcess
typedef NTSTATUS (NTAPI *pNtQueryInformationProcess)(
HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
DWORD debugPort = 0;
NtQueryInformationProcess(
GetCurrentProcess(),
ProcessDebugPort, // 7
&debugPort,
sizeof(debugPort),
NULL
);
if (debugPort != 0) exit(1);
// Debug flags
DWORD debugFlags = 0;
NtQueryInformationProcess(
GetCurrentProcess(),
ProcessDebugFlags, // 0x1F
&debugFlags,
sizeof(debugFlags),
NULL
);
if (debugFlags == 0) exit(1); // 0 means being debuggedBypass: Use ScyllaHide plugin in x64dbg (patches all common checks automatically). Manually: force IsDebuggerPresent return to 0, patch PEB.BeingDebugged to 0, hook NtQueryInformationProcess. In IDA: ida_bytes.patch_byte(check_addr, 0x90).
PEB-Based Detection
// Direct PEB access
#ifdef _WIN64
PPEB peb = (PPEB)__readgsqword(0x60);
#else
PPEB peb = (PPEB)__readfsdword(0x30);
#endif
// BeingDebugged flag
if (peb->BeingDebugged) exit(1);
// NtGlobalFlag
// Debugged: 0x70 (FLG_HEAP_ENABLE_TAIL_CHECK |
// FLG_HEAP_ENABLE_FREE_CHECK |
// FLG_HEAP_VALIDATE_PARAMETERS)
if (peb->NtGlobalFlag & 0x70) exit(1);
// Heap flags
PDWORD heapFlags = (PDWORD)((PBYTE)peb->ProcessHeap + 0x70);
if (*heapFlags & 0x50000062) exit(1);Bypass: In x64dbg, follow gs:[60] (x64) or fs:[30] (x86) in dump. Set BeingDebugged (offset +2) to 0; clear NtGlobalFlag (offset +0xBC on x64).
Timing-Based Detection
// RDTSC timing
uint64_t start = __rdtsc();
// ... some code ...
uint64_t end = __rdtsc();
if ((end - start) > THRESHOLD) exit(1);
// QueryPerformanceCounter
LARGE_INTEGER start, end, freq;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
// ... code ...
QueryPerformanceCounter(&end);
double elapsed = (double)(end.QuadPart - start.QuadPart) / freq.QuadPart;
if (elapsed > 0.1) exit(1); // Too slow = debugger
// GetTickCount
DWORD start = GetTickCount();
// ... code ...
if (GetTickCount() - start > 1000) exit(1);Python script — timing-based anti-debug detection scanner:
#!/usr/bin/env python3
"""Scan a binary for common timing-based anti-debug patterns."""
import re
import sys
PATTERNS = {
"RDTSC": rb"\x0f\x31", # RDTSC opcode
"RDTSCP": rb"\x0f\x01\xf9", # RDTSCP opcode
"GetTickCount": rb"GetTickCount\x00",
"QueryPerfCounter": rb"QueryPerformanceCounter\x00",
"NtQuerySysInfo": rb"NtQuerySystemInformation\x00",
}
def scan(path: str) -> None:
data = open(path, "rb").read()
print(f"Scanning: {path} ({len(data)} bytes)\n")
for name, pattern in PATTERNS.items():
hits = [m.start() for m in re.finditer(re.escape(pattern), data)]
if hits:
offsets = ", ".join(hex(h) for h in hits[:5])
print(f" [{name}] found at: {offsets}")
print("\nDone. Cross-reference offsets in IDA/Ghidra to find check logic.")
if __name__ == "__main__":
scan(sys.argv[1])Bypass: Use hardware breakpoints (no INT3 overhead), NOP the comparison + conditional jump, freeze RDTSC via hypervisor, or hook timing APIs to return consistent values.
Exception-Based Detection
// SEH: if debugger is attached it consumes the INT3 exception
// and execution falls through to exit(1) instead of the __except handler
__try { __asm { int 3 } }
__except(EXCEPTION_EXECUTE_HANDLER) { return; } // Clean: exception handled here
exit(1); // Dirty: debugger swallowed the exception
// VEH: register handler that self-handles INT3 (increments RIP past INT3)
// Debugger intercepts first, handler never runs → detected
LONG CALLBACK VectoredHandler(PEXCEPTION_POINTERS ep) {
if (ep->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT) {
ep->ContextRecord->Rip++;
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}Bypass: In x64dbg, set "Pass exception to program" for EXCEPTION_BREAKPOINT (Options → Exceptions → add 0x80000003).
Linux Anti-Debugging
// ptrace self-trace
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1) {
// Already being traced
exit(1);
}
// /proc/self/status
FILE *f = fopen("/proc/self/status", "r");
char line[256];
while (fgets(line, sizeof(line), f)) {
if (strncmp(line, "TracerPid:", 10) == 0) {
int tracer_pid = atoi(line + 10);
if (tracer_pid != 0) exit(1);
}
}
// Parent process check
if (getppid() != 1 && strcmp(get_process_name(getppid()), "bash") != 0) {
// Unusual parent (might be debugger)
}Bypass (LD_PRELOAD hook):
# hook.c: long ptrace(int request, ...) { return 0; }
# gcc -shared -fPIC -o hook.so hook.c
LD_PRELOAD=./hook.so ./targetGDB bypass command sequence:
# 1. Make ptrace(PTRACE_TRACEME) always return 0 (success)
catch syscall ptrace
commands
silent
set $rax = 0
continue
end
# 2. Bypass check after ptrace call: find "cmp rax, 0xffffffff; je <exit>"
# Clear ZF so the conditional jump is not taken:
# set $eflags = $eflags & ~0x40
# 3. Bypass /proc/self/status TracerPid check at the open() level
catch syscall openat
commands
silent
# If arg contains "status", patch the fd result to /dev/null equivalent
continue
end
# 4. Bypass parent process name check
set follow-fork-mode child
set detach-on-fork off---
Anti-VM Detection
Hardware Fingerprinting
// CPUID-based detection
int cpuid_info[4];
__cpuid(cpuid_info, 1);
// Check hypervisor bit (bit 31 of ECX)
if (cpuid_info[2] & (1 << 31)) {
// Running in hypervisor
}
// CPUID brand string
__cpuid(cpuid_info, 0x40000000);
char vendor[13] = {0};
memcpy(vendor, &cpuid_info[1], 12);
// "VMwareVMware", "Microsoft Hv", "KVMKVMKVM", "VBoxVBoxVBox"
// MAC address prefix
// VMware: 00:0C:29, 00:50:56
// VirtualBox: 08:00:27
// Hyper-V: 00:15:5DRegistry/File Detection
// Windows registry keys
// HKLM\SOFTWARE\VMware, Inc.\VMware Tools
// HKLM\SOFTWARE\Oracle\VirtualBox Guest Additions
// HKLM\HARDWARE\ACPI\DSDT\VBOX__
// Files
// C:\Windows\System32\drivers\vmmouse.sys
// C:\Windows\System32\drivers\vmhgfs.sys
// C:\Windows\System32\drivers\VBoxMouse.sys
// Processes
// vmtoolsd.exe, vmwaretray.exe
// VBoxService.exe, VBoxTray.exeTiming-Based VM Detection
// VM exits cause timing anomalies
uint64_t start = __rdtsc();
__cpuid(cpuid_info, 0); // Causes VM exit
uint64_t end = __rdtsc();
if ((end - start) > 500) {
// Likely in VM (CPUID takes longer)
}Bypass: Use bare-metal environment, harden VM (remove guest tools, randomize MAC, delete artifact files), patch detection branches in the binary, or use FLARE-VM/REMnux with hardened settings.
For advanced VM detection (RDTSC delta calibration, VMware backdoor port, hypervisor leaf enumeration, guest driver artifact checks), see references/advanced-techniques.md.
---
Code Obfuscation
Control Flow Obfuscation
Control Flow Flattening
// Original
if (cond) {
func_a();
} else {
func_b();
}
func_c();
// Flattened
int state = 0;
while (1) {
switch (state) {
case 0:
state = cond ? 1 : 2;
break;
case 1:
func_a();
state = 3;
break;
case 2:
func_b();
state = 3;
break;
case 3:
func_c();
return;
}
}Analysis Approach:
- Identify state variable
- Map state transitions
- Reconstruct original flow
- Tools: D-810 (IDA), SATURN
Opaque Predicates
int x = rand();
if ((x * x) >= 0) { real_code(); } // Always true → junk_code() is dead
if ((x*(x+1)) % 2 == 1) { junk(); } // Always false → consecutive product is evenAnalysis Approach: Identify invariant expressions via symbolic execution (angr, Triton), or pattern-match known opaque forms and prune them.
Data Obfuscation
String Encryption
// XOR encryption
char decrypt_string(char *enc, int len, char key) {
char *dec = malloc(len + 1);
for (int i = 0; i < len; i++) {
dec[i] = enc[i] ^ key;
}
dec[len] = 0;
return dec;
}
// Stack strings
char url[20];
url[0] = 'h'; url[1] = 't'; url[2] = 't'; url[3] = 'p';
url[4] = ':'; url[5] = '/'; url[6] = '/';
// ...Analysis Approach:
# FLOSS for automatic string deobfuscation
floss malware.exe
# IDAPython string decryption
def decrypt_xor(ea, length, key):
result = ""
for i in range(length):
byte = ida_bytes.get_byte(ea + i)
result += chr(byte ^ key)
return resultAPI Obfuscation
// Dynamic API resolution
typedef HANDLE (WINAPI *pCreateFileW)(LPCWSTR, DWORD, DWORD,
LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
pCreateFileW myCreateFile = (pCreateFileW)GetProcAddress(
kernel32, "CreateFileW");
// API hashing
DWORD hash_api(char *name) {
DWORD hash = 0;
while (*name) {
hash = ((hash >> 13) | (hash << 19)) + *name++;
}
return hash;
}
// Resolve by hash comparison instead of stringAnalysis Approach: Identify the hash algorithm, build a database of known API name hashes, use HashDB plugin for IDA, or run under a debugger to let the binary resolve calls at runtime.
Instruction-Level Obfuscation
; Dead code insertion — semantically inert but pollutes disassembly
push ebx / mov eax, 1 / pop ebx / xor ecx, ecx / add ecx, ecx
; Instruction substitution — same semantics, different encoding
xor eax, eax → sub eax, eax | mov eax, 0 | and eax, 0
mov eax, 1 → xor eax, eax; inc eax | push 1; pop eaxFor advanced anti-disassembly tricks (overlapping instructions, junk byte insertion, self-modifying code, ROP as obfuscation), see references/advanced-techniques.md.
---
Bypass Strategies Summary
General Principles
1. Understand the protection: Identify what technique is used 2. Find the check: Locate protection code in binary 3. Patch or hook: Modify check to always pass 4. Use appropriate tools: ScyllaHide, x64dbg plugins 5. Document findings: Keep notes on bypassed protections
Tool Recommendations
Anti-debug bypass: ScyllaHide, TitanHide
Unpacking: x64dbg + Scylla, OllyDumpEx
Deobfuscation: D-810, SATURN, miasm
VM analysis: VMAttack, NoVmp, manual tracing
String decryption: FLOSS, custom scripts
Symbolic execution: angr, TritonEthical Considerations
This knowledge should only be used for:
- Authorized security research
- Malware analysis (defensive)
- CTF competitions
- Understanding protections for legitimate purposes
- Educational purposes
Never use to bypass protections for: software piracy, unauthorized access, or malicious purposes.
---
Related skills
How it compares
Choose anti-reversing-techniques for offensive hardening of distributable binaries rather than SAST vulnerability scanning.
FAQ
What does anti-reversing-techniques do?
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 chall
When should I use anti-reversing-techniques?
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 chall
Is anti-reversing-techniques safe to install?
Review the Security Audits panel on this page before installing in production.