1
2
3
本人喜欢逆向,纯个人爱好,纯技术学习,如有侵仅,请联系我!技术能力有限如有错误或遗漏敬请见谅!
 
该游戏作为主流游戏,应用了较多的安全手段,采用U3D开发+il2cpp,典型的标志是,APK包的 \assets\bin\Data\Managed\Metadata 目录,有global-metadata.dat 同时\lib中有libil2cpp.so,根据论坛学到的知识使用,采用Il2CppDumper 进行反编译,软件在github或论坛其它地方下载,使用方法略过,通过反编译能编译出以下文件:

图片描述

1
然后IDA打开 libil2cpp.so,用脚本加载后也能正常识别类名方法名和参数

图片描述
乍一看,很容易,很顺利很正常,内容也看似非常正常。但实际上游戏在加载时应该是用了某种安全措施,对 global-metadata.dat 进行修改,对 libil2cpp.so 进行偏移或加密,具体安全方法未知,需要在内存中dump下 global-metadata.dat,同时 libil2cpp.so 上也进行了安全保护,只有在加载时进行dump,加载完后 libil2cpp.so 会进行加载,可通过frida进行dump具体方法论坛上有,dump通过 Il2CppDumper 反编译。

1
2
3
4
5
6
7
另外本游戏也有frida检测,如果采用USB或ATTACH模式均无法使用,实测需要通过修改端口并通过网络启动frida服务,同时需要用swap 模式进行优化附加,可以避开游戏 so 中对程序的附加(如果游戏自己附加了调试则无法frida)同时该游戏有通过 so 也无法进行IDA动态调试原因未知,不过能用frida 也很方便,不用动态调试也行。
 
以上工具使用详见论坛其它文章!本文重点在于分析的思路,是分享如何使用 dump.cs 和 libil2cpp.so 找到需求的关键位置,然后如何使用 frida 进行调试最终实现想要的功能,由于时间和篇幅的原因,无法详细到每一步的细节,以下以该游戏广告为例进行说明,游戏现状是多个功能或奖励需要查看30秒以上的广告才能获得,同时有些广告不能关闭且自动弹出各种窗口烦死人。
 
开干,用VS打开 dump.cs 我们可以看到游戏的逻辑代码的类和方法体,源代码编译在libil2cpp.so中。首先分析dump.cs文件,我们的需求是广告,那么直接搜AD 或者 show,找出可疑的,直接加入 frida中。
 
这里搜索 Ad 发现太多了,主要是有多很多包含Add的,太多了不好分析 ![图片描述](upload/attach/202407/999559_BR6HVT76FCF6HEG.jpg)

于是使用正则把add过滤掉,搜索Ad[^d],还是有900多个 图片描述
于是再换一个软件,可以用dnSpy打开dump.cs 打开ctrl+shift+k搜索程序集,包括Ad的类型,注意区分大小写,只有几十个比较,前几个发现 AdDataMgr 比较可疑,然后类打开看下,
图片描述
图片描述
可疑方法全部用frida hook住,先不管他们的参数先hook查看是否调用,和相应的流程,用frida启动游戏,发现果然打开广告时,果然有调用,调用流程是 ShowAd -> 时间到后调用 OnSuccess 其他的如OnClickAd、OnCloseAd没有调用,先不管了,有这两个,去掉这烦人的广告感觉应用可以,复制上图的方法的offset,打开IDA,按G键,输入offset,直接跳到方法,分析showAd,发现ShowAd中有两处调用了 OnSuccess , 通过IDA也查找内存引用也可以发现 OnSuccess 的调用位置图片描述

1
设想是否想法让 showAd 不经过其它无关代码,直接调用 OnSuccess 是不是就去广告了,但问题来了,首先 showAd中有两处调用 OnSuccess 是哪处呢?那么为了验证,我们就不对 OnSuccess 进行 hook ,转而hook 调用前的判断逻辑,去缩小范围,如下图:

调用一
调用二
发现在调用二处hook有反馈,那么仔细分析代码,估计调用时机是打开广告时,判断是否为特权用户,如果是就直接跳转,那么查看汇编代码发现。OnSuccess 上面有两个if判断。
图片描述
同样还是hook住 OnSuccess 直接先把 TBZ W0, #0, loc_13C1284 中TBZ换成TBNZ 使逻辑反向,运行测试,发现打开广告时,TBNZ位置有调用,然后 OnSuccess 没有调用,分析汇编代码直接把第二个判断 TBZ W0, #0, loc_13C1220 置空,点击广告直接运行 OnSuccess 至此去广告成功。
U3D游戏 hook libil2cpp.so 即可,关键代码如下:
将A0 06 00 36 修改为 A0 06 00 37即:TBZ换成TBNZ,只需要hook地址的第4字节将36修改为37

将CBZ X0, loc_13C1534 置空 NOP

最新回复:
uvbs 2024-07-04 13:24:04
U3D patch之后直接能打包回去嘛
zkbutt 2024-07-11 22:02:01
持久化没时间试哦,可以试一试
bugshunter 2024-08-28 12:59:26
楼主,我也在分析这款游戏,但是直接运行il2cppdumper那个CodeRegistration字段是0,你是怎么解决的?
zkbutt 2024-08-30 14:56:43
bugshunter 楼主,我也在分析这款游戏,但是直接运行il2cppdumper那个CodeRegistration字段是0,你是怎么解决的?
加了密的,你要用内存中dump出  libil2cpp.so global-metadata.dat 这两个文件才可以
bugshunter 2024-09-01 08:36:38
zkbutt 加了密的,你要用内存中dump出 libil2cpp.so global-metadata.dat 这两个文件才可以
我试了在内存中dump的frida脚本,因为那个偏移104还是108那个字段也是0,脚本dump出来size也是0了,你是用的什么脚本?
zkbutt 2024-09-01 15:07:01
我用的自己写的frida框架, libil2cpp.so 需要在dlopen加载方法onleave时马上dump出来,否则无效;global-metadata.dat  游戏启动后,随时可dump出,内存查找,"AF 1B B1 FA 1D 00 00 00 00 01 00 00",用查到内存的地址取偏移和大小,取出来要校验一下,内存查找可能有多个,大小和apk中大小差不多就行,let addr_offset = 0xF8;        let addr_count = 0xFC; 
mb_hrjitufz 2024-09-03 02:27:19
zkbutt 我用的自己写的frida框架, libil2cpp.so 需要在dlopen加载方法onleave时马上dump出来,否则无效;global-metadata.dat 游戏启动后,随时可dump出, ...
不知道咋回事,我在dlopen onLeave时通过Process.findModuleByName("libil2cpp.so")进行 dump出来的也有问题,so修复 后也不能用,dlopen会加载两个libil2cpp.so,看了两个大小好像不一样,不知道是不是做了什么操作。不过楼主不过去广告的话,hook GetMonthKardBoolPrivilege,然后返回该true也能达成一样的效果。
bugshunter 2024-09-06 18:17:29
老哥的意思是li2cpp.so要dump,metadata也要dump下来吗?因为我单独试了从内存中按f8和fc偏移弄出来的metadata.dat,放到il2cppDumper一样说CodeRegistration字段为0,需要手动输入
bugshunter 2024-09-06 19:39:01
zkbutt 我用的自己写的frida框架, libil2cpp.so 需要在dlopen加载方法onleave时马上dump出来,否则无效;global-metadata.dat 游戏启动后,随时可dump出, ...
试了两个都dump出来,再放到il2cppdumper里运行,提示:Input il2cpp dump address or input 0 to force continue:,输入0后,还是需要CodeRegistration字段,奇怪了,老哥,是我操作有误吗?