dll依然有加壳
![](https://file.jishuzhan.net/article/1788583261337817089/c957a989047dc3da88c75c696ddd30ef.webp)
但是这次global-metadata.dat也加密了,原工具没办法用了,不过依然是可以修复的
a. 法一:frida-il2cpp-bridge
可以用frida-il2cpp-bridge
记frida-il2cpp-bridge的使用-CSDN博客
一定要用第二种方法编译,不然那后面的脚本不好注入
(编译找不到python包就放到C盘去)
npm run watch
启动编译
![](https://file.jishuzhan.net/article/1788583261337817089/88a25cc1e6f50c9d7bc517fcc5bb40dc.webp)
bash
{
"main": "index.ts",
"scripts": {
"prepare": "npm run build",
"watch": "frida-compile index.ts -w -o hook.js"
},
"dependencies": {
"frida-il2cpp-bridge": "^0.8.5"
}
}
脚本写在这里
![](https://file.jishuzhan.net/article/1788583261337817089/728d13e3783d68094133d5d232c8f033.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/2fa88c5ff6a1179f06ac0b1f6bf40f60.webp)
TypeScript
import "frida-il2cpp-bridge";
Il2Cpp.perform(() => {
console.log(Il2Cpp.unityVersion);
Il2Cpp.dump("dump.cs", "./")
});
hook.js
会自动生成
启动ez unity.exe
![](https://file.jishuzhan.net/article/1788583261337817089/51dc208c48ed5a7993ee92a8e0c90c05.webp)
然后cmd命令注入,pid号可以在任务管理器查看
frida -l C:\frida-il2cpp-bridge\hook.js -p 4572
![](https://file.jishuzhan.net/article/1788583261337817089/166d09b39a1dd77528d9c0f662002040.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/e272d83e86a66d057c7eaec762c419f6.webp)
dump.cs就会保存在exe同目录下
![](https://file.jishuzhan.net/article/1788583261337817089/7628c85b188383d05ee01d8eaefba2ac.webp)
搜索Assembly-CSharp
得到关键函数,注释里是相对虚拟地址(Relative Virual Address,RVA)
![](https://file.jishuzhan.net/article/1788583261337817089/f0b59bd4322dbedeffff7d631ea13733.webp)
我们用IDA打开脱壳的GameAssembly.dll
,IDA显示的都是虚拟地址(VA)
VA = Imagebase(基地址) + RVA
可以用CFF Explorer查一下
![](https://file.jishuzhan.net/article/1788583261337817089/cb2a562265f6bec28815c84b08739a6b.webp)
由此可以算出上面几个函数的VA,然后手动G跳转过去就可以找到函数,进行命名
![](https://file.jishuzhan.net/article/1788583261337817089/d743dff24d4059ae7f2470dc599afc13.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/836057e550a4905748f1c557486606c6.webp)
不过字符串信息都在global-metadata.dat里,所以dll里也搞不到需要的参数(其实注释里能找到)
所以frida-il2cpp-bridge跟踪字符串
![](https://file.jishuzhan.net/article/1788583261337817089/b0668dba086563b113bd5a01f1244b3e.webp)
TypeScript
import "frida-il2cpp-bridge";
Il2Cpp.perform(() => {
console.log(Il2Cpp.unityVersion); //打印出 Unity 游戏的版本
const String = Il2Cpp.corlib.class("System.String");
//从 Unity 游戏的 mscorlib(即 Unity 的 C# 运行库)中获取了 System.String 类的引用,
//并将其存储在 String 常量中
Il2Cpp.trace(true).classes(String).and().attach();
//设置跟踪为启用状态 指定您想要跟踪的类 链式调用方法 启动跟踪
});
点击一下Check键
![](https://file.jishuzhan.net/article/1788583261337817089/b99a864e147dee60f1eaf9c91300ee1e.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/2da9eadf1cb8879324d5d32b93bf775a.webp)
可以看到被调用的参数
![](https://file.jishuzhan.net/article/1788583261337817089/634890d6ce932b5859da7f8bf3668b56.webp)
这里应该是输入的加密和原密文的对比,所以得到密文 pNufkEIU9dHjKXYXWiFyrthHYFEfqJAWcPM/t8/zX1w=
然后追踪Check类
![](https://file.jishuzhan.net/article/1788583261337817089/8b0831566ecc5f81aac46a3229044eaa.webp)
TypeScript
import "frida-il2cpp-bridge";
Il2Cpp.perform(() => {
console.log(Il2Cpp.unityVersion);
const AssemblyCSharp = Il2Cpp.domain.assembly("Assembly-CSharp").image //默认的 C# 脚本编译目标, 返回该程序集的实际内存镜像
const Check = AssemblyCSharp.class("Check"); //查找该程序集中名为 Check 的类
Il2Cpp.trace(true).classes(Check).and().attach();
});
点一下
![](https://file.jishuzhan.net/article/1788583261337817089/77e0ad1bb1209360814392131148d9cc.webp)
key = "a216d5d34c2723f5", iv = "9f68268f755b1363"
也可以这样写
TypeScript
import "frida-il2cpp-bridge";
let ass = Il2Cpp.domain.assembly("Assembly-CSharp");
//从 Unity 游戏的 IL2CPP 运行时域中获取 Assembly-CSharp 程序集的引用
Il2Cpp.trace(true).assemblies(ass).and().attach();
![](https://file.jishuzhan.net/article/1788583261337817089/60b15c0721d87f4831653eab1b26ad7b.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/5ddec827468c8e6bfd4c8af933cc7707.webp)
(woc frida真好用)
b. 法二:global-metadata.dat解密
实际上是文件头被改了
先看看正常的文件头
![](https://file.jishuzhan.net/article/1788583261337817089/a680e546d5d5371d1943242145d1108c.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/b4c915b4b84ac9aa57979a1ca8cf8f1b.webp)
改一下
![](https://file.jishuzhan.net/article/1788583261337817089/a05095c519eb639d6e6cb53b693758c7.webp)
跑一下(记得脱壳)
![](https://file.jishuzhan.net/article/1788583261337817089/4da55d5d56b173817bfae9eccc1ad1e4.webp)
之后同baby unity恢复符号表
![](https://file.jishuzhan.net/article/1788583261337817089/6472134d6a98926bbe324b880e3f608a.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/07119c9cf1858ed6ac475a3171c3b9ba.webp)
Check__AESEncrypt(input, StringLiteral_5611, StringLiteral_5124, 0i64)
的参数点开来看看
![](https://file.jishuzhan.net/article/1788583261337817089/714ac829a3a14f7b48da3eea4beca9f7.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/8c3aed18a719074cd7dd745df3898235.webp)
![](https://file.jishuzhan.net/article/1788583261337817089/cbda2298507670be0d196b63c717410d.webp)
因为都是明文存储的字符串,脚本添加的注释里可以找到AES的所有参数,然后同上用厨子解一下即可
c. 法三:CE的Mono dissector
【CheatEngine基础教程】四、Unity3D游戏《晚上nano好》修改实战 - 哔哩哔哩
![](https://file.jishuzhan.net/article/1788583261337817089/56f4958acd8dfcfdb06a5ab0661bc1a2.webp)
附加进程后激活Mono并分析
![](https://file.jishuzhan.net/article/1788583261337817089/90fabf96a807815906a6e65fbdaf2fa8.webp)
函数符号表全看到了,地址是动态的没啥用,之后还是frida钩子分析参数