源码:MonoHook,Xlua
本来只是想学一下hook的,然后发现经过XLUA注入后,hook竟然不能用了。仔细查了一下发现是XLua.Hotfix.HotfixInject()
导致的。
1.DLL注入基础
1.虚拟地址空间
Windows 中每个进程都有自己的虚拟地址空间。
进程 A 可以在位于0x12345678
地址处存储一个数据,进程 B 也可以在自己的地址空间中相同地址0x12345678
处存储一个数据。
当进程 A 中的线程访问位于地址0x12345678
处的内存时,它访问的是进程 A 的数据,进程 B 也一样,二者互不影响。
2.编译方式与方案选择(Mono or IL2CPP)
JIT与AOT:
JIT,即Just-in-time,动态(即时)编译,边运行边编译;AOT,Ahead Of Time,指运行前编译,是两种程序的编译方式
首先我们知道Mono是可以跨平台的,能实现Mono跨平台的原因是Mono可以把C#代码编译成CIL中间语言,然后在对应平台的VM再把IL指令编译成该平台使用的机器码。
Mono的这种编译方式就是JIT。
然后因为JIT的效率较AOT还是比较低的,所以Unity开发了一种基于AOT的编译方式,IL2CPP。
为什么使用IL2CPP?
- Mono VM在各个平台移植,维护非常耗时
- Mono版本授权受限
- 提高运行效率
- IOS的内存有访问权限,无法使用JIT
Android下会生成:
\assets\bin\Data\Managed\ Assembly-CSharp.dll 一般不打包进apk(游戏的控制逻辑,只作为中间文件存放,运行时不会调用)
\lib\armeabi-v7a\ libil2cpp.so, libmain.so, libunity.so (libil2cpp.so中包含了游戏控制的native code,和IL2CPP VM功能)
2.Unity DLL注入
DLL注入简单版
DLL注入大佬板
Unity的DLL注入其实就是获取DLL(C#代码编译成DLL其实都是IL指令),将其中的IL代码进行修改。替换成我们新编写的IL代码或者插入一段我们想要的IL逻辑。
3.Hook
Hook的代码其实不算是代码注入,其实算是一种IL的指针替换,把指向想要Hook的目标函数(Target Method)的指针指向我们自己定义的函数(Replacement Method),然后再用一个代理函数(Proxy Method)指向原来的目标函数。
主要的问题就是要获取三个函数的内存地址,然后修改对应指针。
4.XLUA
XLUA开启hotfix分为几步:
- 添加HOTFIX_ENABLE宏(推荐开发时不添加,也不知道我们项目为什么开发期也添加了)
- 执行XLua/Generate Code,生成Gen Code
- 执行XLua/Hotfix Inject In Editor注入,这里就是把打了标签的类型和函数都进行了DLL注入(我们项目好像对所有类型全都注入了,所以我的hook这里用不了了,因为执行到对应的gen code时报错了)
XLUA注入详解
5.Huatuo
华佗是一个基于IL2CPP的全热更方案。
IL2CPP想实现热更的话,需要把DLL转换成CPP后进行热更。IL2CPP的VM只能解释CPP代码为机器码。所以当我们正常修改代码后是不能获得DLL对应的CPP代码,而要走一次IL2CPP的代码生成流程。
华佗为IL2CPP新增了一个解释器,让IL2CPP可以支持外部DLL的解析,也就是华佗interpreter解释器实现了IL到CPP的类型转换(通过枚举转换),然后再将CPP代码交给IL2CPP的VM进行处理与解析。进而支持DLL的热更
P.S.后记,记一次XLua hotfix inject导致hook失败的问题
光速复制hook代码到工程,启动,hook一气呵成!然后发现报错了:
1 |
nvalidProgramException: Invalid IL code in DotNetDetour.LDasm:SizeofMinNumByte (void*,int): IL_0018: call 0x06007fc0 |
人已经傻了,报了个IL的错。想了一天也没想明白为什么会这样,第二天去看了一下IL的代码发现:
第18行居然是一个XLUA的代码执行。经过一天的XLUA学习,发现这段代码是在执行XLua Hotfix Inject时被注入到DLL内的。因为Xlua为了实现热更,在打了标签(项目里默认对所有类型全注入)的函数内注入一段lua的中间代码。
经过了各种各样的挣扎,比如给类型给函数加XLUA的一些黑名单,忽略标签,全都没有用。最后有一天灵光一现,把hook的代码打一个单独的Assembly Define,这样代码就不会被XLUA注入了。经过测试,果然hook又能用了!!!