PluginBench
Skill
Fail
Audit score 45

rev-unicorn-debug

p4nda0s/reverse-skills

Debug and emulate code fragments using the Unicorn engine with environment simulation.

What is rev-unicorn-debug?

A reverse-engineering skill for emulating specific functions or code fragments in isolation using the Unicorn CPU emulator. Use it to trace binary execution, decrypt algorithms, or bypass environment dependencies (JNI, syscalls, libc) without running the full program.

  • Emulate isolated code fragments and functions using Unicorn's CPU emulation engine
  • Hook and simulate external dependencies (libc, JNI, syscalls, C++ runtime) through callback mechanisms
  • Trace binary execution at block or instruction level with minimal overhead
  • Auto-map missing memory pages and recover from unmapped access errors
  • Support multiple architectures (ARM64, ARM32, x86-64, x86-32, MIPS32) with architecture-specific register and calling-convention handling

How to install rev-unicorn-debug

npx skills add https://github.com/p4nda0s/reverse-skills --skill rev-unicorn-debug
Prerequisites
  • Unicorn emulation engine (unicorn Python bindings)
  • Python 3.6+
  • Binary file or raw code bytes to emulate
  • Understanding of target architecture (ARM, x86, MIPS) and calling conventions
Claude Code
Cursor
Windsurf
Cline

How to use rev-unicorn-debug

  1. 1.Load the target binary or code fragment as raw bytes into Unicorn memory
  2. 2.Identify external dependencies (libc calls, JNI, syscalls) in the target function
  3. 3.Register hook callbacks for each dependency using UC_HOOK_CODE or UC_HOOK_INTR
  4. 4.Set up initial register state (SP, arguments, return address) according to the target architecture
  5. 5.Run emulation and use callback output to diagnose crashes or missing mappings
  6. 6.Iteratively add memory mappings or fix hooks until the target function completes successfully

Use cases

Good for
  • Decrypt or decode data by emulating the algorithm in isolation without full binary execution
  • Analyze and debug a specific function's behavior by tracing its register and memory state
  • Reverse-engineer obfuscated code by stepping through execution with hooks on key operations
  • Test binary code fragments across different architectures without setting up full runtime environments
  • Bypass environment constraints (missing JNI implementations, unavailable syscalls) during analysis
Who it's for
  • Reverse engineers and malware analysts
  • Security researchers performing binary analysis
  • Developers debugging architecture-specific code in isolation
  • CTF competitors analyzing compiled binaries

rev-unicorn-debug FAQ

Should I parse ELF/PE headers or load the binary as raw bytes?

Load as raw bytes first and map directly into Unicorn memory. Only parse headers minimally if raw loading fails due to code referencing specific segment addresses.

How do I handle external function calls like malloc or JNI functions?

Hook the function's address using UC_HOOK_CODE callbacks and implement the simulation logic in Python (e.g., a bump allocator for malloc, or a fake JNIEnv function table in memory).

What should I do when emulation crashes with an unmapped memory error?

Use the callback output to identify the faulting address and type (fetch/read/write), then map the missing page or add a hook for the unhandled function call.

Which callback type should I use for tracing?

Prefer UC_HOOK_BLOCK for block-level tracing over UC_HOOK_CODE for instruction-level tracing. Only enable instruction tracing on small targeted ranges to minimize overhead.

How do I set up the correct calling convention for different architectures?

Refer to the architecture quick reference in the skill documentation: ARM64 uses X0-X7 for arguments and X0 for return; x86-64 uses RDI, RSI, RDX, RCX, R8, R9; ARM32 uses R0-R3; x86-32 and MIPS32 pass arguments on the stack or via registers as per their ABI.

Full instructions (SKILL.md)

Source of truth, from p4nda0s/reverse-skills.


name: rev-unicorn-debug description: Debug and emulate specific code fragments or functions using the Unicorn engine. Activate when the user wants to emulate a function with Unicorn, trace binary execution without running the full program, decrypt or decode data by emulating the algorithm, or bypass environment dependencies (JNI, syscalls, libc) during emulation.

rev-unicorn-debug - Unicorn Emulation Debugger

Debug and emulate specific code fragments or functions using the Unicorn engine. Analyze context dependencies (JNI, syscalls, library functions) and simulate them through hook mechanisms to complete the user's debugging goal.


Core Principles

  1. Load file raw first — do NOT parse ELF/PE/Mach-O headers. Read the file as raw bytes and map directly into Unicorn memory. We only need to emulate specific functions, not the entire binary. If raw loading fails (code references segments at specific addresses), then parse minimally — only map the segments needed.
  2. Identify context dependencies — analyze the target code for external calls (JNI, syscalls, libc, imports) and hook them to provide simulated responses.
  3. Use callbacks extensively — leverage Unicorn's hook system for debugging, tracing, error recovery, and environment simulation.
  4. Iterative fix — when emulation crashes, use the callback info to diagnose and fix (map missing memory, hook unhandled calls, fix register state).
  5. Minimal trace output — prefer block-level tracing over instruction-level. Only enable instruction trace on small targeted ranges. Use counters and summaries instead of per-step logging.

Environment Simulation Strategy

Before emulating, read the target function and identify what it calls. Hook external dependencies by address and simulate in Python:

CategoryExamplesSimulation Strategy
libcmalloc, free, memcpy, strlen, printfHook address, implement logic in Python (bump allocator for malloc)
JNIGetStringUTFChars, FindClass, GetMethodIDBuild fake JNIEnv function table in UC memory, write RET stubs at each entry, hook stub addresses
Syscallsread, write, mmap, ioctlHook UC_HOOK_INTR, dispatch by syscall number
C++ runtimeoperator new, __cxa_throwHook and simulate
Library callspthread_mutex_lock, dlopenHook and return success/stub

Hook pattern: Register a UC_HOOK_CODE callback. When PC hits a known import address, execute the Python simulation, then set PC = LR to skip the original function.


Callback Types to Use

CallbackPurpose
UC_HOOK_CODEIntercept import calls by address; instruction-level trace (use sparingly, narrow range only)
UC_HOOK_BLOCKBlock-level trace (preferred over instruction trace)
UC_HOOK_MEM_UNMAPPEDAuto-map missing pages to recover from unmapped access errors
UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITETrace memory access on targeted data ranges only
UC_HOOK_INTRIntercept SVC/INT for syscall simulation

Iterative Debugging Workflow

When emulation fails, follow this loop:

  1. Run — start emulation, let it crash
  2. Read callback output — which address faulted? What type (read/write/fetch)?
  3. Diagnose:
    • Unmapped memory fetch → missing code page, map it
    • Unmapped memory read/write → missing data section or uninitialized pointer, map or hook
    • Hitting an import stub → identify the function, add a simulation hook
    • Infinite loop → add a code hook with execution counter, stop after threshold
  4. Fix — add the hook / map the memory / adjust registers
  5. Re-run — repeat until the target function completes

Architecture Quick Reference

ArchUc ConstModeSPLRArgsReturnSyscall
ARM64UC_ARCH_ARM64UC_MODE_LITTLE_ENDIANSPX30X0-X7X0X8 + SVC #0
ARM32UC_ARCH_ARMUC_MODE_THUMB / UC_MODE_ARMSPLRR0-R3R0R7 + SVC #0
x86-64UC_ARCH_X86UC_MODE_64RSP(stack)RDI,RSI,RDX,RCX,R8,R9RAXRAX + syscall
x86-32UC_ARCH_X86UC_MODE_32ESP(stack)(stack)EAXEAX + int 0x80
MIPS32UC_ARCH_MIPSUC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN$sp$ra$a0-$a3$v0$v0 + syscall