SleighCraft is one of the BinCraft project.
SleighCraft
is a decoder (or, linear disassembler) based on ghidra's decompiler implementation. Sleighcraft can be used in Rust or Python, with both high-level and low-level API.
In general, sleighcraft
is just like capstone but with IR and more archs.
Features:
- Rust based API and Python scripting API.
- Decoding with IR as the semantic meaning.
- Archs: 110 architectures.
️️✔️: provided
❌: not provided
🚧: in construction
🤔: not sure, maybe not
Comparison with capstone:
Feature | SleighCraft | Capstone Engine |
---|---|---|
disassemble | ✔️ | ✔️ |
IR | ✔️️ | ❌ |
C API | 🚧 | ✔️ |
custom architecture | ️✔️ | ❌ |
Architectures comparision with capstone (according to capstone arch list):
Arch Names | SleighCraft | Capstone Engine |
---|---|---|
6502 | ✔️ | 🤔 |
6805 | ✔️ | 🤔 |
8051 | ✔️ | 🤔 |
8048 | ✔️ | 🤔 |
8085 | ✔️ | 🤔 |
68000 | ✔️ | 🤔 |
aarch64(armv8) | ✔️ | ️️✔️ |
arm | ✔️ | ️️✔️ |
cp1600 | ✔️ | 🤔 |
cr16 | ✔️ | 🤔 |
avr8 | ✔️ | ️️🤔 |
dalvik | ✔️ | 🤔 |
jvm | ✔️ | 🤔 |
mips | ✔️ | ️️✔️ |
powerpc | ✔️ | ️️✔️ |
sparc | ✔️ | ️️✔️ |
tricore | ✔️ | 🤔 |
riscv | ✔️ | 🤔 |
z80 | ✔️ | 🤔 |
System Z | ❌ | ✔️ |
xCore | ❌ | ✔️ |
Rust
Use cargo:
sleighcraft = { git = "https://github.com/StarCrossPortal/sleighcraft" }
The repo is a bit large to submit on crates-io (because of predefined sla files), but save you the complex of compiling sleigh files yourself.
Python:
# quick install it with pip
$ pip3 install bincraft
# or download binaries than choose the corresponding architecture
$ pip3 install bincraft-0.1.0-cp39-cp39-Arch.whl
# or manual, to do this, you need to have rust compiler installed and maturin
# better with rustup.
$ pip3 install maturin
$ maturin build
$ pip3 install bincraft-0.1.0-cp39-cp39-Arch.whl
NodeJs:
# quick install it with npm
$ npm i bincraft
# or manual, to do this, you need to have rust compiler installed, nodejs and neon
# better with rustup.
$ npm install -g neon-cli
$ neon build
One could refer to doc.rs to see how Rust binding can be used.
Python binding:
from bincraft import Sleigh
code = [0x90, 0x31, 0x32] # code to disassemble
# init the sleigh engine Sleigh(arch, code)
sleigh = Sleigh("x86", code)
# now we are prepared to disassemble!
# disasm(start_addr)
for asm in sleigh.disasm(0):
addr = asm.addr()
mnem = asm.mnemonic()
body = asm.body()
# quite like capstone, right?
print(f'Addr: {addr}\t mnemonic: {mnem}\t body: {body}')
# but! we also have the IR!
pcodes = asm.pcodes()
for pcode in pcodes:
opcode = pcode.opcode()
vars = pcode.vars()
print(f'opcode: {opcode}\t vars: {vars}\t')
print()
Nodejs binding:
const Sleigh = require('bincraft');
//or const Sleigh = require('.');
// init the sleigh engine Sleigh(arch, code) like python
const sleigh = new Sleigh("x86",[0x90,90]);
// disasm(start_addr)
// - start: Default is 0
const asms = sleigh.disasm();
asms.forEach(asm => {
let addr = asm.addr();
let mnemonic = asm.mnemonic();
let body = asm.body();
// dump instruction
console.log(`addr: ${addr}\t mnemonic: ${mnemonic}\t body: ${body}`);
// And we have IR!
let pcodes = asm.pcodes();
pcodes.forEach(pcode => {
opcode = pcode.opcode();
vars = pcode.vars();
console.log(`opcode: ${opcode}\t vars: ${vars}`);
});
});
Rust (kinda low level):
// Overall procedure:
// 1. get the spec, this is where we know how to decode anything
// 2. get a loader, this is where we fill the input bytes to the engine.
// A predefined loader is provided: `PlainLoadImage`, which sets
// the things to decode by using a single buf.
// 3. set the AssemblyEmit and PcodeEmit instance, these are two
// traits that defines the callback at the decode time.
// 4. do the decode
use sleighcraft::*;
let mut sleigh_builder = SleighBuilder::default();
let spec = arch("x86").unwrap();
let buf = [0x90, 0x32, 0x31];
let mut loader = PlainLoadImage::from_buf(&buf, 0);
sleigh_builder.loader(&mut loader);
sleigh_builder.spec(spec);
let mut asm_emit = CollectingAssemblyEmit::default();
let mut pcode_emit = CollectingPcodeEmit::default();
sleigh_builder.asm_emit(&mut asm_emit);
sleigh_builder.pcode_emit(&mut pcode_emit);
let mut sleigh = sleigh_builder.try_build().unwrap();
sleigh.decode(0).unwrap();
println!("{:?}", asm_emit.asms);
println!("{:?}", pcode_emit.pcode_asms);
A more detailed documentation of Rust API is still under development.
This is a project started by StarCrossTech PortalLab.
Any contribution through pull request is welcome. ✌️