Expand description
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 viatypes::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:
- A borrowed view (
Function,Segment) is a cheapCopyhandle that borrows theDatabaseand re-queries the kernel per accessor. - A lazy iterator (
Segments,function::Functions) walks a domain without collecting. - An owned snapshot (
Type,StackFrame,Ctree) is aSendvalue detached from the kernel and analyzable on any thread; aSnapshotsuffix (function::FunctionSnapshot) marks one taken from a view. - A kernel-handle owner (
Pattern,decompiler::DecompiledFunction) holds an IDA resource it frees onDrop, so it stays!Sendon the kernel thread.
§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 withIDA_SDK_DIR.- 64-bit databases. idakit works with
.i64and 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:
IDADIR, if set.idat64on yourPATH.- The platform’s default install locations:
~/ida-pro-*and/opt/on Linux,/Applications/on macOS,Program Fileson 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_DIRbuilds against a local SDK checkout instead of fetching.IDA_SDK_CACHE_DIRrelocates 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
Ctreesyntax tree. - error
- Error types for idiomatic
idakitcalls. - function
- Enumerates a database’s functions, reads them through the
Functionview, and edits them through theFunctionEditcursor. - instruction
- Decodes machine instructions into an owned
Instructionand 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
Netnodeview andNetnodeMutcursor. - 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 resolvedTypeshares, and writes them throughTypesMutand theTypeExprbuilder.
Structs§
- Address
- A validated address, any real value other than the invalid sentinel.
- Arena
- An append-only arena of
T, addressed byIdx<T>. - Basic
Block - One basic block, a straight-line run of code with a single entry and single exit.
- Ctree
- An owned, interned,
Sendsyntax tree of a decompiled function, fromDatabase::decompile. The root is always a block statement. - Database
- The open database.
- Database
Info - An owned,
Sendsnapshot of database-wide metadata, fromDatabase::info. - Database
Open Builder - Builder for
Database::open. Setrun_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. - External
Exit - A control-flow edge that leaves the function, a tail-jump or tail-call from a
BasicBlocktotarget, an address in no block of this graph. - Flow
Chart - An owned,
Sendcontrol-flow graph of one function, fromDatabase::flowchart. - Function
- A borrowed view of one function, keyed by entry address.
- Ida
- A
Send + Clonehandle 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.
- Location
Mut - A write cursor at one address, from
Database::at_mut. - Matches
- A lazy iterator over a
Pattern’s matches, fromDatabase::search/Database::search_in. - Name
- A named address from the database’s name list, yielded by
Names. - Name
Flags get_ea_name’sgtn_flagsbits (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.
- Segment
Flags - 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. - Stack
Frame - An owned,
Sendsnapshot of a function’s stack frame. - Stack
Slot - One slot in a function’s stack frame, its frame-pointer-relative offset and byte size, plus a
kindthat is either a real variable (with name/type) or a reserved slot. - String
Literal - 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,
Sendsnapshot of one resolved type. - Xref
- A cross-reference edge, carrying both endpoints. For
xrefs_tothetoend is the queried address; forxrefs_fromthefromend is. - Xrefs
- An iterator over cross-references, from
Database::xrefs_to/Database::xrefs_from.
Enums§
- Basic
Block Kind - The kind of control-flow transfer that ends a basic block.
- Bitness
- Addressing width: 16-, 32-, or 64-bit.
- Code
Xref - A closed mirror of IDA’s raw code-reference enum.
- Data
Xref - A closed mirror of IDA’s raw data-reference enum.
- Segment
Alignment - A segment’s alignment code (
sa*fromsegment.hpp), fromSegment::alignment. - Segment
Class - A segment’s classification, from its
class_namestring. - Segment
Combination - A segment’s combination code (
sc*fromsegment.hpp), fromSegment::combination. - Segment
Type - A segment’s type code (
SEG_*fromsegment.hpp), fromSegment::kind. - Stack
Slot Kind - A
StackSlotis either a real stack variable, carrying its name and type, or one of the two slots IDA reserves in every frame. - Xref
Kind - A reference classified into the code or data type space.
- Xref
Origin - A cross-reference’s origin, either IDA’s own analysis or an explicit user annotation.
Type Aliases§
- Basic
Block Id - A typed handle into
FlowChart’s block arena. Edges are lists of these; block 0 is the entry.