This folder is a reproducible failure/success comparison for Mach-O dylib injection:
- The target binary (
calc) has very limited header padding (about 32 bytes). - Injecting a long dylib path can corrupt the binary after re-signing.
- Injecting a short dylib path with the right flags can persist the hook safely.
calc/calc.c: target program sourcehook/: Rust hook payload project (sighookbased)
- This example itself requires macOS aarch64 (Apple Silicon)
codesignavailable in your environment
Run from repository root:
# 1) Build insert-dylib
cargo build --release
# 2) Enter this example folder
cd examples/classic-tight-headerpad-case
# 3) Build the target binary
cc -O2 -fno-inline calc/calc.c -o calc_bin
# 4) Build the hook dylib
cargo build --release --manifest-path hook/Cargo.tomlDYLD_INSERT_LIBRARIES="$PWD/hook/target/release/libclassic_hook.dylib" ./calc_binExpected output:
[+] hooked: now x0 is 99.
Result: 99
Use a longer filename such as libh.dylib:
cp hook/target/release/libclassic_hook.dylib libh.dylib
../../target/release/insert-dylib libh.dylib calc_bin calc_bad
codesign -f -s - ./calc_bad
./calc_badCommon symptom:
- Process exits unexpectedly and does not print the expected final result line.
Use a short filename such as h.dylib:
cp hook/target/release/libclassic_hook.dylib h.dylib
../../target/release/insert-dylib --no-strip-codesig h.dylib calc_bin calc_ok
codesign -f -s - ./calc_ok
./calc_okExpected output:
[+] hooked: now x0 is 99.
Result: 99
For LC_LOAD_DYLIB, command size is:
cmdsize = 24 + align8(path_len + 1)
Where:
24is the fixed size ofstruct dylib_commandpath_len + 1includes the trailing\0
In this case:
- available header space is about 32 bytes
libh.dylibneeds 40 bytes (overflow)h.dylibneeds 32 bytes (fits exactly)
That is why long path injection fails while short path injection succeeds.
- When header padding is tight, prefer short install names.
- In this case, prefer
--no-strip-codesig. - If you can rebuild the target, add
-Wl,-headerpad_max_install_names.