在网上看到一篇帖子,能够对C++ static initializers进行hook, 使用 MachOView 打开一个MachO文件,多数情况下会看到这个section __mod_init_func
,里面保存了当前模块所有的initializer函数地址,当dyld调用doModInitFunctions时便能一一调用这些initizlizer。
因为__mod_init_func在data 段,于是尝试能否在程序运行的过程中动态修改这些initializer的函数地址以达到hook的目的
其中关键的文件在for循环中的这句: ```
memory[idx] = (MemoryType)myInitFunc_Initializer;
意思是将每个initializer的函数地址都改为自己的函数地址,但会导致崩溃,有哪位懂的能说说是啥原因不???
关键代码如下:
声明dyld中的doModInitFunctions函数
typedef void (*OriginalInitializer)(int argc, const char* argv[], const char* envp[], const char* apple[], const MyProgramVars* vars);
定义自己的ModInit函数
static void myInitFunc_Initializer(int argc, const char* argv[], const char* envp[], const char* apple[], const struct MyProgramVars* vars){
NSLog(@"hook_cpp my init func\n");
//其他代码。。。
}
static void hookModInitFunc(char *model_name) {
uint32_t counts = _dyld_image_count();
const struct mach_header *mhp;
intptr_t slider;
for(uint32_t i=0; i<counts; i++){
const char* name = _dyld_get_image_name(i);
if (strstr(name, model_name)) {
mhp = _dyld_get_image_header(i);
slider = _dyld_get_image_vmaddr_slide(i);
break;
}
}
#ifndef __LP64__
unsigned long size = 0;
MemoryType *memory = (uint32_t*)getsectiondata(mhp, "__DATA", "__mod_init_func", & size);
#else /* defined(__LP64__) */
const struct mach_header_64 *mhp64 = (const struct mach_header_64 *)mhp;
unsigned long size = 0;
MemoryType *memory = (uint64_t*)getsectiondata(mhp64, "__DATA", "__mod_init_func", & size);
#endif /* defined(__LP64__) */
for(int idx = 0; idx < size/sizeof(void*); ++idx){
MemoryType original_ptr = memory[idx];
NSLog(@"original_ptr = %lld",original_ptr);
[g_initializer addObject:[NSNumber numberWithLongLong:original_ptr]]; //保存原来的地址
memory[idx] = (MemoryType)myInitFunc_Initializer;//替换为我们自己的Initializer
}
}
@interface FooObject : NSObject @end
@implementation FooObject
+ (void)load{
NSLog(@"hook_cpp==foo object load \n");
g_initializer = [NSMutableArray new];
g_cur_index = -1;
char *model_name = (char *)"/test";// 一个名为test的APP
hookModInitFunc(model_name);
}
@end