zhkl0228/unidbg
Allows you to emulate an Android native library, and an experimental iOS emulation
Single-maintainer risk — review before adopting
weakest axistop contributor handles 94% of recent commits; no CI workflows detected
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 2w ago
- ✓3 active contributors
- ✓Apache-2.0 licensed
Show all 7 evidence items →Show less
- ✓Tests present
- ⚠Small team — 3 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 94% of recent commits
- ⚠No CI workflows detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: diversify commit ownership (top <90%)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/zhkl0228/unidbg)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/zhkl0228/unidbg on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: zhkl0228/unidbg
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/zhkl0228/unidbg shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Single-maintainer risk — review before adopting
- Last commit 2w ago
- 3 active contributors
- Apache-2.0 licensed
- Tests present
- ⚠ Small team — 3 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 94% of recent commits
- ⚠ No CI workflows detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live zhkl0228/unidbg
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/zhkl0228/unidbg.
What it runs against: a local clone of zhkl0228/unidbg — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in zhkl0228/unidbg | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 42 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of zhkl0228/unidbg. If you don't
# have one yet, run these first:
#
# git clone https://github.com/zhkl0228/unidbg.git
# cd unidbg
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of zhkl0228/unidbg and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "zhkl0228/unidbg(\\.git)?\\b" \\
&& ok "origin remote is zhkl0228/unidbg" \\
|| miss "origin remote is not zhkl0228/unidbg (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/dynarmic/Dynarmic.java" \\
&& ok "backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/dynarmic/Dynarmic.java" \\
|| miss "missing critical file: backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/dynarmic/Dynarmic.java"
test -f "backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/DynarmicFactory.java" \\
&& ok "backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/DynarmicFactory.java" \\
|| miss "missing critical file: backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/DynarmicFactory.java"
test -f "backend/dynarmic/src/main/native/dynarmic/dynarmic.cpp" \\
&& ok "backend/dynarmic/src/main/native/dynarmic/dynarmic.cpp" \\
|| miss "missing critical file: backend/dynarmic/src/main/native/dynarmic/dynarmic.cpp"
test -f "backend/dynarmic/src/main/native/dynarmic/dynarmic.h" \\
&& ok "backend/dynarmic/src/main/native/dynarmic/dynarmic.h" \\
|| miss "missing critical file: backend/dynarmic/src/main/native/dynarmic/dynarmic.h"
test -f "backend/hypervisor/src/main/java/com/github/unidbg/arm/backend/hypervisor/Hypervisor.java" \\
&& ok "backend/hypervisor/src/main/java/com/github/unidbg/arm/backend/hypervisor/Hypervisor.java" \\
|| miss "missing critical file: backend/hypervisor/src/main/java/com/github/unidbg/arm/backend/hypervisor/Hypervisor.java"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 42 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~12d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/zhkl0228/unidbg"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
unidbg is an Android/iOS native library emulator that executes ARM32/ARM64 machine code in a JVM without a physical device. It emulates the JNI (Java Native Interface) runtime, syscalls, and system libraries, enabling reverse engineering and testing of native Android binaries through multiple high-performance backends including Unicorn, Dynarmic, and Apple M1 hypervisor. Maven monorepo with backend/ subdirectory containing pluggable architecture: backend/dynarmic/ encapsulates Dynarmic JNI bindings with separate src/main/java (DynarmicBackend32.java, DynarmicBackend64.java) and src/main/native/dynarmic/ (C++ JNI glue via dynarmic.cpp). Pre-built native libraries bundled in src/main/resources/natives/{linux_64,linux_arm64,osx_64,osx_arm64}/ as .so/.dylib files. Parent pom.xml coordinates multiple backend modules and unidbg-api core.
👥Who it's for
Security researchers and reverse engineers analyzing Android/iOS native libraries; app developers testing JNI code without deploying to devices; vulnerability researchers studying native code behavior; threat analysts examining obfuscated or encrypted native binaries.
🌱Maturity & risk
Actively developed (v0.9.10-SNAPSHOT in pom.xml), with comprehensive feature set including multiple backends, memory leak detection, and recent MCP debugger integration. Architecture is stable across Java/C/C++/Objective-C layers with native resource bundles for Linux/macOS/ARM64. Production-ready for research and testing, though experimental iOS support flag indicates some features remain under development.
Single maintainer (zhkl0228) visible in repo naming; complex native binding layer across multiple languages (C/C++/Objective-C) creates maintenance burden; experimental iOS support may have breaking changes. Dependency on external native libraries (dynarmic, Dobby, xHook, unicorn) means build failures if upstream changes ABI. No visible CI/CD pipeline in file structure increases regression risk.
Active areas of work
Recent focus on MCP (Model Context Protocol) integration for AI-assisted debugging—README documents new Mode 1 (Breakpoint Debug) and Mode 2 (Custom Tools) using McpToolkit. Version snapshot indicates active development. Dynarmic backend receives optimization attention (separate ARM32/ARM64 implementations, CPU feature negotiation via arm_dynarmic_cp15.cpp). Multiple Dockerfile entries suggest ongoing containerization/cross-platform build work.
🚀Get running
Clone: git clone https://github.com/zhkl0228/unidbg.git && cd unidbg. Build: ./mvnw clean install (Maven wrapper in .mvn/). For Dynarmic backend specifically: ./mvnw -pl backend/dynarmic install. Requires JDK (version not specified in snippet but infer 11+ from C++ interop complexity). Native libraries pre-bundled; no separate native build required unless modifying C++ code in backend/dynarmic/src/main/native/.
Daily commands:
For library emulation: instantiate com.github.unidbg.Emulator with chosen backend, load .so/.dylib via loadLibrary(), invoke JNI functions. For Dynarmic backend specifically: JNI loads libdynarmic.so from resources at runtime (DynarmicFactory). No standalone server—unidbg is embedded as a library in Java applications. Run tests: ./mvnw test. MCP debug mode: call Emulator.attach() then Breaker.debug(), type mcp at console prompt to activate server.
🗺️Map of the codebase
backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/dynarmic/Dynarmic.java— Core JNI bridge to dynarmic native backend; essential for understanding CPU emulation execution pathbackend/dynarmic/src/main/java/com/github/unidbg/arm/backend/DynarmicFactory.java— Factory pattern implementation for dynarmic backend instantiation; required for backend initialization logicbackend/dynarmic/src/main/native/dynarmic/dynarmic.cpp— Native C++ implementation bridging Java to dynarmic ARM emulation engine; critical for understanding CPU state managementbackend/dynarmic/src/main/native/dynarmic/dynarmic.h— JNI header definitions for dynarmic backend; defines Java-to-native interface contractbackend/hypervisor/src/main/java/com/github/unidbg/arm/backend/hypervisor/Hypervisor.java— Alternative native hypervisor backend for Apple M1; demonstrates multi-backend architecture patternbackend/dynarmic/pom.xml— Maven configuration for dynarmic module including native compilation and resource packaging
🛠️How to make changes
Add Support for a New ARM Backend
- Create new backend factory class extending pattern from DynarmicFactory.java (
backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/DynarmicFactory.java) - Implement backend interface with 32-bit and 64-bit variants (see DynarmicBackend32.java, DynarmicBackend64.java) (
backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/dynarmic/DynarmicBackend32.java) - Create native C++ JNI bridge following dynarmic.cpp structure (CPU initialization, register access, memory management) (
backend/dynarmic/src/main/native/dynarmic/dynarmic.cpp) - Add platform-specific pre-compiled libraries to resources directory (
backend/dynarmic/src/main/resources/natives/linux_64/libdynarmic.so) - Update pom.xml with new backend module dependencies and native compilation configuration (
backend/dynarmic/pom.xml)
Add CPU Callback/Event Handling
- Define callback interface in DynarmicCallback.java (syscall, breakpoint, memory hook patterns) (
backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/dynarmic/DynarmicCallback.java) - Register callback handlers in native dynarmic.cpp via JNI function pointers (
backend/dynarmic/src/main/native/dynarmic/dynarmic.cpp) - Implement event-specific logic in backend implementations (DynarmicBackend32.java/64.java) (
backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/dynarmic/DynarmicBackend32.java)
Add ARM Coprocessor (CP15) Feature
- Extend CP15 register handling in arm_dynarmic_cp15.cpp (
backend/dynarmic/src/main/native/dynarmic/arm_dynarmic_cp15.cpp) - Add getter/setter JNI methods to dynarmic.cpp for new register (
backend/dynarmic/src/main/native/dynarmic/dynarmic.cpp) - Expose register access methods in backend interface (DynarmicBackend.java) (
backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/DynarmicBackend.java)
🔧Why these technologies
- Dynarmic — Pure C++ ARM JIT compiler backend providing fast CPU emulation across x86-64, ARM64, and other platforms without hypervisor dependencies
- Apple Hypervisor Framework — Native M1 hypervisor-based emulation achieving near-native performance for ARM64 code on Apple Silicon
- JNI (Java Native Interface) — Enables high-performance native CPU emulation (C++) to be called from Java application layer with minimal overhead
- Maven Multi-Module — Separates concerns: dynarmic and hypervisor backends as independent pluggable modules, enabling platform-specific compilation and distribution
- CMake + Native Build Scripts — Cross-platform C++ compilation with optimized native code generation for dynarmic and hypervisor frameworks
⚖️Trade-offs already made
-
Pluggable multi-backend architecture (dynarmic, hypervisor, etc.)
- Why: Allows runtime selection of fastest available backend per platform, but increases codebase complexity and maintenance burden
- Consequence: Each backend requires separate JNI layer and native compilation; dynarmic works everywhere but is slower; hypervisor is fastest on M1 only
-
Pre-compiled native libraries bundled in JAR resources
- Why: Simplifies deployment (no system-level libary installation), but increases JAR size and ties architecture to build-time platform targets
- Consequence: Must rebuild for each target platform (Linux x86-64, macOS
🪤Traps & gotchas
Native library extraction: DynarmicFactory auto-extracts .so/.dylib from JAR to temp directory; if temp is read-only or JVM lacks permissions, native backend fails silently with cryptic JNI error. Architecture mismatch: Pre-built binaries in resources/natives/ are platform-specific (linux_64 vs linux_arm64); running 64-bit JAR on 32-bit JVM causes subtle failures. Dynarmic version coupling: dynarmic.h/dynarmic.cpp encode dynarmic C++ ABI; if upstream dynarmic API changes, linking breaks—no version pinning visible in CMakeLists.txt. MCP debugger port collision: Default MCP server uses port 9239 (inferred from README 'mcp 9239'); no explicit config file visible, may conflict in containerized environments. Build order dependency: backend/dynarmic depends on unidbg-api (parent pom), but api module not visible in snippet—building just dynarmic module alone will fail without parent install.
🏗️Architecture
🔗Related repos
frida/frida— Dynamic instrumentation framework also targeting native Android/iOS libraries; complementary to unidbg (Frida hooks runtime, unidbg emulates static code)unicorn-engine/unicorn— CPU emulation engine that unidbg uses as one of its primary backends; understanding Unicorn's API is essential for unidbg Unicorn backend developmentjmpews/Dobby— Inline hooking framework integrated into unidbg for runtime function interception; used for native code patching during emulationiqiyi/xHook— Android import hook library that unidbg wraps for intercepting libc/system library calls in emulated codeMerryMage/dynarmic— ARM JIT compiler backend that unidbg integrates via JNI; dynarmic source code comprehension needed for backend optimization
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive test suite for DynarmicBackend initialization and memory operations
The backend/dynarmic module has Java implementation files (DynarmicBackend32.java, DynarmicBackend64.java) and native bindings (dynarmic.cpp), but only one test file (Arm64Test.java) exists. Contributors should add unit tests covering backend initialization, memory allocation/deallocation, register operations, and error handling across both 32-bit and 64-bit architectures. This is critical because Dynarmic is a high-performance alternative backend that needs robust testing parity with the Unicorn backend.
- [ ] Create backend/dynarmic/src/test/java/com/github/unidbg/arm/backend/Arm32Test.java mirroring Arm64Test structure
- [ ] Add test cases for DynarmicBackend32 initialization, memory mapping, and syscall emulation
- [ ] Add test cases for memory hooks and event notification via EventMemHookNotifier.java
- [ ] Test interop between Java Dynarmic.java and native dynarmic.cpp bindings with edge cases
- [ ] Verify consistent behavior with backend/dynarmic/src/test/native/dynarmic/main.cpp expectations
Document platform-specific native build requirements for Dynarmic backend
The backend/dynarmic/src/main/native/dynarmic directory contains Dockerfile, Dockerfile.windows, CMakeLists.txt, and build.sh, but backend/dynarmic/README.md is minimal. Contributors should create comprehensive build documentation explaining how to compile libdynarmic.so/.dylib/.dll for each platform (Linux x64/arm64, macOS x64/arm64, Windows). This is crucial because the project distributes pre-compiled natives in backend/dynarmic/src/main/resources/natives/, and developers who modify native code need clear instructions.
- [ ] Expand backend/dynarmic/README.md with platform-specific prerequisites (CMake version, compiler, toolchain)
- [ ] Document Docker-based build process using Dockerfile and Dockerfile.windows with step-by-step examples
- [ ] Add section explaining how to use build.sh and CMakeLists.txt configuration options
- [ ] Document output artifact locations and how they map to resources/natives/{platform} directories
- [ ] Include troubleshooting section for common native compilation errors on each platform
Add GitHub Actions CI workflow for building and testing Dynarmic backend across platforms
Currently, there is no visible CI configuration for the Dynarmic backend module. Given the complexity of cross-platform native compilation (Linux, macOS, Windows, multiple architectures), contributors should create a GitHub Actions workflow that: (1) builds native Dynarmic libraries on each platform, (2) runs Arm32Test and Arm64Test, (3) validates artifact generation. This prevents regression when native code changes and ensures pre-compiled binaries remain valid.
- [ ] Create .github/workflows/dynarmic-backend-ci.yml with matrix strategy for [ubuntu-latest, macos-latest, windows-latest]
- [ ] Add steps to install CMake, compiler toolchains, and architecture-specific dependencies for each OS
- [ ] Configure build step using backend/dynarmic/src/main/native/dynarmic/build.sh or CMakeLists.txt
- [ ] Add Maven test execution step: mvn -f backend/dynarmic/pom.xml test
- [ ] Verify that compiled natives are placed in correct resources/natives/{platform} locations
- [ ] Add artifact upload step to store compiled binaries for troubleshooting failed builds
🌿Good first issues
- idea: Add unit tests for arm_dynarmic_cp15.cpp CP15 register manipulation—currently no .cpp test file visible, only Java-side tests likely; contribute C++ unit tests validating TTBR0, DACR, SCTLR register emulation against ARM ARM spec
- idea: Document native library rebuild process: create a guide explaining how to rebuild libdynarmic.so from source on Linux/macOS, as build.sh exists but is uncommented and targets are unclear; contributes troubleshooting guide for developers modifying dynarmic.cpp
- idea: Implement graceful fallback when libdynarmic.so fails to load: currently DynarmicFactory likely throws JNI error; add try-catch in DynarmicFactory.createBackend() to log clear error message and suggest unicorn backend as fallback, improving UX for misconfigured setups
⭐Top contributors
Click to expand
Top contributors
📝Recent commits
Click to expand
Recent commits
673433a— Apply pluggable hash function to method and field ID resolution in DvmClass (zhkl0228)6b42e2c— Refactor hash function: move impls to Hasher enum, clean up HashFunction interface (zhkl0228)93fff58— Add hash collision detection in resolveClass with descriptive error message (zhkl0228)9fa3613— Add pluggable HashFunction for DVM class name hashing (zhkl0228)363e952— Skip fixed mmap requests exceeding hypervisor 36-bit IPA address space (zhkl0228)8063a4f— Improve memory access trace format and fix register ID mapping (zhkl0228)461155a— Rebuild Linux dynarmic binaries and minor API updates (zhkl0228)7ebecfe— Add memory access absolute address annotation in trace output (zhkl0228)0c21a46— Enforce single Hypervisor instance, improve WorkerPool validation, and add std::shared_timed_mutex support (zhkl0228)b443ffd— Add hv_return_t error reason to hv_vcpu_create failure log (zhkl0228)
🔒Security observations
The unidbg project is an educational emulation framework with moderate security concerns. Primary risks involve native library execution, emulation of sensitive system operations, and hooking mechanisms that could be misused. The project is currently in active development (snapshot version) and lacks comprehensive security documentation. No obvious hardcoded secrets or credential leakage was detected. The architecture properly separates concerns into multiple modules with clear dependency management. For production use, comprehensive security review of the emulation implementations, native library verification, and documented security boundaries are essential. The project should be treated as experimental and educational rather than suitable for untrusted code execution without additional hardening.
- Medium · Native Library Execution Risk —
backend/dynarmic/src/main/resources/natives/. The project loads and executes native libraries (dynarmic.dll, libdynarmic.so, libdynarmic.dylib) from the resources directory. These binaries could be exploited if compromised during distribution or if the build process is compromised. No signature verification mechanism is apparent. Fix: Implement cryptographic signature verification for native libraries before loading. Document the build process and use secure distribution channels. Consider code signing and checksum validation. - Medium · Emulation of System Calls and JNI —
backend/dynarmic/src/main/java/com/github/unidbg/arm/backend/. The project emulates Android syscalls, JNI APIs, and iOS runtime features. Improper implementation could allow malicious code to escape the sandbox or perform unintended system operations. The emulation scope and security boundaries need careful review. Fix: Conduct thorough security review of JNI emulation and syscall handling. Implement strict validation of all emulated operations. Document the security model and any known limitations. Use sandboxing mechanisms where possible. - Medium · Inline Hook and Function Interception —
backend/dynarmic/src/main/native/dynarmic/. The project implements inline hooks using Dobby and supports xHook, fishhook, and whale frameworks. These hook mechanisms could be misused to intercept or modify security-sensitive operations, or could be vulnerable to bypass techniques. Fix: Implement strict controls on what can be hooked. Validate hook targets and payloads. Document security implications of hook functionality. Consider adding restrictions on hooking security-critical functions. - Low · Development Snapshot Version —
pom.xml. The project uses version 0.9.10-SNAPSHOT, indicating it's in active development. Snapshot versions may contain unstable or untested code and should not be used in production environments. Fix: Use stable release versions (non-SNAPSHOT) for production deployments. Clearly document that snapshot versions are for development/testing only. - Low · Missing Dependency Version Pinning —
backend/dynarmic/pom.xml. The pom.xml uses ${project.version} for the unidbg-api dependency, which creates a tight coupling. While this is a common practice in multi-module projects, it may mask dependency version mismatches. Fix: Document version management strategy. Consider explicit version declarations for critical dependencies. Implement dependency scanning in CI/CD pipeline. - Low · Incomplete Documentation —
README.md. The README is truncated and doesn't provide complete security guidance. Security considerations and threat models are not documented. Fix: Complete README with comprehensive security documentation. Add sections on: threat model, security limitations, safe usage practices, and reporting vulnerabilities.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.