主页关于链接归档

Ghidra 基本使用 & 对游戏反编译

记录

最近某音游更新了,很se,又想回坑玩玩了。于是简单看了下反编译啥的,研究了一天算是摸了点皮毛,名词什么的还是搞不懂。


本篇全程处于一个「俺寻思能行」的状态。

早在之前就知道了在淘宝上有很多售卖这游戏的 Steam 版 DLC 破解补丁的,直接覆盖到游戏目录就能解开 DLC。
推测 DLC 只是个数据,实际 DLC 内容已经在游戏本体里了,只需要检测账号是否有 DLC 来解锁内容。
于是外网搜索相关词条,翻到了俄罗斯老大哥的论坛,有相关板块,翻了一遍发现旧的破解方法及补丁已经失效了。
不过应该还是能自己搓一个。

根据论坛大佬这个很有参考价值的回复和附带的截图就能看个大概原理和需要用到的工具了:

貌似是用一个 if 语句判断的
貌似是用一个 if 语句判断的

工具

还原

首先用 Il2CppDumper 对 GameAssembly.dll 进行一个还原。
我们不需要还原后的 DLL 文件,只需要一个 script.json 提供给脚本使用。所以可以在 config.json 里把 GenerateDummyDll 改成 false

使用:

Il2CppDumper.exe "GameAssembly.dll的位置" "global-metadata.dat的位置"

反编译

打开 Ghidra,把 GameAssembly.dll 丢进去。打开会问你要不要分析,让它分析。(我也不知道是不是必要的,不分析脚本用不了,但也不需要完全全部分析才能用)

导入脚本

首先打开这个窗口,填写路径,然后会自动识别这个路径下的脚本文件。

有必要可以把其他路径关了
有必要可以把其他路径关了

然后运行这个脚本,选择刚刚生成的 script.json。报错可能是分析还没结束。

左边那个叉我也不知道要不要点
左边那个叉我也不知道要不要点

其实我没用搜索,因为已经从大佬的截图里看到了要改的地方。直接从左边小窗口的 Functions 里找就行。
没用过我也不知道,应该是这么搜索的吧。

我寻思是
我寻思是

编辑

中间窗口是汇编,右边是伪代码,应该只是拿来看的。
点伪代码里的内容后,汇编窗口会自动跳转对应位置。

根据大佬说的,貌似有一个 if 语句是判断是否有 DLC 的,需要删掉。
看截图貌似写成 NOP 就可以了。

TEST 不管他,后面的相关内容都改成 NOP。 选择多行,按下 C 或者右键选择 Clear Code Bytes。然后在右边的 Bytes 窗口改为编辑模式,全部改成 90
关闭编辑模式,返回中间汇编窗口,选择多行,按下 D 或者右键选择 Disassemble。
这时候应该能在伪代码窗口看到 if 语句已经不见了。

修改演示
修改演示

接着发现下面也有个 if 语句,应该也是跟 DLC 检测有关。
这次不删,理论把所有判断都反过来也行。比如 == 0 => != 0。 只要使用 Patch Instruction 把 JZJNZ 互换就可以了。

Patch Instruction
Patch Instruction

保存导出

左上角点击保存图标或者经典操作 Ctrl+S
然后在 File 里选择 Export Program...
Format 选择 Binary,记得把 Selection Only 取消掉,导出后会变成 文件名.dll.bin,把 .bin 删掉。

成了,但没完全成

把导出的文件替换到游戏目录,打开游戏发现成功了。
但是只解锁了曲包,要进入关卡一次才能解锁角色之类的剩下的内容。
在选曲界面还是有提示购买 DLC,但是可以直接进关卡。推测是按钮有一个单独的判断是否有 DLC,而我们刚刚把这个判断干掉了。
这时候在伪代码里发现了 Assets.Scripts.PeroTools.UI.BtnIAP$$get_default_unlock_all(0),看起来很可疑。但是不想研究了,累了。

MuseDash
MuseDash

猜到了吗,是 Muse Dash。

最后还是成了

文章刚写完发布就想起来另一个操作,有人通过 CE 脚本能直接修改出来 DLC。

CE脚本源码:

define(DLC_CHECK,Steamworks.SteamApps.BIsDlcInstalled)
define(bytes, 40 53 48 83 EC 20 8B D9 33 C9 E8)
 
[ENABLE]
{$lua}
if LaunchMonoDataCollector() ~= 0 then
    local mId = mono_findMethod('Steamworks', 'SteamApps', 'BIsDlcInstalled')
    mono_compile_method(mId)
end
{$asm}
assert(DLC_CHECK, bytes)
DLC_CHECK:
 mov rax, 1
 ret
 
[DISABLE]
DLC_CHECK:
 db bytes

参考了下 CE 脚本源码,重新改了下:

Steamworks.SteamApps.BIsDlcInstalled
Steamworks.SteamApps.BIsDlcInstalled
找到 Steamworks.SteamApps$$BIsDlcInstalled,也就是上面截图的位置,直接把下面改为 MOV RAX, 1RET
剩下的全部改成 NOP。(不知道有没有必要)

重新启动游戏,已经直接解锁了,不需要再进关卡一次才解锁。
但好像选了角色不会记录,每次重开游戏还是得重新选角色。(这几天又玩了几次,好像又会记录角色选择了)

后记

说到最后我也就学了个怎么保存导出。
研究半天太累了都不想玩了,白改了。
谁发明的白背景代码高亮,看到凌晨四点快把我整瞎了。

又试着修改了游戏内角色的技能,顺便做了个视频:【Muse Dash】修女偷取梦游少女技能致其猝死

参考

the end.