Skip to content

Latest commit

 

History

94 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Binkit

Rust

Binkit is a Rust command-line toolbox for inspecting, disassembling, and modifying ELF64 binaries. It can display ELF metadata, disassemble x86-64 code, calculate an injection plan, append a payload, and update the executable entry point.

Use Binkit only on binaries you own or are authorized to modify. You are responsible for complying with applicable laws, licenses, and policies.

Features

  • Display complete ELF64, program-header, and section-header information.
  • Disassemble ELF sections or raw x86-64 machine code using Intel syntax.
  • Calculate aligned payload addresses and signed rel32 return offsets.
  • Append a payload by repurposing a compatible section and program header.
  • Update the ELF entry point.
  • Protect existing output files unless --force is explicitly provided.
  • Write files atomically while preserving the source permissions.
  • Reject malformed or unsupported ELF structures with descriptive errors.

See ELF compatibility for the exact supported formats and current limitations.

Installation

Cargo

cargo install --locked binkit

Build from source

git clone https://github.com/matheus-git/binkit.git
cd binkit
cargo build --release --locked
./target/release/binkit --help

Prebuilt binaries may also be available on the GitHub Releases page.

Commands

Run binkit --help or binkit <COMMAND> --help for the complete CLI reference.

Inspect ELF metadata

The info command displays the complete ELF header and its program or section tables. Options can be combined:

binkit info ./program --header
binkit info ./program --programs
binkit info ./program --sections
binkit info ./program --header --programs --sections

The header output includes identification fields, byte order, ABI, file type, architecture, entry point, flags, table offsets, entry sizes, counts, and the section-name table index.

Disassemble code

Disassemble .text or another section from a little-endian x86-64 ELF file:

binkit disasm ./program
binkit disasm ./program --section .init

Disassemble a file containing raw x86-64 machine code:

binkit disasm ./payload.bin --bin

Check an injection plan

Calculate the aligned injection address and the signed rel32 displacement back to the current entry point:

binkit check-inject ./program
binkit check-inject ./program --return-address 0x401000

This command only reports values; it does not modify or create a file.

Inject a payload

Append a payload and write the modified ELF to a new file:

binkit inject ./program \
  --inject ./payload.bin \
  --output ./program.injected

By default, Binkit repurposes .note.gnu.property, renames it to .injected, and assigns an aligned virtual address. Select another compatible section or address when needed:

binkit inject ./program \
  --inject ./payload.bin \
  --section .custom-note \
  --address 0x405000 \
  --return-address 0x401000 \
  --output ./program.injected

Injection requires the selected section to have a matching program header and enough space in the section-name string table for .injected. The command fails without creating the output if these requirements are not met.

Existing destinations are protected. Use --force only when replacement is intentional:

binkit inject ./program -i ./payload.bin -o ./program.injected --force

The payload is appended as provided. Binkit reports the injection address and return displacement but does not generate a jump, trampoline, or architecture-specific payload instructions.

Update the entry point

Write a new ELF entry point to a separate output file:

binkit update ./program --entry 0x405000 --output ./program.updated

Omitting --output updates the input path atomically. Replacing a different existing destination requires --force.

Library usage

The ELF64 parser and core calculations are available as a Rust library:

use binkit::elf64::{Elf64Binary, calculate_rel32};

let bytes = std::fs::read("program")?;
let binary = Elf64Binary::new(&bytes)?;

println!("Entry point: 0x{:X}", binary.entry());
println!("rel32: {}", calculate_rel32(0x405000, binary.entry())?);

# Ok::<(), anyhow::Error>(())

Development

The project toolchain is pinned in rust-toolchain.toml and is installed automatically by rustup. Run the same quality checks used by CI:

cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-features
cargo build --release --locked

The integration tests also use GNU binutils, GCC, Clang, and lld. They compile several ELF64 variants, execute an injected x86-64 payload, and verify that another payload can restore the initial process state and return to the original entry point. On Debian or Ubuntu:

sudo apt-get update
sudo apt-get install binutils build-essential clang lld

The fuzz target requires nightly Rust and cargo-fuzz:

cargo install cargo-fuzz --locked
cargo +nightly fuzz run elf64-roundtrip

Generated fuzz corpora, artifacts, and build output are ignored by Git.

Contributing

Contributions should include tests for behavior changes and pass the formatting, lint, test, and release-build commands above. Useful areas include additional ELF validation, executable injection fixtures, architecture support, structured output, and other binary formats.

License

Licensed under the MIT License.

About

A modular toolbox for analyzing, disassembling, and patching binary formats.

Topics

Resources

Stars

11 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages