/sui

Embed custom RO data into precompiled executables

Primary LanguageRustMIT LicenseMIT

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