gslab2021 初赛 - 安卓客户端安全 | Xhy’s Blogwp参考
Assembly CSharp.dll文件已加密,路径为X:\GameSafety\Game2021\安卓客户端题目\初赛题目\RocketMouse\assets\bin\Data\Managed
mono
引擎的unity游戏,包名com.personal.rocketmouse
启动游戏会弹窗hacker detect并退出,在com.tencent.games.sec2021.Sec2021MsgBox
下找到onDismiss
方法调用系统函数exit
查找show的交叉引用找到com.tencent.games.sec2021.Sec2021IPC
的onNativeEngineResponse方法,猜测调用了native层的函数使进程退出,在ida中找kill函数的交叉引用找到函数sub_1F788,继续查找函数调用链找到1FAA8,该函数被调用了5次
用florida过掉了检测
查看libmono.so发现libmono.so经过了加密,用elf-dump-fix
在libmono.so加载之后从内存中dump并修复得到解密后的monodump.so
找到libmono.so的mono_image_open_from_data_with_name
方法,此处用于加载Assembly-CSharp.dll
文件,发现第一条指令用于跳转到libsec2021.so的sub_1CEDC
函数,此函数用于对Assembly-CSharp.dll文件解密
会先判断如果是MZ开头并且路径中没有Assembly-CSsharp.dll文件,就跳转到0x1CF88
执行,否则就调用0x1CF4C
解密函数,如图,此处会将sec2021.png的0x410B
至末尾的数据解密,解密结果为真正加载的Assembly-CSharp.dll,查看函数调用可以看到解密函数为0x1D2A0
其中sub_18CEC
为获取dll索引,crc32校验函数为subF3B4
正常会返回0,直接把返回值patch成0即可过检测
过完检测之后因为mono_image_open_from_data_with_name
函数的第一条指令会完成解密操作,所以可以hook下一条指令,当读取到真正的Assembly-CSharp.dll
时在内存中dump出来
|
|
dump完成之后分析dll文件,因为目标为实现无敌
,所以只需要修改游戏逻辑中对碰撞的检测即可,定位到MouseController
类的OnTriggerEnter2D
函数
如果不是金币就会调用HitByLaser
函数,所以只要把相应的Dead属性改为false即可,在ida中静态patch,原来为4.1,改为4.0即可
最后只需要把0x1CF88处的跳转指令改成B ,使非MZ
开头的dll才执行解密函数,并把原本的dll替换成破解版即可
复现中遇到的问题
-
打开APP就会退出并弹窗"
hacker detect:xxx
",后面发现是app检测了tmp目录下是否存在frida/ida
相关的东西,更改名称即可过检测 -
使用frida启动APP仍然会退出,是对frida的一些行为进行检测。使用
florida
过了检测 -
尝试hook libsec2021.so中的
sub_1F120
(字符串解密函数)时,会出现opcode crack
的情况,原因未查明,但是通过patch掉退出函数的调用也能过,缺点是只能hook出部分字符串 -
在dump内存的时候,会出现dump不出来的情况,后面检查发现是libmono.so是动态加载的,于是要先hook
dlopen
函数,在libmono.so加载之后再进行hook,并执行内存dump -
dump Assembly-CSharp.dll的时候,是根据dll的大小来判断的,目前不清楚具体原因是什么,但是在hook
mono_image_open_from_data_with_name
函数的时候发现他加载的文件大小差异比较大,目前猜测是比较所有被加载的dll的大小之后才判断要dump大小为0x2800
的dll文件