Objective-Hooker is an extra tiny Objective-C framework that lets you hook Objective-C classes without using long and cumbersome syntax or an external preprocessor.
- Simple to integrate – just add one header file and one source file to your project
- Simple to use – hooks are defined as if they were subclasses, use
super
to call the original implementation, or any other unhooked method - Can hook classes with Swift-mangled names
- Lets you easily hook and use classes that you don't link against; useful for hooking classes that come from the main executable
For all uses, you first need to add ObjectiveHooker.h
and ObjectiveHooker.m
to your project.
Include ObjectiveHooker.h
and the headers for the hooked class (In this example, AppKit.h
for NSApplication
). Use the OCHHookClass
macro to declare a pair of a hooked class and a hooking class, followed by the hooking class's @implementation
(Do not declare an @interface
, OCHHookClass
does that for you), which includes every instance or class method you want to hook. Use [super ...]
to call unhooked methods from your implementations. For example:
#import <AppKit/AppKit.h>
#import "ObjectiveHooker.h"
OCHHookClass(NSApplication, NSApplicationHook)
@implementation NSApplicationHook
+ (instancetype) sharedApplication
{
NSLog(@"OCHExampleHook");
return [super sharedApplication];
}
@end
Note: Your hooking class must not declare any ivar, including implicit ivars auto-generated by properties.
To hook or use a class your library does link against (For example, when your library is injected into an executable, and you wish to use or hook some of its classes), first declare its @interface
as you'd usually do, then use the OBHDynamicClass
macro with the class name. This will allow you to use and hook that class as if you linked to it properly. For example:
@interface DOCKIndicatorLayer : CALayer
{
@public
int _currentIndicatorSize;
}
- (void)dockBackgroundChanged;
- (void)updateIndicatorForSize:(float)arg1;
@end
OBHDynamicClass(DOCKIndicatorLayer)
...
[[DOCKIndicatorLayer alloc] init]; // You can now use that class like any normal class
To hook an Objective-C class that is implemented in Swift, and has a Swift-mangled name, use OBHHookSwiftClass
instead of OCHHookClass
. The OBHHookSwiftClass
macro takes the Swift-mangled class name as the first argument, the hooking class name as the second argument, and the Objective-C non-mangled class name as the third argument. All Swift-mangled classes are treated as if they're dynamically linked using OBHDynamicClass
, but will use the Objective-C name you used as the third argument (for example, in @interface
or when calling class methods) for example:
@interface FloorLayer : CALayer
@end
OBHHookSwiftClass(Dock.FloorLayer, FloorLayerHook, FloorLayer)
@implementation FloorLayerHook
...
@end
Objective-Hooker is licensed under the MIT license, Copyright © 2018-2020 Lior Halphon