FuchsiaExample Objective-C C ABI

To demonstrate how to use Substrate to build an extension, we will now walk through the implementation of a concrete example: an extension that modifies the color of numerous interface components to become shades of fuchsia. This extension is useless, but has the advantage of being immediately noticeable.

This example uses Substrate's runtime API and macros. Most developers actually use Logos, a popular preprocessor that takes a declarative hook syntax and generates code that directly uses Substrate.

Step 1: Filter Configuration

The code for UIColor is in a library called UIKit, which has the bundle identifier com.apple.UIKit.

See Also:

Code Deployment: iOS / Darwin
Property Lists

Filter = {
    Bundles = ("com.apple.UIKit");
};
$ plutil -convert binary1 FuchsiaExample.plist

Step 2: Library Skeleton

Our filter is in a separate file, so we only need declare a function for our initialization code.

See Also:

Guide: Process Loading

#include <CydiaSubstrate/CydiaSubstrate.h>

// this is a macro that uses __attribute__((__constructor__))
MSInitialize {
    // ... code to run when extension is loaded
}

Step 3: Modify Implementation

The implementation of the method is replaced at the Objective-C runtime level. We thereby specify our replacement implementation using the calling convention of an Objective-C IMP.

To call the previous implementation, we use the function pointer provided when we hooked.

Here, we call through to the original and modify the result, removing all green from the color and jacking up the red (yielding shades of fuchsia).

See Also:

C API: MSHookMessageEx

UIColor *(*_UIColor$init)(id self, SEL _cmd,
    CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha);

UIColor *$UIColor$init(id self, SEL _cmd,
    CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha
) {
    return _UIColor$init(self, _cmd, 1, 0, blue, alpha);
}

MSInitialize {
    MSHookMessageEx([UIColor class], @selector(initWithRed:green:blue:alpha:),
        (IMP) &$UIColor$init, (IMP) &_UIColor$init);
}