Skip to main content

Crate idakit

Crate idakit 

Source
Expand description

idakit

CI Coverage crates.io docs.rs License: MIT MSRV

Access, extend, and automate IDA through a first-class Rust API.

idakit drives IDA’s analysis kernel from safe Rust:

const SINKS: &[&str] = &["strcpy", "system", "memcpy", "sprintf"];

for function in db.functions().take(300) {
    // Decompile to a C syntax tree; skip anything that won't decompile.
    let Some(tree) = function.decompile().ok().and_then(|d| d.ctree().ok()) else { continue };

    for (_, callee, _) in tree.calls() {
        // Resolve the call target to a name, then match it against the list.
        let Some((_, Some(name))) = tree.kind(callee).as_obj() else { continue };
        if SINKS.iter().any(|s| name.contains(s)) {
            println!("{} calls {name}", function.name());
        }
    }
}

§Core types

  • Ida: brings the kernel up and marshals work onto its thread.
  • Database: the open database, and the root of every read and write.
  • Function: a function’s name, bytes, chunks, instructions, and decompilation.
  • Segment: a segment’s range, permissions, and class.
  • Type: an owned type snapshot, comparable across databases via types::diff.
  • Ctree: a decompiled function’s syntax tree, walkable off the kernel thread.
  • Xref: a cross-reference edge between two addresses.

§Usage

IDA’s kernel initializes once per process and runs on a single thread. The example above used Ida::here, which initializes it on the current thread and hands the database back directly, a good fit for a tool or test that owns its thread.

When the current thread must stay free, such as a GUI event loop or an async runtime, Ida::run hosts the kernel on its own dedicated thread instead. It hands your closure an Ida handle whose Ida::call marshals work onto the kernel from any thread:

use idakit::prelude::*;

Ida::run(|ida| {
    ida.call(|db: &mut Database| -> Result<()> {
        db.open("path/to/database.i64").call()?;
        for function in db.functions() {
            println!("{:#x} {}", function.address().get(), function.name());
        }
        db.close(false);
        Ok(())
    })?
})??;

The open database is a single-owner kernel (Database is Send + !Sync), so it can move between threads but is never shared. Reads borrow it and return lightweight views like Function and Segment; writes take it by mutable reference, so a read can’t outlive a mutation.

Only one database is live at a time. Ida::here and Ida::run return InitError::AlreadyRunning while one is already open; drop it and you can start another.

For lower-level control, idakit_sys exposes IDA’s raw C bindings directly.

Both crates carry #[doc(alias)] tags mapping items to their IDA SDK names, so a rustdoc search resolves an SDK spelling like SEGPERM_READ or netnode::altval to the binding. Aliases are per crate: idakit_sys carries the raw-binding names, idakit carries the idiomatic wrappers.

§Conventions

A handful of shapes recur across every domain:

§Requirements

  • IDA Pro 9.3. A local install is needed to build, since idakit links its libraries, and a valid license to run, since IDA checks it when the kernel initializes.
  • A 64-bit host running Linux, macOS, or Windows.
  • Rust 1.88 or newer.
  • A C++17 compiler for the build: g++ or Clang on Linux and macOS, MSVC on Windows.
  • git, to fetch the SDK headers that match your install, unless you supply a local SDK checkout with IDA_SDK_DIR.
  • 64-bit databases. idakit works with .i64 and can’t open a 32-bit .idb.
    • You don’t have to bring one, though: it can analyze a binary from scratch.
    • A 32-bit binary is fine, since the limitation is the database format, not the target.

§Building

idakit locates your IDA install automatically, in order:

  1. IDADIR, if set.
  2. idat64 on your PATH.
  3. The platform’s default install locations: ~/ida-pro-* and /opt/ on Linux, /Applications/ on macOS, Program Files on Windows.

If none match, set IDADIR to the directory holding IDA’s runtime library.

The SDK headers are fetched to match your installed IDA version, so a normal build needs no extra flags. Two variables override that:

  • IDA_SDK_DIR builds against a local SDK checkout instead of fetching.
  • IDA_SDK_CACHE_DIR relocates the fetch cache.

Databases must be 64-bit .i64, since the facade is compiled __EA64__.

§License

The bindings are MIT licensed. The IDA SDK and runtime are proprietary to Hex-Rays; idakit links against your own install and redistributes none of it.

Re-exports§

pub use crate::netnode::Altvals;
pub use crate::netnode::HashEntries;
pub use crate::netnode::Netnode;
pub use crate::netnode::NetnodeBytes;
pub use crate::netnode::NetnodeBytesError;
pub use crate::netnode::NetnodeMut;
pub use crate::netnode::Netnodes;
pub use crate::netnode::NodeId;
pub use crate::netnode::Persist;
pub use crate::netnode::Supvals;
pub use crate::netnode::Tag;
pub use crate::netnode::TaggedNetnode;
pub use crate::netnode::TaggedNetnodeMut;
pub use idakit_sys as sys;

