Skip to content

StarCrossPortal/sleighcraft

Repository files navigation

SleighCraft

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 ✔️

How to install

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

How to Use

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.

About Us

This is a project started by StarCrossTech PortalLab.

Any contribution through pull request is welcome. ✌️