Home

Awesome

(lib)substitute

Substitute is a system for modifying code at runtime by substituting custom implementations for arbitrary functions and Objective-C methods. It is also a Free Software substitute for Cydia Substrate. It currently has full support for iOS and limited support for OS X; in the (hopefully near) future I will port it more widely.

License: LGPLv2.1+ with optional extra permissiveness; see LICENSE.txt

Current status

Alpha. Currently only build tested on Mac, targeting Mac and iOS.

To compile for iOS:

./configure --xcode-sdk=iphoneos --xcode-archs=arm64 && make -j8 && ./script/gen-deb.sh

You may want to turn off IB_VERBOSE in darwin-bootstrap/ib-log.h, which currently spams a lot of files to /tmp and spams the syslog. I will turn it off by default soon.

To compile for Mac (does not support bootstrapping/bundle loading/etc., only direct usage as a library):

./configure && make -j8

In other situations, ./configure --help should be informative. I'm using a build system I wrote from scratch, intended to be extensible for many use cases rather than project specific, and therefore somewhat complex; it's currently rather rough around the edges. Please let me know about any problems with it.

Known issues (will be fixed soon): - launchd will sometimes crash when injecting Substrate while Substitute is already loaded. [not sure whether this is still an issue] - White-on-white status bar (I think) in SafetyDance. - Each dylib is >100kb due mostly to zero padding (and fat binaries). This is easily fixed by adding FS compression, which I need to do in the deb.

How to use on iOS:

Extensions should be placed in /Library/Substitute/DynamicLibraries, with
the same layout as Substrate.  If you want to quickly test whether an
existing Substrate extension works with Substitute, you can run

install_name_tool -change \
  /Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate \
  /usr/lib/libsubstitute.0.dylib \
  extension.dylib

and move it to the new directory.

Substitute compared to Substrate

* Both libraries work by overwriting a few instructions at the beginning of such a function; to allow the substitute function to call back into the original, they first copy those instructions elsewhere, and append a jump to the unmodified instructions after the patch site constituting the rest of the function. However, some instructions depend on the current PC and will break if run from an unexpected location, so both libraries disassemble the moved instructions and fix up the most common such sequences. The benefit to this library's approach is mostly on 32-bit ARM/Thumb; ARM64 only has a few instructions that use PC, and Substrate already borrows a full x86 disassembler library.

Todo list (approx. priority order)