注入防护求助:iOS15如何获取MachO动态库加载列表。

※需求:
实现注入防护,如:frida,cycript等。

※当前方案:
1.遍历const char * dyld = _dyld_get_image_name(i)中所有的image_name
2.基于《iOS应用逆向与安全》8.3源码:MachOParser实现。
like:
//获取加载的动态库

NSArray* MachOParser::find_load_dylib(){
    NSMutableArray* array = [[NSMutableArray alloc] init];
    mach_header_t *header = (mach_header_t*)base;
    segment_command_t *cur_seg_cmd;
    uintptr_t cur = (uintptr_t)this->base + sizeof(mach_header_t);
    for (uint i = 0; i < header->ncmds; i++,cur += cur_seg_cmd->cmdsize) {
        cur_seg_cmd = (segment_command_t*)cur;
        if(cur_seg_cmd->cmd == LC_LOAD_DYLIB || cur_seg_cmd->cmd == LC_LOAD_WEAK_DYLIB){
            dylib_command *dylib = (dylib_command*)cur_seg_cmd;
            char* name = (char*)((uintptr_t)dylib + dylib->dylib.name.offset);
            NSString* dylibName = [NSString stringWithUTF8String:name];
            [array addObject:dylibName];
        }
    }
    return [array copy];
}

※目前问题:
iOS15版本系统无法像其他低版本系统一样返回完整的动态库列表。
方案1不再返回第三方动态库,方案2仅仅返回“ /usr/lib/libSystem.B.dylib

※优化方案与存在的问题。
我的方案:
将find_load_dylib方法 mach_header_t header = (mach_header_t)base;改为: mach_header_64 *header = (mach_header_64 *)&_mh_execute_header;可行。
问题:
该方案无法在动态库中实现。
通过增加“_mh_execute_header”以得到完成动态库加载列表的方法,在APP或静态库static library工程中没有问题。(至于为什么加这么一个就行了,我也是不知其所以然~)
但是在我的动态库.dylib工程中无法使用,存在报错: Showing Recent Messages Undefined symbol: __mh_execute_header

请大家帮助,指点,谢谢。

排版一下.

因为动态库的头不叫这个名字

     obfuscator->addMustPreserveSymbols("___dso_handle");
        obfuscator->addMustPreserveSymbols("__mh_execute_header");
        obfuscator->addMustPreserveSymbols("__mh_dylib_header");
        obfuscator->addMustPreserveSymbols("__mh_bundle_header");
        obfuscator->addMustPreserveSymbols("__mh_dylinker_header");
        obfuscator->addMustPreserveSymbols("__mh_object_header");
        obfuscator->addMustPreserveSymbols("__mh_preload_header");

官方的定义在 <mach-o/ldsyms.h>

1 Like

因为这是连接器保留符号,指向主程序的头部

那咋办?动态库工程里没法用这个方案,我该换个思路。 :thinking:

不用啊 dyld get vm slide0能拿到主程序的内存地址。【不太确定需不需要随机加个小偏移】然后用这个地址加dladdr还是哪个API就能拿到主程序的mh execute header了。
太久不做蓝方忘了(

嗯嗯,这次iOS15版本更新对MachO读取这块影响还是挺大的。
不光是读动态库加载列表的问题,有些重签名工具的签名IPA包在15版本上也不能通过验证了。

iOS实现注入防护,如:frida,cycript等。
iOS15你是怎么验证frida? 注入FridaGadget.dylib验证的还是iOS15能越狱了?_dyld_get_image_name还是能获取第3方库;

验证macho文件的动态库加载项“LC_LOAD_DYLIB”和“LC_LOAD_WEAK_DYLIB”里面有没有“FridaGadget.dylib”字段。
该功能在iOS15上不能像低版本一样如实输出,并不是iOS15能越狱了。

_dyld_get_image_name在iOS15上也是一样的问题,输出一大堆系统框架,不再输出第三方的了。

多谢您的提点 :heartbeat:
出现问题的原因是:iOS15中_dyld_get_image_vmaddr_slide(0)拿到的不是主程序地址,而是在_dyld_get_image_vmaddr_slide(3)中(多个工程验证,iOS15主程序都是在index-3位置,但没有官方文档,妄加猜测)。
低于iOS15版本的设备确实是dyld get vm slide0能拿到主程序的内存地址,这一变动造成了获取header失败,以至接下来的操作无法进行。
iOS15如图:

iOS13如图:

《iOS应用逆向与安全》8.3源码:MachOParser的调用方案:

前两个是Xcode调试才注入的应该。 你离开Xcode跑起来试试