Scene:
I was trying to reverse engineer a mobile substrate dylib. Via IDA, the dylib called MSHookFunction() inside the constructor, and the arguments were from dlopen and dlsym. IDA failed to show the symbols of dlopen and dlsym, so I had to turn to gdb, which could possibly print the 2nd arg of dlsym, a char*, at run time.
Goal:
Break at the very beginning of the constructor of this dylib with gdb.
First Thought:
The constructor of a dylib is executed right after it's loaded, doing all the necessary initializations (Correct me if I'm wrong). So I wrote a command line tool which simply dlopen the dylib and then dlclose it, to run the constructor. FYI, here's the code of the dylib and the command line tool:
// iOSTestDylib.dylib: I'm using [Logos][1] here
%ctor
{
%init;
NSLog(@"snakeninny: ctor of dylib");
}
// iOSTestTool
#include <mach-o/dyld.h>
#include </usr/include/dlfcn.h>
int main(int argc, char **argv, char **envp)
{
NSLog(@"snakeninny: line 6 of command line tool");
void *handle = dlopen("pathOfTheAboveDylib", RTLD_LAZY);
NSLog(@"snakeninny: line 8 of command line tool");
dlclose(handle);
return 0;
}
As you can guess, once I run iOSTestTool, it printed:
- snakeninny: line 6 of command line tool
- snakeninny: ctor of dylib
- snakeninny: line 8 of command line tool
Then setting a break point inside iOSTestDylib.dylib seemed to solve the problem. But I suddenly realized that, before dlopen iOSTestDylib.dylib, the ASLR offset of iOSTestDylib.dylib was unknown, therefore the address of the bp was uncertain. Meanwhile, after dlopen, though we could figure out the ASLR offset, the ctor was already executed, so bp became meaningless. In either situation, I couldn't break inside the constructor of a dylib. Mission failed, and neither did I have a second thought, nor a plan B :(
Question:
What should I do to reach my goal?