前言
图太多了要一个一个上传,太麻烦了,win端破解部分详情可以看我在吾爱破解发的贴:
https://www.52pojie.cn/thread-2033644-1-1.html
Unity Personal 证书需要频繁联网验证并且没办法离线使用真的很不方便,目前也没有现成的工具能破解 Unity 2022 及之后的版本,所以我决定自己动手尝试破解它。
刚开始学习逆向工程,此贴仅作记录,可能有些写的不够完善或者有错误的地方欢迎大佬们指正~
破解原理
修改Unity.exe的二进制文件,绕过校验相关的代码。通俗来讲就是把校验相关的if判断强制跳过或者强制将条件设置为true。
使用工具
IDA Pro 64 :用于静态调试和查看反汇编后的伪代码
7.6汉化版链接:https://pan.baidu.com/s/11Pp6yUHW1k-jmXtPSnFRVg?pwd=zxwu
x64dbg :用于动态调试
链接:https://github.com/x64dbg/x64dbg
x64dbg插件dbgChild :用于调试子程序(后面用于自动附加使用命令行打开的Unity)
github链接:https://github.com/therealdreg/DbgChild
x64dbg插件安装教程:https://blog.csdn.net/lhk124/article/details/107978710
(unity没有加壳,所以不需要脱壳工具,如果要逆向加过壳的软件需要先使用脱壳工具脱壳)
破解过程
删除证书文件(C:\ProgramData\Unity\Unity_lic.ulf),直接启动Unity.exe,弹出熟悉的许可证校验错误窗口,我们可以通过这个弹窗开始入手破解。
1、使用 x64dbg 附加 Unity.exe,在内存中搜索弹窗字符串的引用(右键点击搜索-所有模块-字符串)。
2、打上断点,启动并运行dbg,发现可以运行到断点处
3、在IDA中找到这段代码,按F5查看伪代码,可以看到调用这段代码的函数名为CheckLicenseActivated,猜测这个函数的作用应该是检验许可证是否生效。找到执行弹窗的语句的条件判断,可以看到这里是调用了一个虚函数,传入v48,然后判断v48偏移值为10的位置是否为true
4、找到这个函数ActiveWithErrorReason(查找虚函数的方法见补充),查看其返回值,根据代码可以看出a2是一个结构体指针,其中有一处将其首字节设置为0,可以猜测这段的逻辑应该是在有许可证时检验许可证是否生效,在没有许可证的时候直接返回错误
5、猜想成立,开始尝试。返回到dbg,找到这段代码,将其改为1
6、修改完成后继续运行,可以发现现在不会在弹窗,可以直接进入Unity Hub了!使用Unity命令行打开工程,发现不会打开工程,还是打开Unity Hub。重新加载许可证,使用Unity命令行打开工程,发现可以直接跳转到工程。由此可以推断出Unity.exe应该是在某个时机又进行了一次。
7、删除许可证,加载dbg插件dbgChild,使用dbg打开cmd,然后使用Unity命令行打开工程,等待附加了Unity的dbg打开,执行到弹出Unity Hub,发现在弹出Unity Hub前会停止,反复尝试几次可以得知在Application::InitProjectSettings中调用的HomeWindow::Show是打开Unity Hub的函数。
8、猜测就是在这之前进行了某种判断,如果许可证通过则直接打开工程,如果许可证不通过则打开hub,在IDA中查看伪代码,发现是这段判断,在dbg中将jz改为jmp,直接强制跳过跳转到Unity Hub的逻辑
9、再次使用命令行运行,直接打开工程,成功!但是问题又来了,发现使用Unity命令行打开工程运行打开的始终是上一个打开的工程,所以要继续分析。
10、继续分析InitProjectSetting函数,因为是使用命令行的projectPath参数打开的工程,所以可以寻找projectPath相关逻辑,找到一段代码和projectPath有关,并且在此处验证了许可证
11、直接跳过许可证验证
12、保存后再次使用命令行打开,可以正常打开了。
13、但是问题又来了,当我打开一个安卓工程时会弹窗需要切换平台,猜测应该是build相关的逻辑也需要验证许可证
14、这个问题很好找,直接和第一步一样找弹窗信息就好,非常轻松的就找到了弹窗的位置
15、分析Application::PromptToChangeBuildTarget函数的伪代码后可以看出弹窗代码是没有判断的逻辑的,那么应该就是在调用该函数的地方进行的判断,查找Application::PromptToChangeBuildTarget函数的交叉引用,找到了调用它的函数Application::ValidateBuildTargetSupport
16、分析伪代码,找到了它的判断条件,可以看到如果IsBuildTargetSupported为true,就会直接返回,也就不会弹窗了
17、分析IsBuildTargetSupported,找到了许可证相关的函数
18、查看该函数,发现调用了大量的ILicensingInternal接口的第一个虚函数,找到找到这个虚函数(这一步应该也可以直接让BuildPlayerLicenseCheck强制返回1,但是因为dbg调试的时候这个虚函数被调用了很多次,所以直接从这个虚函数入手)
19、找到这个虚函数,查看其返回值为0或1,那么只要将其强制返回1即可
20、改完后再次测试,可以顺利运行了!
补充,如何通过IDA查找虚函数
回到第4步,可以看到

