Docs  /  Guides

Frequently Asked Questions

Repository: https://github.com/ECLS-Studio/rerius


General#

Q: What is Rerius?

Rerius is a binary analysis framework written in C99 with zero external dependencies. It disassembles ELF, PE, and Mach-O binaries for x86-64, AArch64, and RISC-V; builds control-flow graphs; detects entropy anomalies; recursively follows code; validates instructions; lifts to a typed SSA-based IR ("NR" internally); symbolically executes; and emulates ARM64/RISC-V concretely. It ships both a CLI tool and a Node.js native addon.


Q: What platforms does it run on?

Linux (x86-64, ARM64), Android/Termux (AArch64), macOS (ARM64, x86-64), FreeBSD, OpenBSD. Windows support is partial (builds with MinGW but less tested).


Q: Does it run on Android?

Yes. Termux is a first-class target. pkg install nodejs clang make git && cd Rerius && make builds both the CLI and JS addon.


Q: Does Rerius execute the binaries it analyzes?

No: except for the -I emulator flag, which runs a concrete instruction-by-instruction interpreter with software checks against process spawning, network access, and out-of-bounds memory access (see EMULATOR.md for exactly what those checks do and don't cover). All other analysis (CFG, entropy, RDA, IVF, symbols, xrefs) is purely static and never runs any part of the target binary.


Q: Why C99 with no dependencies?

To be portable across the range of environments reverse engineering happens in: Rerius runs on older Linux distributions, Android/Termux, BSD, and similar setups without requiring a package manager or internet access. A stripped binary that needs analysis may come from an environment where you can't apt install capstone.


Build#

Q: make says open_memstream not found.

open_memstream is POSIX but requires Linux glibc ≥ 2.10 or macOS ≥ 10.13. On older systems, use a newer distro or Termux.

Q: Why does Clang reject auto nested functions?

auto nested functions are a GCC extension: not valid C99. The current codebase doesn't use them; if you hit this, check you're building from the latest tagged release and not an old checkout or fork.

Q: The JS addon crashes immediately after build.

Check the Node.js major version used to compile matches the one running it. Rebuild with JS mode in setup.sh or npm run rebuild after switching Node versions.

Q: log2 undefined / linker error.

The entropy module uses log2() from <math.h>. setup.sh (not the top-level Makefile) sets LDFLAGS to include -lm. Check with grep LDFLAGS setup.sh.


Analysis#

Q: CFG shows dead bytes as instructions (dw, v_15, etc.).

This happens when the binary uses jump tricks or opaque predicates: unconditional branches followed by bytes that were never meant to be decoded as instructions, placed there to confuse linear disassemblers. Rerius's two-pass CFG builder pre-registers branch targets and skips these dead-byte regions rather than decoding through them; if you still see this, check docs/CLI_REFERENCE.md for whether -C picked up the function correctly.

Q: What is AIRE and when should I use it?

--aire stands for "Assisted Intelligence Reverse Engineering" in the source: despite the name, it's rule-based heuristic pattern matching over the accumulated analysis state, not a trained model. It synthesizes prior analysis results (IVF, poly map, SMC data, entropy) into a ranked list of observations with confidence scores. Run it after other passes (-V, --poly, -I) to get a synthesized read of what the binary is likely doing. It's most useful as a starting point when you don't yet know what kind of obfuscation, if any, a binary uses: treat its output as leads to investigate, not conclusions.

Q: What does AIRE's Context block tell me?

After printing the ranked insight list, AIRE tallies which category (vm-dispatch, smc, poly, anti-debug, packer, etc.) had the most hits and prints a one-line description of the dominant pattern. If it says "Focus: VM interpreter / dispatch loop", that's a suggestion to start by tracing the dispatch function rather than, say, hunting for packed sections: not a certainty about what the binary does.

Q: What does AIRE's Next Steps block tell me?

Up to three shell commands chosen based on the dominant category detected. For vm-dispatch, that's typically run vt / cfg <func> / xrefs <addr>. For packer, it's typically entropy / run vt / cfg <entry>. These are picked from what AIRE found in this run, not a fixed generic list.

Q: What is .aire_memory and can I delete it?

.aire_memory is written to the working directory after AIRE runs. It stores up to 32 entries keyed by binary SHA-256: run count, timestamp, dominant category, top insight, and last interactive command: used to show a "memory recall" banner the next time you analyze the same binary. Deleting it is safe; AIRE just starts fresh.

Q: AIRE shows a Memory recall banner but I have never analyzed this binary before.

The SHA-256 of the binary matched an existing .aire_memory entry: this happens if you've analyzed a byte-identical copy from a different path (the key is content-based, not path-based), or if the file is shared/reused from an earlier session.

Q: Unicode scanner shows CJK-looking characters for normal ASCII binaries.

The UTF-16LE scanner requires codepoints above U+02FF and a preceding 0x00 byte as a string boundary marker, and skips .dynstr/.dynsym, specifically to cut down on this kind of false positive on typical ELF binaries. If you're still seeing a lot of false positives, it's worth filing a bug with the binary's format/architecture: see UNICODE_DETECTION.md for how the filter works and what it doesn't catch.

Q: Entropy scan shows HIGH for my .text section: is it packed?

Not necessarily. Fixed-width instruction architectures (AArch64's 4-byte instructions) tend to read as higher entropy than variable-length x86-64 code. A .text section around 5.5–6.5 bits/byte is unremarkable for ARM64. Values at or above 7.0 are a stronger signal worth investigating further.

Q: Recursive descent shows 60% coverage: is that bad?

Not on its own. 60–80% is common. Uncovered bytes are typically alignment padding between functions, switch-table data embedded in .text, jump-trick dead bytes, or genuinely unreachable error paths. Very low coverage (well under 40%) is a signal worth investigating for heavy obfuscation, not proof of it by itself.

Q: Decompiler / SSA-NR output says nop/... for most lines.

The lifter covers the common ARM64 and RISC-V integer instruction set (mov/movk/movn, add, sub, mul, div, and, or, eor/xor, lsl, lsr, ror, sign/zero-extend, ldr, str, bl, blr, ret, svc, mrs, cmp, cbz, tbz, and conditional branches). Unsupported instructions (SIMD/NEON, crypto extensions) emit nop placeholders instead of being lifted. If most of a function shows as nop, it's likely SIMD-heavy code the lifter doesn't yet model.

Q: What is the difference between DSA and NR (SSA)?

SSA/NR is a static lift: it models code structure, inferred types, and direct call relationships from the binary alone, without running anything. DSA (Dynamic Single Assignment) extends this with concrete values observed during an emulation trace. Use SSA/NR to read structure; use DSA (after running -I to generate trace data) to look at what values a definition actually took at runtime and spot patterns like opaque predicates. Run --dsa or dsa <func> in the interactive shell.

Q: The poly map shows xor-mutation-loop: what does that mean?

The scanner found a pattern where a value is loaded (ldr), XOR'd with a key (eor), then stored back (str) to an address inside an executable section: a common shape for a self-decrypting code stub. If this pattern is real, the code that eventually executes there differs from what's on disk at that address. Run -I (emulator) to observe the bytes as decoded at runtime, or -P (symexec) to track the write symbolically; treat the poly-map label itself as a hint to investigate, not a confirmed finding.

Q: Symbolic execution says (x0_sym + 0x7) ^ 0x55: what does that mean?

The return value depends on the input register x0 (the first argument), and couldn't be evaluated to a concrete number because x0's value wasn't known at analysis time: the expression is the formula relating output to input. Use .emulate(idx, {'0': 42n}) (or -I with initial registers) to evaluate it for a specific input.


JavaScript / npm#

Q: require('rerius') throws "native addon not found".

Run npm run build or bash build_js.sh from the Rerius root. The addon is compiled on-device: see BUILDING.md if the build itself fails.

Q: Can I use Rerius in a browser?

No. Rerius is a native Node.js addon (.node file) and can't run in a browser directly. The REST server (js/server/server.js) can act as a backend that a browser frontend talks to over HTTP.

Q: JSON.stringify throws "BigInt not serializable".

Addresses in the JS API are bigint, which JSON.stringify doesn't handle by default. Convert them with a replacer:

const replacer = (_, v) => typeof v === 'bigint' ? `0x${v.toString(16)}` : v;
JSON.stringify(data, replacer);

Q: Is there a TypeScript definition file?

Yes: js/index.d.ts ships with the package. No separate @types/rerius package is needed.

Q: The REST server is slow for large binaries.

The server creates a fresh ReriusBinary per request (withFile), which re-parses the file each time. For a production service, add a cache keyed by SHA-256 so repeat requests against the same binary skip re-parsing. See NPM_USAGE.md for a sketch of that pattern.


CI/CD#

This repository snapshot doesn't include .github/workflows/, so the answers below describe the intended process per CICD_GUIDE.md and PUBLISHING.md: verify against the live workflow files on GitHub if you're setting this up yourself.

Q: How do I publish a new version to npm?

Per the documented process: run the Release workflow in GitHub Actions (Actions → Release → Run workflow → enter version), which is meant to bump package.json, commit, tag, and hand off to the publish pipeline. See PUBLISHING.md.

Q: The nightly build fails on ubuntu-24.04-arm: I don't have that runner.

GitHub's hosted ARM64 runners have limited free-tier minutes. If you're adapting this workflow for your own fork and hit quota limits, comment out the ARM64 matrix entry.

Q: How do I add prebuilt binaries so users don't need to compile on install?

Build js/rerius.node on each target platform, copy it to js/prebuilds/rerius-<platform>-<arch>.node, commit, and publish: js/scripts/install.js checks that directory before falling back to compiling from source.


Mach-O / macOS#

Q: Does Rerius support macOS binaries?

Yes. src/formats/macho.c handles: - Single-arch Mach-O (ARM64 and x86-64) - FAT/universal binaries: automatically selects the ARM64 slice, falls back to x86-64 - Section parsing (__TEXT,__text.text, __DATA,__data.data, etc.) - Entry point from LC_MAIN - Symbol table from LC_SYMTAB

See MACHO_SUPPORT.md for details.

Q: macOS sections() returns an empty array.

Double check you're on the current release rather than an old build: the Mach-O magic constants need to match what a little-endian CPU actually reads from the file (0xFEEDFACF for ARM64 LE, bytes CF FA ED FE on disk). If sections() is empty on a binary that has a valid Mach-O magic, please file a bug with the binary's file output.

Q: macOS functions() returns nothing on stripped binaries.

Function detection on stripped Mach-O binaries relies on recognizing common ARM64 prologues (sub sp, sp, #N, stp xN, xM, [sp, #-N]!) and falls back to the section entry point as a function boundary of last resort. If a binary uses an unusual prologue shape, detection may miss functions: this is a heuristic, not a guarantee.

Q: Assembler errors when building on macOS.

Rerius selects platform/arm64_macos.S (Mach-O assembler syntax) on Apple Silicon and platform/x86_64_macos.S on Intel Mac automatically via the build script: platform/arm64_bsd.S (ELF syntax) is for FreeBSD/OpenBSD and isn't valid input for the macOS assembler. If you're seeing this error, check the build script correctly detected Darwin as the OS.


npm#

Q: How do I use Rerius without git cloning?

npm install rerius

The postinstall script compiles the native addon automatically: no git clone or manual make needed.

Q: npm install says "No C compiler found".

Install clang or gcc:

# Debian/Ubuntu
sudo apt install build-essential libnode-dev

# macOS
xcode-select --install

# Termux
pkg install clang

Q: Can I ship prebuilt binaries so users don't need to compile?

Yes: build on each target platform, copy js/rerius.node to js/prebuilds/rerius-<platform>-<arch>.node, commit, then npm publish. js/scripts/install.js checks prebuilds/ first, before falling back to compiling from source.

Edit this page on GitHub Source: docs/FAQ.md · Rerius v1.0.0
On this page
Frequently Asked Questions General Build Analysis JavaScript / npm CI/CD Mach-O / macOS npm
ESC
↑↓ navigate openesc close