样本:https://alist.iosbx.com/d/%E5%A4%A9%E7%BF%BC%E4%BA%91%E7%9B%98/Public/afzsgame.dylib
一、分析
把样本dylib用IDA打开,点OK,等待解析
等待黄灯变为绿灯
因为本身权限不够,免越狱修改基址只能使用修补,即https://github.com/pwkdje/static-inline,巨魔或者越狱可以使用vm_write。
通过static-inline.h可以看到这两个函数原型,ActiveCodePatch是修改基址,DeactiveCodePatch是恢复基址,传入三个参数,char类型的machoPath、uint64_t类型的vaddr、char类型的patch。
而在IDA中uint64_t会变成ulong long,因为 uint64_t 本质是 typedef,IDA选择底层类型显示。在IDA左边的函数窗口command + F搜索(char *,ulong long,char *),为什么?因为即使他混淆了函数名,也一定会传这三个参数进去。
可以看到有三个函数,对应
怎么区分哪个是需要hook的函数?双击进入第一个函数,View->Open subviews->Generate pseudocode查看伪代码。
下拉可以看到读取了.app文件夹。
对应StaticInlineHookPatch,不是我们需要的函数。
双击进入第二个函数,查看伪代码。
从static-inline.mm的ActiveCodePatch函数中可以看到将hookBlock->target_replace设置为一个非空地址(void*)((uint64_t)base + hookBlock->patched_vaddr),对应伪代码hook_block[9] = &module_by_path[hook_block[4]]。
为什么是hook_block9和hook_block4?因为在static-inline.h定义的结构体StaticInlineHookBlock中可以看到uint64_t patched_vaddr和void *target_replace分别偏移了32个字节和72个字节,每个uint64_t或指针占 8 字节。
UjMXdPjaeKdJ99MghN2EZKXlrxLpCNuq51(char *,ulong long,char *)函数对应ActiveCodePatch(char* machoPath, uint64_t vaddr, char* patch)
双击进入第三个函数,查看伪代码。
*(_QWORD *)(hook_block + 72) = 0LL对应DeactiveCodePatch函数里的hookBlock->target_replace = NULL
go2JHTRHkPVSbDto2gAWjeEKaoVmpTuz2(char *,ulong long,char *)对应DeactiveCodePatch(char* machoPath, uint64_t vaddr, char* patch)
二、Hook修改
打开终端创建一个theos的dylib项目。
MSHookFunction((void *)MSFindSymbol(NULL, "__Z34UjMXdPjaeKdJ99MghN2EZKXlrxLpCNuq51PcyS_"),
(void *)new_UjMXdPjaeKdJ99MghN2EZKXlrxLpCNuq51,
(void **)&original_UjMXdPjaeKdJ99MghN2EZKXlrxLpCNuq51);
MSHookFunction((void *)MSFindSymbol(NULL, "__Z33go2JHTRHkPVSbDto2gAWjeEKaoVmpTuz2PcyS_"),
(void *)new_go2JHTRHkPVSbDto2gAWjeEKaoVmpTuz2,
(void **)&original_go2JHTRHkPVSbDto2gAWjeEKaoVmpTuz2);
在new_UjMXdPjaeKdJ99MghN2EZKXlrxLpCNuq51和new_go2JHTRHkPVSbDto2gAWjeEKaoVmpTuz2用NSLog打印出参数即可,hook函数需越狱。因为他的动态库有限制bundle id,得注入他源里有的bundle id才能显示菜单。









文章评论