0%

Magisk注入Unity全自动Hook实战--神庙逃亡2

在之前的一篇文章 Android 外部 imgui 绘制 (二)–补充
提到了 Unity 全自动 hook 的实现。那么就来实战一下.
游戏: 神庙逃亡 2

工具

1.Il2CppDumper
2.ida7.5
3.ndk 等编译环境

过程

Il2CppDumper 解压出 dump.cs 等函数信息

下载 Il2CppDumper
把 apk 里的 global-metadata.dat, 和 libil2cpp.so 提取出来.

1
\assets\bin\Data\Managed\Metadata\global-metadata.dat
1
\lib\armeabi-v7a\libil2cpp.so

新建文件夹 out, 命令行执行

1
Il2CppDumper.exe libil2cpp.so global-metadata.dat out

之后解压后的头文件会在 out 文件夹里.
out

dump.cs 里搜索关键点

打开 dump.cs, 搜索 kill. 顺便一提,对于没有加密的 u3 的游戏来说,关键点基本上就是 money,coin,kill,death,start 等。我的目标是实现人物无敌,所以才选择 kill.

1
2
// RVA: 0x7A7FE0 Offset: 0x7A7FE0 VA: 0x7A7FE0
public void Kill(DeathTypes deathType, float shakeCamMagnitude = 0, bool killBySelf = False) { }

得到它的 RVA 是 0x7A7FE0.

ida 分析

ida 打开 libil2cpp.so
Alt+F7 执行脚本 ida_py3.py (这个脚本在 Il2CppDumper 里), 选择 out 文件夹里的 script.json, 导入所有函数符号到 ida.
跳转到地址 0x7A7FE0, 在函数头按 X 查看其交叉引用.
ida0
jcyy
点击,因为 Stumble 有绊倒的意思。分析它大概是一个判断人物失误的函数.

1
TRRunnerPawn$$Stumble+1548

ida
唉,看到 Invincible 了,英语不好的我查了下

1
Invincible 无敌的; 不可战胜的; 不能改变的;

好家伙,这不就是我们要的判断无敌的函数吗?

1
TRRunnerPawn__IsInvincible(a1)

干就完事了.

自动 Hook

dump.cs 搜索 IsInvincible

1
2
// RVA: 0x795050 Offset: 0x795050 VA: 0x795050
public bool IsInvincible() { }

拿到地址后可以去 ida 修改硬编码,直接返回 true. 但是这样不够自动化。万一版本更新偏移变了咋办?

还记得一开头的 Unity 全自动 hook 的实现吗?
https://github.com/kotori2/riru_unity_example.

我们就来全自动 hook 一次.-_-

大佬已经帮我们写好框架了。只需要填就行.

1
2
Il2CppClass* clazz = il2cpp_class_from_name(image, "", "TRRunnerPawn");
hook_each((unsigned long)il2cpp_class_get_method_from_name(clazz, "IsInvincible", 0)->methodPointer, (void *)hook_invincible, (void **)&backup_invincible);
1
2
3
4
5
6
7
8
9
10
int hook_invincible(int a1)
{
if (backup_invincible == nullptr)
{
LOGE("backup DOES NOT EXIST");
}
// LOGD("hook");
int r = backup_invincible(a1);
return true;
}

注意
il2cpp_class_get_method_from_name 的第 3 个参数是该方法的参数个数 (dump.cs 里看到的参数个数,不是 ida), 填错就直接闪退.

smtw