Languages: English | 简体中文 | 繁體中文 | 日本語 | 한국어 | Français | Deutsch | Español | Italiano | Русский | العربية
The AI-friendly binary analysis & decompilation engine — 1:1 lift, built on LLVM
PE · ELF · Mach-O · EVM · Solana SBF | x86-64 · i386 · AArch64 · ARM32 · EVM256 · SBF | C + Python SDKs
GitHub always shows this English
README.mdon the repository homepage. Use the language links above for localized versions.
NeverD is a native and smart-contract analysis/decompilation engine built around 1:1 instruction-level lifting. It loads PE, ELF, Mach-O, legacy EVM bytecode, and Solana SBF ELF programs. Native targets decode with Capstone; EVM and SBF use dedicated version-aware decoders and staged IR. Every path uses hand-written semantics rather than approximate translation. Supported instructions preserve their observable behavior in LLVM IR, C, Rust for SBF, Solidity-oriented EVM reconstruction, or—on native targets—a rewritten binary.
Strict mode is on by default. An instruction with no lifter throws UnliftedInstruction instead of skipping, guessing, or emitting a silent NOP.
CLI tools, integrators, and AI agents use one engine — libneverd — through a pure C API. They do not link Capstone, LLVM, or internal C++ directly.
Input formats, host contracts, and limitations are documented in the EVM guide and Solana SBF guide.
- 1:1 semantics — hand-written lifters; unsupported opcodes throw under default strict mode
- LLM-friendly — structured C, LLVM IR, and JSON analysis through a pure C API with deterministic errors
- One pipeline, multiple exits —
lift→ LLVM IR ·decompile→ C/Solidity/Rust ·patch→ rewritten native binary - Binary rewrite — PE / ELF / Mach-O with section trampolines or in-place overwrite
- Analysis toolkit — CLI, debug info, signatures, plugins, and optional obfuscation passes
| x86-64 | i386 | AArch64 | ARM32 | |
|---|---|---|---|---|
| PE (Windows) | ✓ | ✓ | ✓ | ✓ |
| ELF (Linux / Android) | ✓ | ✓ | ✓ | ✓ |
| Mach-O (macOS / iOS) | ✓ | ✓ | ✓ | ✓ |
Every cell is implemented, but integration depth differs. See the architecture coverage matrix. Mach-O i386 uses thin relocatable objects because modern macOS cannot link historical i386 executables.
Legacy EVM bytecode is supported independently of native containers: all 150 assigned opcodes through Fusaka feed dedicated Low/Med/High IR, verified LLVM i256, C23 _BitInt(256), and Solidity output. See EVM decompilation.
Solana SBF v0-v4 ELF programs use a dedicated strict loader, complete versioned ISA metadata, Low/Med/High IR, verified LLVM, portable C11, and safe stable Rust. See Solana SBF decompilation.
Binary (PE / ELF / Mach-O)
→ Loader + DebugInfo
→ Capstone decode
→ LowIR architecture-neutral NdOps · CFG
→ MedIR types · ABI · calls · memory · SSA
│
├─ lift MedIR → LLVM IR
├─ decompile MedIR → HighIR → C
│ MedIR → LLVM IR → opt → C (-llvm)
└─ patch MedIR → LLVM IR → codegen → binary
EVM (raw / hex / compiler artifact)
→ runtime normalization + hardfork-aware decode
→ EVM LowIR → EVM stack-SSA MedIR → recovered EVM HighIR
├─ lift → verified LLVM i256/i512
└─ decompile → C23 _BitInt(256) or Solidity reconstruction
Solana SBF ELF (v0-v4)
→ version-aware legacy/strict loader + verifier
→ SBF LowIR → normalized MedIR → recovered SBF HighIR
├─ lift → verified LLVM i64 runtime ABI
└─ decompile → portable C11 or safe stable Rust
| Stage | Role |
|---|---|
| LowIR | ~77 NdOp opcodes + CFG |
| MedIR | Types, calling conventions, memory model, SSA |
| HighIR | Structured control flow (if / while / for) |
| LLVM | Optimize, emit C, or codegen machine code |
git submodule update --init --recursive
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build
# Pipeline
./build/bin/neverd lift -o out.ll binary
./build/bin/neverd decompile -o out.c binary
./build/bin/neverd patch -hello -o patched binary
# EVM
./build/bin/neverd lift contract.evm -o contract.ll
./build/bin/neverd decompile --language=c contract.evm -o contract.c
./build/bin/neverd decompile --language=solidity contract.evm -o contract.sol
# Solana SBF
./build/bin/neverd info program.so
./build/bin/neverd lift program.so -o program.ll
./build/bin/neverd decompile --language=c program.so -o program.c
./build/bin/neverd decompile --language=rust program.so -o program.rs
# Analysis
./build/bin/neverd funcs binary
./build/bin/neverd disasm --func 0x401000 binary
./build/bin/neverd sym-explore --func 0x401000 --expressions binary
./build/bin/neverd audit binary
./build/bin/neverd hunt binary
./build/bin/neverd sigs --auto binarySignature libraries are installed to build/bin/signatures/ at build time. sigs --auto selects the matching set from format, architecture, and bitness.
Requirements: CMake ≥ 3.20 · Ninja · C++20 compiler · Git submodules (LLVM fork + Capstone)
git submodule update --init --recursive
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build buildThe first configure builds the LLVM fork locally (often 30–60 minutes). Later builds are incremental. Presets: CMakePresets.json → release / relwithdebinfo / debug.
Prebuilt LLVM · artifacts · tests · CMake options
Prebuilt LLVM
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DNEVERD_LLVM_PREBUILT=ON \
-DNEVERD_LLVM_PREBUILT_TAG=neverd-llvm-v23.0.0-r1
cmake --build buildNeverD's normal push and pull-request CI deliberately builds the LLVM submodule
from source. When manually running the CI workflow, select
use_prebuilt_llvm to validate the published packages; only a manually
selected true enables prebuilt LLVM. Leaving it unchecked keeps the same
source-build path as automatic CI.
Published packages are selected from the host running CMake:
| Host | Release asset |
|---|---|
| macOS arm64 | neverd-llvm-macos-arm64.tar.xz |
| Linux x86_64 | neverd-llvm-linux-x86_64.tar.xz |
| Windows x64 | neverd-llvm-windows-x64.zip |
Each archive is checked against the digest pinned in
cmake/NeverDLLVMPrebuilt.cmake — or its published .sha256 file, for a tag
those pins do not describe — before extraction under
~/.cache/neverd-llvm/<tag>/<arch>/ (or the path set by
NEVERD_LLVM_PREBUILT_CACHE_DIR). For the pinned default, the package's
BUILDINFO.txt must also name the exact LLVM submodule commit. The release
build uses ccache on macOS and Linux. Windows clang-cl builds use sccache with
the GitHub Actions cache backend; compiler caches only accelerate rebuilds and
are never published as release assets.
The default uses the package revision neverd-llvm-v23.0.0-r1; unlike the
legacy mutable base tag, its Git tag, release target, source commit, and three
archive digests form one revisioned source pin that NeverD treats as
immutable. Existing build directories still caching the legacy default move
to r1 automatically unless they also provide an explicit
NEVERD_LLVM_PREBUILT_SHA256 override. The Prebuilt LLVM Audit workflow runs
on pushes, pull requests, and every six hours. It invokes
scripts/audit_prebuilt_llvm_release.py to compare that source pin with the
live GitHub release and each published checksum sidecar.
If the LLVM fork changes while LLVM still reports 23.0.0, publish the next
package revision—neverd-llvm-v23.0.0-r2, then -r3—rather than overwriting
an existing release or inventing LLVM version 23.0.1:
gh workflow run neverd-release.yml \
--repo NeverSight/llvm-project \
--ref main \
-f release_tag=neverd-llvm-v23.0.0-r2 \
-f overwrite_existing_assets=falseAfter the workflow succeeds, update the default tag, pinned commit, and all
three digests in cmake/NeverDLLVMPrebuilt.cmake together. A fresh package is
then cached below .cache/neverd-llvm/neverd-llvm-v23.0.0-r1, while a stale or
republished archive fails before extraction. overwrite_existing_assets
exists only for legacy recovery; the normal revision workflow leaves it off.
Artifacts
| Path | Description |
|---|---|
build/bin/neverd |
Unified CLI |
build/bin/neverd-bench |
Benchmark harness (JSON timings) |
build/bin/neverd-sigmaker |
.pat generator from static libraries |
build/bin/libneverd.* |
Engine shared library |
build/bin/sdk/ |
Canonical C SDK include root; use <neverd/sdk/NeverDCAPI.h> or <neverd/sdk/NeverDPlugin.h> with the neverd/sdk/ hierarchy preserved |
build/bin/sdk/python/ |
Typed Python plugin package and examples |
build/bin/signatures/ |
Bundled signature libraries |
Tests
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON
cmake --build build --target check-neverd| Target | Description |
|---|---|
check-neverd |
All tests |
check-neverd-semantic |
Semantic roundtrip only (Unicorn) |
See Testing NeverD for focused targets, CTest labels, fixture requirements, and the cross-format rewrite grid.
CMake options
| Option | Default | Description |
|---|---|---|
NEVERD_LLVM_PREBUILT |
OFF |
CI prebuilt LLVM |
NEVERD_BUILD_SHARED |
ON |
Build libneverd |
NEVERD_ENABLE_PYTHON_PLUGINS |
ON |
Embed CPython 3.10+ plugin support |
NEVERD_BUILD_PLUGINS |
OFF |
Example plugins |
BUILD_TESTING |
OFF |
Unit tests |
neverd <command> [options] <binary>
| Command | Output | Description |
|---|---|---|
lift |
.ll |
Lift to LLVM IR |
decompile |
.c / .sol / .rs |
C, EVM Solidity, or SBF Rust selected with --language |
decompile -llvm |
.c |
Via LLVM IR + optimizer |
patch |
binary | Rewrite machine code |
neverd patch -hello -o patched binary
neverd patch --from-ir repl.ll -o patched binary
neverd patch --from-c repl.c --func 0x401000 -o patched binary
neverd patch --mode inplace -o patched binary
neverd patch --subst --flatten --mba -o patched binaryAnalysis commands
| Command | Purpose |
|---|---|
info / dashboard / headers |
Metadata and overview |
funcs |
Discovered functions |
disasm |
Disassemble (--func name or hex) |
sym-explore |
Bounded native LowIR path exploration (--func; JSON output) |
audit |
Heap-lifetime defects and uninitialized local stack reads (JSON) |
hunt |
Dangerous-copy overflows with symbolic witnesses and additive process-input-v1 replay evidence when a complete plan is available (JSON schema v1) |
hex |
Hex dump at an address |
cfg / callgraph |
CFG / call graph (JSON; DOT/SVG optional) |
xrefs |
Cross-references |
strings / search |
Strings / byte or text search |
imports / exports / symbols / relocs |
Tables |
segments / sections / entrypoints |
Layout |
diff |
Compare two binaries (-a / -b) |
sigs |
Signature patterns (--auto) |
rename / annotate / bookmarks |
Session markup |
export |
Export results |
plugins |
List or run plugins |
Most analysis commands accept --json.
Integrators use the pure C API from libneverd:
| Header | Role |
|---|---|
NeverDCAPI.h |
Session, lift, decompile, patch, IR / CFG, annotations |
NeverDPlugin.h |
Dynamic-library plugin ABI |
neverd_session_t s = neverd_session_create();
neverd_session_load(s, "binary.exe");
neverd_session_analyze(s);
const char *c = neverd_decompile(s, 0x401000);
neverd_free_string(c);
neverd_session_destroy(s);For EVM, use neverd_decompile_all_ex(..., NEVERD_OUTPUT_SOLIDITY, ...) to
select Solidity explicitly; legacy neverd_decompile_all continues to emit C.
See the EVM C API examples.
Native shared libraries and Python .py files use the same plugin lifecycle.
Build the native example with -DNEVERD_BUILD_PLUGINS=ON; see the
native plugin guide for the pure-C descriptor, callbacks,
build/link steps, discovery, CLI workflow, and ABI constraints. Python support
is on by default and can be removed completely with
-DNEVERD_ENABLE_PYTHON_PLUGINS=OFF; the
Python plugin guide covers its typed SDK and package
workflow. Both kinds use <neverd-dir>/plugins, ~/.neverd/plugins, and
$NEVERD_PLUGIN_PATH.
| Component | Role | Source |
|---|---|---|
| LLVM (fork) | IR, optimize, codegen, diagnostics | third_party/llvm-project or prebuilt |
| Capstone | Decode | third_party/capstone |
Third-party components keep their own licenses.
Development is integrated on the dev branch. See
CONTRIBUTING.md for setup, Release versus Debug guidance,
style, targeted tests, and pull-request expectations. The
architecture and testing guides map
common changes to their owning code and verification suites.
LLVM components retain their Apache-2.0 WITH LLVM-exception license. Capstone retains its own license.