Using Rerius in a Backend Project
This guide explains how to add Rerius as an npm dependency in any Node.js backend project - no manual compilation needed.
Repository: https://github.com/ECLS-Studio/rerius
How It Works#
Rerius is a native Node.js addon (.node file). The npm install process automatically compiles the C source into a platform-specific binary. No separate build step required on the consumer side.
npm install rerius
↓
postinstall script runs
↓
checks for prebuilt binary (prebuilds/<platform>-<arch>.node)
↓ if not found:
compiles from source using clang/gcc + Node headers
↓
rerius.node ready
Installation#
npm install rerius
# or
yarn add rerius
# or
pnpm add rerius
Requirements for compilation (if no prebuild):
- C compiler: clang or gcc
- Node.js dev headers (usually bundled with Node)
- make (optional - installer falls back to direct compile)
Termux/Android:
pkg install nodejs clang
npm install rerius
Basic Usage#
const rerius = require('rerius');
// One-liner with auto-close
rerius.withBinary('/path/to/binary', bin => {
console.log(bin.arch); // 'AArch64 (ARM64)'
console.log(bin.sha256); // 'a3f8bc...'
console.log(bin.isPie); // true
const fns = bin.functions(); // detected functions
const syms = bin.symbols(); // symbol table
const xr = bin.xrefs(); // cross-references
console.log(fns.length, 'functions,', syms.length, 'symbols');
});
Express.js Backend Example#
mkdir my-re-backend && cd my-re-backend
npm init -y
npm install express rerius
// app.js
const express = require('express');
const rerius = require('rerius');
const path = require('path');
const app = express();
app.use(express.json());
// POST /analyze - analyze an uploaded binary path
app.post('/analyze', async (req, res) => {
const { file } = req.body;
if (!file) return res.status(400).json({ error: 'body.file required' });
try {
const result = rerius.withBinary(file, bin => ({
arch: bin.arch,
format: bin.format,
sha256: bin.sha256,
isPie: bin.isPie,
isStripped: bin.isStripped,
entry: String(bin.entry),
functions: bin.functions().length,
symbols: bin.symbols().length,
xrefs: bin.xrefs().length,
sections: bin.sections().map(s => ({
name: s.name,
type: s.type,
size: String(s.size),
})),
}));
res.json(result);
} catch (e) {
res.status(500).json({ error: e.message });
}
});
// POST /disasm - disassemble a section
app.post('/disasm', (req, res) => {
const { file, section = '.text', limit = 200 } = req.body;
if (!file) return res.status(400).json({ error: 'body.file required' });
try {
const insns = rerius.withBinary(file, bin =>
bin.disasmJson(section, { limit: parseInt(limit, 10) })
.map(i => ({
address: String(i.address),
mnemonic: i.mnemonic,
operands: i.operands,
group: i.group,
symbol: i.symbol,
}))
);
res.json({ section, count: insns.length, instructions: insns });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
// POST /entropy - entropy scan
app.post('/entropy', (req, res) => {
const { file } = req.body;
if (!file) return res.status(400).json({ error: 'body.file required' });
try {
const output = rerius.withBinary(file, bin => bin.entropy());
res.json({ output });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
// POST /decompile - decompile a function by index
app.post('/decompile', (req, res) => {
const { file, funcIdx = 0 } = req.body;
if (!file) return res.status(400).json({ error: 'body.file required' });
try {
const output = rerius.withBinary(file, bin =>
bin.decompile(parseInt(funcIdx, 10))
);
res.json({ output });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
app.listen(3000, () => console.log('RE backend running on :3000'));
node app.js
# Test
curl -s -X POST http://localhost:3000/analyze \
-H 'Content-Type: application/json' \
-d '{"file":"/bin/ls"}' | jq .
Fastify Backend Example#
npm install fastify rerius
// server.js
const Fastify = require('fastify');
const rerius = require('rerius');
const app = Fastify({ logger: true });
app.post('/api/info', async (req) => {
const { file } = req.body;
return rerius.withBinary(file, bin => bin.info);
});
app.post('/api/functions', async (req) => {
const { file } = req.body;
return rerius.withBinary(file, bin => ({
functions: bin.functions().map(f => ({
name: f.name,
start: String(f.start),
size: String(f.size),
insnCount: f.insnCount,
hasCalls: f.hasCalls,
hasLoops: f.hasLoops,
}))
}));
});
app.post('/api/full', async (req) => {
const { file } = req.body;
// Full analysis pipeline - symbols, funcs, xrefs, CFG, unicode
return rerius.withBinary(file, bin => {
const r = bin.analyze();
return {
info: r.info,
functions: r.functions.length,
xrefs: r.xrefs.length,
blocks: r.blocks.length,
timing: r.analysisTimeMs,
};
});
});
app.listen({ port: 3000 }, err => {
if (err) { app.log.error(err); process.exit(1); }
});
TypeScript Example#
npm install rerius
# TypeScript declarations are bundled - no @types/rerius needed
// analyze.ts
import { withBinary, BinaryInfo, Function, Section } from 'rerius';
interface AnalysisReport {
info: BinaryInfo;
topFuncs: Function[];
sections: Section[];
}
export function analyzeFile(filePath: string): AnalysisReport {
return withBinary(filePath, bin => ({
info: bin.info,
topFuncs: bin.hottestFunctions(10).map(h => h.function),
sections: bin.sections(),
}));
}
// Async version
export async function analyzeAsync(filePath: string) {
const { withBinaryAsync } = await import('rerius');
return withBinaryAsync(filePath, async bin => {
const r = bin.analyze();
return {
sha256: r.info.sha256,
functions: r.functions.length,
isPacked: bin.entropy().includes('PACKED'),
};
});
}
Advanced: Long-running Analysis Service#
For a server that analyzes many binaries, reuse binary handles to avoid repeated parsing:
const rerius = require('rerius');
// Cache parsed binaries keyed by SHA-256
const cache = new Map();
function getOrLoad(filePath) {
const bin = rerius.load(filePath);
const key = bin.sha256;
if (cache.has(key)) {
bin.close(); // close the duplicate
return cache.get(key);
}
cache.set(key, bin);
return bin;
}
// Clean up on process exit
process.on('exit', () => cache.forEach(b => b.close()));
process.on('SIGINT', () => { cache.forEach(b => b.close()); process.exit(0); });
process.on('SIGTERM', () => { cache.forEach(b => b.close()); process.exit(0); });
Handling BigInt in JSON Responses#
Rerius uses bigint for all addresses. JSON.stringify doesn't handle bigint natively. Two options:
// Option 1: Convert to hex strings before sending
const insns = bin.disasmJson('.text', { limit: 100 }).map(i => ({
...i,
address: `0x${i.address.toString(16)}`,
}));
// Option 2: Custom JSON replacer
const replacer = (_, v) => typeof v === 'bigint' ? `0x${v.toString(16)}` : v;
res.json(JSON.parse(JSON.stringify(data, replacer)));
// Option 3: Use the built-in REST server (handles bigint automatically)
// node node_modules/rerius/server/server.js
// → http://localhost:7070
Built-in REST Server (zero extra code)#
Rerius ships its own REST server with 42 endpoints and a web UI:
# Start from node_modules
node node_modules/rerius/server/server.js
# Custom port
PORT=8080 node node_modules/rerius/server/server.js
# Programmatic start
const { createServer } = require('rerius/server/server');
createServer({ port: 8080 });
All endpoints: POST /api/<name> with { "file": "/absolute/path" } - see js/README.md for the full list.
Web UI: https://rerius.sbs
API Surface (quick reference)#
const rerius = require('rerius');
// Module-level
rerius.load(path) // → ReriusBinary
rerius.version() // → '1.0.0'
rerius.withBinary(path, cb) // → T (auto-close)
rerius.withBinaryAsync(path, cb) // → Promise<T>
// ReriusBinary properties
bin.arch / .format / .os / .entry / .sha256 / .isPie / .isStripped / .hasDebug
// Analysis
bin.sections() bin.symbols() bin.functions()
bin.xrefs() bin.xrefsTo(addr) bin.xrefsFrom(addr)
bin.blocks() bin.unicodeStrings() bin.strings()
bin.hottestFunctions(n) bin.analyze()
// Lookup
bin.symAt(addr) bin.funcAt(addr)
bin.sectionByName(name) bin.sectionAt(addr)
bin.readBytes(addr, len)
// Disassembly
bin.disasm(section?)
bin.disasmJson(section?, { limit, offset })
// Advanced (ARM64, RISC-V; symexec also x86-64 -- see docs/API.md for exact coverage)
bin.symexec(funcIdx?) bin.ssa(funcIdx?)
bin.decompile(funcIdx?) bin.emulate(funcIdx?, initRegs?)
// Detection
bin.entropy() bin.rda(section?) bin.ivf()
// Formats: ELF64 (all 3 archs) · ELF32 (RV32 only) · PE64+ · Mach-O 64/FAT · Raw
// (PE32 and ELF32 x86/ARM are not currently supported -- see docs/BINARY_FORMATS.md)
// Lifecycle
bin.close()
docs/NPM_USAGE.md · Rerius v1.0.0