Skip to main content

Crate nimrod

Crate nimrod 

Source
Expand description

Parse and inspect Nim-compiled native binaries.

This crate provides a pure-Rust parser and forensic-artifact extractor for binaries produced by the Nim compiler via its C, C++, or Objective-C backends. A Nim-compiled program is a normal ELF, PE, or Mach-O executable — there is no Nim-specific container. The crate recovers Nim runtime artifacts left inside an otherwise-ordinary native binary.

§What it extracts

ArtifactMethodNotes
Detection verdictNimBinary::is_nim11 independent probes
Format / arch / GC modeNimBinary::format, NimBinary::gc_modeELF, PE, Mach-O; refc vs ARC/ORC
Entry shimsNimBinary::entry_shimsNimMain, PreMain, etc.
Init functionsNimBinary::init_functionsWith decoded module paths
Module mapNimBinary::module_mapPer-module: symbols, sizes, init VAs, leaked paths
RTTI globalsNimBinary::rtti_symbolsV1 (TNimType) and V2 (TNimTypeV2) with parsed fields
Type graphNimBinary::typesCross-linked types: members, offsets, sizes, layout, inheritance, enum values, destructors
Code entrypointsNimBinary::code_entrypointsOne VA-tagged stream of shims, inits, procs, raise-enclosing fns, RTTI procs
String literalsNimBinary::string_literals_v2V2 NIM_STRLIT_FLAG scan
Stack-trace metadataNimBinary::stack_traceProc names + .nim file paths (build-host leaks)
Nimble path leaksNimBinary::nimble_pathsPackage name, version, hash, username, OS
Exception typesNimBinary::exception_types*Error, *Defect cstrings in rodata
Raise sitesNimBinary::raise_sitesFull (type, proc, file, line) tuples via instruction analysis
Demangled symbolsdemangle::symbol::parseIdentifier, module, item ID

§Quick start

use nimrod::NimBinary;

let data = std::fs::read("sample").unwrap();
let bin = NimBinary::from_bytes(&data).unwrap();

if !bin.is_nim() {
    eprintln!("not a Nim binary");
    return;
}

// Detection and classification
println!("format: {:?}, gc: {:?}", bin.format(), bin.gc_mode());

// Module map: which Nim modules are compiled in, with every function
let mmap = bin.module_map();
for (name, info) in &mmap.modules {
    println!("{name}: {} functions", info.symbol_count());
    for sym in &info.symbols {
        // sym.name    = demangled Nim identifier
        // sym.address = VA (start disassembling here)
        // sym.size    = byte count (ELF; 0 on Mach-O/PE)
        let _ = (sym.name.as_str(), sym.address, sym.size);
    }
}

// Raise sites: exception type + enclosing function + source location
for rs in bin.raise_sites() {
    let _ = (
        rs.exception_type.as_deref(),   // "ValueError"
        rs.enclosing_function.as_deref(), // "parseHexInt__strutils_u1234"
        rs.file.as_deref(),              // "strutils.nim"
        rs.line,                         // Some(1242)
    );
}

§Design

  • Pure Rust, #![deny(unsafe_code)].
  • Cross-format: ELF, PE, Mach-O via goblin.
  • Zero-copy where possible — borrows from the input byte slice.
  • Forensic-oriented: prioritises attribution-grade artifacts (build-host paths, package refs, exception locations) over pretty-printing.

The format-level research backing every probe and struct layout is documented in RESEARCH.md at the crate root.

§Robustness contract

nimrod parses adversarial input, so every public artifact iterator obeys a uniform contract:

  • Never panics on malformed input. The crate denies unwrap, expect, panic, unchecked indexing, and unchecked arithmetic in library code (see the [lints] table in Cargo.toml).
  • Returns empty on missing data. A walker whose artifact is absent (no V2 strings in a refc build, no raise sites in a binary that never raises) returns an empty slice, not an error.
  • Skips malformed records individually. A single undecodable record (e.g. an RTTI global whose struct bytes are not file-backed) is dropped or degraded to a name-only entry; the rest of the scan still completes. Name-only RTTI entries are flagged by NimType::is_readable.

§Address space

Every address-bearing field returned by this crate is a virtual address in the input image’s load space, never a file offset. Convert to a disassembler-relative RVA with the *_rva helpers on NimBinary, with Container::va_to_rva, or with va_to_i64 for signed-integer storage.

§Thread safety

NimBinary is Send + Sync (enforced by a compile-time assertion), so it can be shared across threads or held across .await points. Its scan caches use std::sync::OnceLock.

Re-exports§

pub use addr::va_to_i64;
pub use container::Arch;
pub use container::Container;
pub use container::Format;
pub use container::Section;
pub use container::SectionKind;
pub use container::Symbol;
pub use container::SymbolKind;
pub use detect::DetectionMatches;
pub use detect::DetectionReport;
pub use entrypoints::CodeEntrypoint;
pub use entrypoints::EntrypointKind;
pub use error::Error;
pub use error::Result;
pub use inits::InitFunction;
pub use inits::InitKind;
pub use metadata::GcMode;
pub use metadata::NimVersionHint;
pub use modules::ModuleInfo;
pub use modules::ModuleMap;
pub use modules::ModuleSymbol;
pub use paths::NimblePath;
pub use paths::PathOs;
pub use raises::ExceptionRef;
pub use rtti::symbols::RttiSymbol;
pub use rtti::symbols::RttiVersion;
pub use rtti::v1::NimKind;
pub use rtti::v1::NimTypeFlag;
pub use shims::EntryShim;
pub use shims::ShimKind;
pub use sites::RaiseSite;
pub use stacktrace::FilePath;
pub use stacktrace::StackTraceHarvest;
pub use strings::v1::StringLiteralV1;
pub use strings::v2::StringLiteral;
pub use types::CodeRef;
pub use types::EnumValue;
pub use types::NimType;
pub use types::TypeField;
pub use types::TypeFlags;
pub use types::TypeRef;
pub use types::TypeShape;

Modules§

addr
Address-space helpers.
container
Container-format abstraction over ELF, PE, and Mach-O.
demangle
Symbol and module-path demangling.
detect
Nim-binary fingerprint detection.
entrypoints
Aggregated code entrypoints.
error
Error types for Nim binary parsing.
inits
Module init-function scanner.
metadata
Nim binary metadata detection.
modules
Cross-referenced module map.
paths
Build-host attribution via nimble package path leaks.
raises
Exception raise-site recovery (phase 1).
rtti
Run-time type information (RTTI) recovery.
shims
Entry-point shim locator.
sites
Exception raise-site recovery (phase 2).
stacktrace
Stack-trace metadata harvester.
strings
Nim string literal scanning.
types
Cross-referenced Nim type graph recovered from RTTI.

Structs§

NimBinary
Parsed view of a Nim-compiled native binary.