Skip to content
pablogsalPublic

About

A patchelf reimplementation that treats ELF patching like a compiler pass

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

hexforge logo

hexforge

IR-first ELF patching in Rust.

A patchelf reimplementation that treats ELF patching like a compiler pass :)

WHY

... something something rewrite in rust ... something something proper IR lifting ... something something

What it is

hexforge patches ELF binaries and shared libraries (interpreter, rpath/runpath, needed libs, soname, execstack, symbol-version cleanup, dynamic symbol renames, and more).

The core idea is to treat patching as a compiler pipeline, not as byte surgery. hexforge first lifts raw ELF bytes into a typed intermediate representation (IR), checks that the representation is internally consistent, applies transforms against that IR, then checks again before emission. If any stage detects inconsistent structure, the pipeline stops.

Architecture

The whole idea is to not treat the files as blobs but lifting them to the cozy world of abstractions. It models ELF structure explicitly: headers, program/section layout, dynamic table entries, dynstr/dynsym state, hash/version tables, and relocation-linked symbol references. Lifting normalizes those pieces into one coherent model so operations can update related structures together instead of patching one table and hoping the rest still agrees.

Validation enforces cross-structure invariants (for example, offsets and spans, dynamic tag consistency, dynsym/dynstr compatibility, and version table coherence). That gives transforms a clear contract: mutate only through validated IR, keep linked structures synchronized, and hand back a model that still passes global checks.

CLI

hexforge has two main subcommands:

  • inspect: read ELF metadata with strict parsing/validation.
  • patch: apply mutations only when invariants hold end-to-end.

Examples:

# Inspect
hexforge inspect --interpreter --rpath --needed ./app
hexforge inspect --format json ./app

# Patch interpreter and rpath
hexforge patch --set-interpreter /lib64/ld-linux-x86-64.so.2 ./app
hexforge patch --set-rpath '/opt/lib:/usr/local/lib' --force-rpath ./app

# DT_NEEDED edits
hexforge patch --add-needed libfoo.so.1 --remove-needed libbar.so.0 ./app
hexforge patch --replace-needed libssl.so.1.1 libssl.so.3 ./app

# Write to a different output
hexforge patch --set-rpath /x ./app --output ./app.patched

Python bindings

PyO3 bindings are available in crates/hexforge-py.

import hexforge

info = hexforge.inspect_file("./app")
plan = hexforge.PatchPlan().set_rpath("/opt/lib", force_rpath=True)
outcome = hexforge.patch_file("./app", "./app.patched", plan)
print(outcome.changed)

Workspace layout

  • hexforge-elf: lift/check/emit + IR validation.
  • hexforge-ops: deterministic mutation ops over IR.
  • hexforge-model: inspection APIs.
  • hexforge-mutate: typed patch API (PatchPlan).
  • hexforge (CLI): inspect and patch.
  • hexforge-py: Python bindings.

About

A patchelf reimplementation that treats ELF patching like a compiler pass

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages