Is there a way to list all swizzled methods in an iOS app?

I am essentially looking for a way to detect when / what submasters are third-party libraries. Recently, I came across a situation where an odd AFNetworking plug was used in the advertising library. AFNetworking swizzles NSURLSessionTask, and the two swizzles did not play well under certain circumstances. I would really like to be able to detect and verify what it is, and ideally even keep all the options with a proven time in the application, so we have the appearance of someone who corrects the monkey what and what risks. Google and search turned out to be nothing more than a bunch of tutorial on how to bounce. Does anyone encounter this problem or have a solution? It seems that I could encode something using objc / runtime.h, but I cannot imagine that I am the first person who needs it.

+8
ios objective-c objective-c-runtime method-swizzling
source share
1 answer

Here I could get the closest one, tinker with a few hours. It includes the use of a mach_override fork, a couple of DYLD quirks regarding boot order, and a stomach for crazy hacks.

It will work only on the simulator, but this should be enough for the use case you use (I, of course, hope that you have no dependencies only on the device).

Soft code looks something like this:

#include <objc/runtime.h> #include <mach_override/mach_override.h> // It is extremely important that we have DYLD run this constructor as soon as the binary loads. If we were to hook // this at any other point (for example, another category on NSObject, in the main application), what could potentially // happen is other `+load` implementations get invoked before we have a chance to hook `method_exchangeImplementation`, // and we don't get to see those swizzles. // It is also extremely important that this exists inside its own dylib, which will be loaded by DYLD before _main() is // initialized. You must also make sure that this gets loaded BEFORE any other userland dylibs, which can be enforced by // looking at the order of the 'link binary with libraries' phase. __attribute__((constructor)) static void _hook_objc_runtime() { kern_return_t err; MACH_OVERRIDE(void, method_exchangeImplementations, (Method m1, Method m2), &err) { printf("Exchanging implementations for method %s and %s.\n", sel_getName(method_getName(m1)), sel_getName(method_getName(m2))); method_exchangeImplementations_reenter(m1, m2); } END_MACH_OVERRIDE(method_exchangeImplementations); MACH_OVERRIDE(void, method_setImplementation, (Method method, IMP imp), &err) { printf("Setting new implementation for method %s.\n", sel_getName(method_getName(method))); method_setImplementation_reenter(method, imp); } END_MACH_OVERRIDE(method_setImplementation); } 

Which is surprisingly simple and produces a conclusion as follows:

Exchange implementations of the method description and custom_description.

There is no good way (without using a breakpoint and viewing the stack trace) to figure out which class is swizzled, but for most things, just looking at the selector should give you a hint about where to go from there.

It seems to work with several categories that I created that swizzle during +load , and from my reading of the internal mach_override and DYLD elements, if you have your library load order configured correctly, you can expect this to be initialized before any other user-earth code if you put it in your own dynamic library.

Now I can not guarantee the safety of this, but it seems to me useful to use the debugging tool, so I posted my example on github:

https://github.com/richardjrossiii/mach_override_example

It MIT is licensed, so feel free to use as you please.

+8
source share

All Articles