这次的主角是NHN AppGuard,主角的特征是libdiresu.so libloader.so。
粗略扫一眼,居然被检测到我那藏起来的Rooting。
直接给我干闪退,幸好我打印了so 加载,不得不让我怀疑libloader.so,现在目标明确,先干它。
可以看到.init_array 有很多个函数,只有第一个函数sub_1718D4被IDA识别到,明显是第一个函数解密了后面的函数,这里有个执行顺序的问题,如果JNI_Onload 是加密的,那么就往init_array,init_proc 去分析,假如都是加密的,那没得说了。
这个壳的解密过程就不细说了,感兴趣可以去看下乐佬写的文章,看的我意犹未尽,从壳的加载解密到闪退等等,说的很详细,点赞。
乐佬的文章https://bbs.kanxue.com/thread-278113.htm
当看完乐佬的文章,你已经可以进入这次的主角,距离成功只差临门一脚。
分析Security Warning弹窗,从弹窗的样式以so加载,可以看出是Java层触发的。
通过Frida 对 Android Dialog.show 打堆栈,可以定位到com.siem.ms7.DetectionPopup。
代码中存在很多隐晦难理解的字符串,先不管它,直接找create的地方,什么鬼,居然没调用。
别慌,从堆栈打印中看到了native,得知这是从native 反射调用滴,嗦嘎!
当我们打印art的所有JNI函数,在NewStringUtf 发现令人激动的一幕。
图上所示,这堆栈怎么没有so名称和偏移啊!不会是自定义linker和开辟了一块匿名内存做检测吧?没事,我们先根据堆栈地址,从maps能不能找到一些有用的信息(正常逻辑是要分析libloader.so对Engine的加载)。
通过对maps 分析,找到堆栈位置在/data/data/com.mobirix.mbpdh/.dtam145zau/fkr5gbebm3 (deleted) 里面,其中(deleted)符合堆栈没有so名字与符号的情况,不用看,直接Hook remove。
可以看到remove了加载的so地址,我们阻止remove将so拷贝出来(暂且叫它“Engine”),此时打印堆栈就能看到对应的so名字。
除了导出函数混淆以外,代码段没加密(奇怪,我分析那会,是对代码段有加密的,现在没加密了)。
跳到 0x706391c34c iuyz5u972r!0xa834c 处,调用了JNI NewStringUTF。
打印堆栈,最终找出触发点,看出有libc的kill和syscall exit,把a2的值改成0绕过检测。
检测点,就不一一说了。
好家伙,init_array 和导出函数加密了,也没见start 与 .init_proc 函数,基本确定是通过其他so去解密的(elf结构没啥问题)。
直接揭晓,解密由libloader.so操作,过程有点复杂就不贴出来了,大概流程就是加载elf,解析elf,找到代码段,解压缩代码段,复制解压的数据回填到il2cpp里,这里推荐一个简单的办法,对il2cpp的代码段监听读写,就得用上MemoryAccessMonitor.enable。
打印出一个大概的地址,偏差不会很大,decode_iL2cpp 的v10代码段起始地址,v11是长度,hook dump出指定起始地址与长度,回填到il2cpp。
舒服,终于看到了熟悉的操作,dump出global-metadata.dat。
用Il2CppDumper dump出游戏的sdk。
查看dump.cs,舒服啊,还有韩文注释了函数的作用,hook 这些函数达到让人意想不到的结果。
难度中下,骚操作不多,集中在libloader。
样本:com.mobirix.mbpdh
看雪ID:New对象处
https://bbs.kanxue.com/user-home-807696.htm
*本文为看雪论坛优秀文章,由 New对象处 原创,转载请注明来自看雪社区
原文始发于微信公众号(看雪学苑):拳打脚踢系列之棒子的游戏——记一次探索做大哥的原理从0到1