#executable #mach-o #elf #binary #binary-format #pe #run-time

bin+lib libsui

A injection tool for executable formats (ELF, PE, Mach-O) that allows you to embed files into existing binary and extract them at runtime

9 releases (4 breaking)

new 0.4.0 Sep 30, 2024
0.3.1 Sep 20, 2024
0.3.0 Aug 14, 2024
0.2.0 Aug 13, 2024
0.0.1 May 26, 2024

#251 in Parser implementations

Download history 3/week @ 2024-06-14 247/week @ 2024-07-12 137/week @ 2024-07-19 205/week @ 2024-07-26 308/week @ 2024-08-02 648/week @ 2024-08-09 565/week @ 2024-08-16 680/week @ 2024-08-23 879/week @ 2024-08-30 1097/week @ 2024-09-06 726/week @ 2024-09-13 1256/week @ 2024-09-20 1030/week @ 2024-09-27

4,330 downloads per month
Used in 4 crates (3 directly)

MIT license

775KB
955 lines

Contains (ELF exe/lib, 410KB) tests/exec_elf64, (Mach-o exe, 400KB) tests/exec_mach64, (DOS exe, 145KB) tests/exec_pe64

libsui

Crates.io

Sui (सुई) is a injection tool for executable formats (ELF, PE, Mach-O) that allows you to embed files into existing binary and extract them at runtime.

It produces valid executables that can be code signed on macOS and Windows.

Documentation | Usage

Usage

cargo add libsui

Embedding data into binaries:

use libsui::{Macho, PortableExecutable};

let exe = std::fs::read("tests/exec_mach64")?;
let mut out = std::fs::File::create("out")?;

Macho::from(exe)?
    .write_section("__hello", b"Hello, World!".to_vec())?
    .build(&mut out)?;

let exe = std::fs::read("tests/exec_pe64")?;
let mut out = std::fs::File::create("out.exe")?;

PortableExecutable::from(exe)?
    .write_resource("hello.txt", b"Hello, World!".to_vec())?
    .build(&mut out)?;

Extracting from self:

use libsui::find_section;

let data = find_section("hello.txt")?;

Design

Mach-O

Resource is added as section in a new segment, load commands are updated and offsets are adjusted. __LINKEDIT is kept at the end of the file.

It is similar to linker's -sectcreate,__FOO,__foo,hello.txt option.

Note that Macho::build will invalidate existing code signature. on Apple sillicon, kernel refuses to run executables with bad signatures.

Use Macho::build_and_sign to re-sign the binary with ad-hoc signature. See apple_codesign.rs for details. This is similar to codesign -s - ./out command.

Macho::from(exe)?
    .write_section("__sect", data)?
    .build_and_sign(&mut out)?;
$ codesign -d -vvv ./out

Executable=/Users/divy/gh/sui/out
Identifier=a.out
Format=Mach-O thin (arm64)
CodeDirectory v=20400 size=10238 flags=0x20002(adhoc,linker-signed) hashes=317+0 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha256=6b1abb20f2291dd9b0dbcd0659a918cb2d0e6b18
CandidateCDHashFull sha256=6b1abb20f2291dd9b0dbcd0659a918cb2d0e6b1876153efa17f90dc8b3a8f177
Hash choices=sha256
CMSDigest=6b1abb20f2291dd9b0dbcd0659a918cb2d0e6b1876153efa17f90dc8b3a8f177
CMSDigestType=2
CDHash=6b1abb20f2291dd9b0dbcd0659a918cb2d0e6b18
Signature=adhoc
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements=none

PE

Resource is added into a new PE resource directory as RT_RCDATA type and extracted using FindResource and LoadResource at run-time.

ELF

Data is simply appended to the end of the file and extracted from current_exe() at run-time.

This is subject to change and may use ELF linker notes (PT_NOTE) in the future.

Testing

This crate is fuzzed with LLVM's libFuzzer. See fuzz/.

exec_* executables in tests/ are compiled from tests/exec.rs:

rustc exec.rs -o exec_elf64 --target x86_64-unknown-linux-gnu

License

MIT

Dependencies

~2–14MB
~125K SLoC