Hooking requires you to provide objective-C class you would like to hook. This is what Class
type is for. One way to get obj-c class is by name via objc_getClass
function. But in your case as I understand it correctly you don't have the name. You want to hook every class that conforms to CLLocationManagerDelegate
protocol and implements specific method. Here is what you can do.
You can obtain every registered obj-C class and search for those which conform toCLLocationManagerDelegate
protocol like this:
static IMP original_didUpdateLocations;
void replaced_didUpdateLocations(id self, SEL _cmd, CLLocationManager* manager, NSArray* locations)
{
NSLog(@"%@ did update locations to %@", manager, locations);
original_didUpdateLocations(self, _cmd, manager, locations);
}
...
#import <objc/runtime.h>
int numClasses = objc_getClassList(NULL, 0);
Class* list = (Class*)malloc(sizeof(Class) * numClasses);
objc_getClassList(list, numClasses);
for (int i = 0; i < numClasses; i++)
{
if (class_conformsToProtocol(list[i], @protocol(CLLocationManagerDelegate)) &&
class_getInstanceMethod(list[i], @selector(locationManager:didUpdateLocations:)))
{
MSHookMessageEx(list[i], @selector(locationManager:didUpdateLocations:), (IMP)replaced_didUpdateLocations, (IMP*)&original_didUpdateLocations);
}
}
free(list);
We need to know how many classes there is. objc_getClassList(NULL, 0)
returns number of all registered classes.
Allocating memory with malloc(sizeof(Class) * numClasses)
and filling it with objects of type Class
using objc_getClassList(list, numClasses)
.
Searching through all these classes for those which conform to CLLocationManagerDelegate
protocol and implement locationManager:didUpdateLocations:
method. If we found one we are hooking it with our own implementation.
In our own implementation we are printing some debug message and calling original implementation before returning. Of course, you can do whatever you what, this is just an example.
Freeing allocated memory using free(list)
.