这里是调用了ILicensingInternal接口的虚函数,所以比起改判断直接去改函数的返回值应该会更好。
如何找到接口的虚函数列表呢?
1、首先查看

返回一个指针,查看该指针的交叉引用

2、查看SetILicensing的交叉引用,跳转到该函数的位置,查看伪代码。

可以看出是先调用WorkerLicense的构造函数 创建ILicensing 接口实例,然后在将接口传给SetILicensing
3、查看WorkerLicense的构造函数,可以找到WorkerLicense的虚函数列表

双击跳转至其地址

4、每个虚函数指针占8个字节,因此这里访问的是第10个虚函数,双击地址跳转到函数实现位置

MacOS破解工具
IDA Pro7.0 for mac 用于静态调试和打补丁
下载链接:https://pan.baidu.com/s/19qXwzdxgN5zkdClrQAWUEw 提取码b482
IDA插件keypatch(上面的安装包自带,需要配置环境) IDA自带的打补丁的工具不好用,需要使用这个插件打补丁
安装python2.7和pip
然后运行命令
pip install keystone-engine
pip install six
Keypatch github链接:https://github.com/keystone-engine/keypatch
Keypatch 使用教程:https://blog.csdn.net/fjh658/article/details/52268907
Hopper Disassembler for macOS 5.18.1 用于动态调试
下载链接:https://down.52pojie.cn/Tools/Disassemblers/Hopper_Disassembler_for_macOS_5.18.1_CracKed_U2B.zip
hopper基本使用:https://www.cnblogs.com/heycomputer/articles/11317400.html
MacOS破解
破解过程和win版差别不大,主要区别是mac系统是用的arm架构,所以汇编语言会有些差异,这里就对照着win的破解过程说一下差异
1、跳过开启软件时的许可证验证(对应4-5)
根据win版本的破解经验,直接找到ActiveWithErrorReason函数,使用IDA查看伪代码,找到许可证信息的结构体指针,有两处将其首字节设置为0

到这里就能想到只要和破解win版本时一样将这里改为v3=1就可以了吧?
再来看汇编代码

v3=0对应的汇编代码是strb wzr,[x23],#8,WZR是硬编码的零寄存器,无法修改其值,所以需要使用通用寄存器中转才可以将其修改为v3=1(例如修改为:
MOV W8, #1
STRB W8, [X23], #8
),但是这样的话就需要添加新的语句,这样会影响到后续指令的地址(如果想要不影响原内存偏移的情况下实现可以找到一段空白空间,在这段空间中写新的逻辑,然后从原逻辑位置跳转到这个位置,最后通过ret返回原流程),所以直接修改的方式行不通,要想别的办法。
既然直接修改行不通,那直接把这段逻辑跳过不就可以了。来看代码,LABEL_13处明显是一段许可证不通过的逻辑

那么我们只要将,如果v32为false则跳转到这一段逻辑,那么我们只要修改这个逻辑判断就可以了,修改为直接跳转

2、跳过Unity Hub直接启动编辑器
修改方法同win直接跳过逻辑即可,区别在于win的汇编语句是jz->jmp,mac中是cbz->b

3、跳过projectPath指令的许可证验证
同上,将跳转逻辑改为b直接跳转即可

4、跳过平台相关的许可证验证
同win,强制跳转到LABLE_8,然后将result强制设置为1即可


5、导出补丁文件IDA-File-Produce file-Create DIF file
应用补丁IDA-Edit-Patch program-Apply patches to input file
6、更新签名
应用补丁后原有的签名会失效,需要使用以下命令重新签名
sudo codesign --force --deep --sign - /Applications/应用名称.app