Modules§

decompiler
Decompiles a function to C pseudocode and a walkable Ctree syntax tree.
error
Error types for idiomatic idakit calls.
function
Enumerates a database’s functions, reads them through the Function view, and edits them through the FunctionEdit cursor.
instruction
Decodes machine instructions into an owned Instruction and its semantic operands.
kernel
Hosts IDA’s kernel thread and marshals closures onto it.
netnode
Reads and writes IDA’s persistent per-database store through the Netnode view and NetnodeMut cursor.
prelude
Re-exports of the crate’s primary types, for a single glob import (use idakit::prelude::*;).
types
Reads a database’s types into TypeTable, the interned arena every resolved Type shares, and writes them through TypesMut and the TypeExpr builder.

Structs§

Address
A validated address, any real value other than the invalid sentinel.
Arena
An append-only arena of T, addressed by Idx<T>.
BasicBlock
One basic block, a straight-line run of code with a single entry and single exit.
Ctree
An owned, interned, Send syntax tree of a decompiled function, from Database::decompile. The root is always a block statement.
Database
The open database.
DatabaseInfo
An owned, Send snapshot of database-wide metadata, from Database::info.
DatabaseOpenBuilder
Builder for Database::open. Set run_auto, then finish with .call().
Export
A borrowed view of one export (entry point), keyed by kernel index.
Exports
A lazy iterator over every export in the database, in kernel order, from Database::exports.
ExternalExit
A control-flow edge that leaves the function, a tail-jump or tail-call from a BasicBlock to target, an address in no block of this graph.
FlowChart
An owned, Send control-flow graph of one function, from Database::flowchart.
Function
A borrowed view of one function, keyed by entry address.
Ida
A Send + Clone handle to the kernel; marshals closures to it from any thread.
Idx
A typed handle into an Arena<T>.
Import
An owned import-table slot (IAT entry / thunk) bound to a symbol in some module, read from a snapshot of the import table.
Imports
A lazy iterator over the database’s imports, from Database::imports.
Location
A borrowed view of one address’s item, keyed by that address.
LocationMut
A write cursor at one address, from Database::at_mut.
Matches
A lazy iterator over a Pattern’s matches, from Database::search/Database::search_in.
Name
A named address from the database’s name list, yielded by Names.
NameFlags
get_ea_name’s gtn_flags bits (name.hpp), controlling substitution/demangling.
Names
A lazy iterator over every named address, in the kernel’s name-list order, from Database::names.
Pattern
A compiled binary search pattern that frees its kernel handle on Drop.
Segment
A borrowed view of one segment, keyed by kernel index.
SegmentFlags
Segment flag bits from segment.hpp (SFL_*, segment_t::flags).
Segments
A lazy iterator over every segment in the database, in kernel order, from Database::segments.
StackFrame
An owned, Send snapshot of a function’s stack frame.
StackSlot
One slot in a function’s stack frame, its frame-pointer-relative offset and byte size, plus a kind that is either a real variable (with name/type) or a reserved slot.
StringLiteral
A borrowed view of one string IDA located, keyed by address.
Strings
A lazy iterator over IDA’s string list, in list order, from Database::strings.
Type
An owned, Send snapshot of one resolved type.
Xref
A cross-reference edge, carrying both endpoints. For xrefs_to the to end is the queried address; for xrefs_from the from end is.
Xrefs
An iterator over cross-references, from Database::xrefs_to/Database::xrefs_from.

Enums§

BasicBlockKind
The kind of control-flow transfer that ends a basic block.
Bitness
Addressing width: 16-, 32-, or 64-bit.
CodeXref
A closed mirror of IDA’s raw code-reference enum.
DataXref
A closed mirror of IDA’s raw data-reference enum.
SegmentAlignment
A segment’s alignment code (sa* from segment.hpp), from Segment::alignment.
SegmentClass
A segment’s classification, from its class_name string.
SegmentCombination
A segment’s combination code (sc* from segment.hpp), from Segment::combination.
SegmentType
A segment’s type code (SEG_* from segment.hpp), from Segment::kind.
StackSlotKind
A StackSlot is either a real stack variable, carrying its name and type, or one of the two slots IDA reserves in every frame.
XrefKind
A reference classified into the code or data type space.
XrefOrigin
A cross-reference’s origin, either IDA’s own analysis or an explicit user annotation.

Type Aliases§

BasicBlockId
A typed handle into FlowChart’s block arena. Edges are lists of these; block 0 is the entry.