-
-
[原创]浅析libFairGuard.so保护方案
-
-
[原创]浅析libFairGuard.so保护方案
前言
今天闲着无聊去应用商店找游戏,看到一款玩法比较新颖的游戏(XX之下),跟之前某跳动旗下某瞳的那款游戏很像。说到那款游戏,当时我随手写了个脚本测试,结果因为写得太晚睡着了,脚本挂了一整晚,醒来直接成了全服榜一……这里真诚道个歉,确实是无心之举。今天看到玩法相似的游戏,忍不住又手痒想看看它的保护方案。
保护概况:libFairGuard.so
这款游戏使用的是libFairGuard.so加固方案。我习惯先去看雪找找有没有相关分析,结果没找到,那就自己动手,顺便填补一下这个分析空缺。
运行策略分析
这个保护的加壳方式很直接:在原有SO的动态链接段中添加对自身保护SO的依赖。具体来说,就是在libil2cpp.so和libunity.so的依赖表中插入了libFairGuard.so。
这意味着:
· 主SO加载时会同步加载libFairGuard.so
· 由于依赖关系,保护SO优先于目标SO加载
· 加载后由它负责运行时解壳、重定向导入表
实际测试发现,受保护SO的导入表全被0A占位,运行时通过下标方式动态回填偏移量来调用系统函数(如libc库函数)。思路清晰,但实现上算不上复杂。
动态转储与反制
尝试转储
受保护影响,静态分析行不通,改用脚本动态转储SO和dat文件。转储后发现,dat元数据被篡改了。
我很少用静态转储,所以选择了动态方式:通过il2cpp API进行反射转储。不出意外,直接崩溃了——问题出在获取程序集时。懒得继续试,直接上IDA。
IDA分析发现
反编译后发现,关键函数il2cpp_domain_get_assemblies被插入了保护代码:
两种标志位分别对应主动退出和异常上报,逻辑很直白。
致命函数sub_69FE100
跟进这个函数:
一眼就能看出:这是调用exit_group强制终止进程。Hook这个函数,直接return 0,完美绕过——是不是太简单了?
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!