Unity Mono 游戏阻止自动拉起 Steam 的逆向分析
依然是我们的钓鱼游戏How to Fish
环境:Unity 游戏,Mono 后端,使用 Heathen.Steamworks 插件,无 SteamStub 壳。
啊, 如果能在u盘上带出去玩就好了, 但是一般来说steam上的游戏在exe启动时都会自动拉起steam, 这就很麻烦了
最初怀疑exe是被SteamStub加壳了, 导致 Steam 启动. 但是Steamless告诉我没壳.

用IDA看看导入表:

只引用了 kernel32.dll 和 UnityPlayer.dll 的 UnityMain2 函数, 说明主 EXE 只是一个 Unity 启动器, 并未包含 Steam 相关代码.
由于游戏使用 Unity 且为 Mono 后端,Steam 集成应该位于托管 DLL 中。
最初在 Assembly-CSharp.dll 中找到 SteamManager 类,但它只负责大厅和联机功能,没有初始化代码。
进一步发现项目使用了 Heathen.Steamworks 插件,初始化逻辑封装在 Heathen.Steamworks.dll 中。
使用dnSpy查看 Heathen.Steamworks.dll , 那么拉起steam的方法大概就应该在这里:

逐步定位到初始化调用链:
SteamworksCreator.Start()
→ SteamSettings.CreateBehaviour()
→ SteamworksBehaviour 的 Awake/Start
→ SteamSettings.Initialize()
→ App.Client.Initialize(applicationId)
在 App.Client.Initialize 方法中发现了两个关键调用:
if (SteamAPI.RestartAppIfNecessary(appId))
{
Application.Quit();
}
else
{
// ...
ESteamAPIInitResult esteamAPIInitResult = SteamAPI.InitEx(out arg);
// ...
}
SteamAPI.RestartAppIfNecessary会检查游戏是否由 Steam 启动,否则通过 Steam 重启游戏,从而拉起 Steam。SteamAPI.InitEx在初始化时若检测到 Steam 未运行,也会尝试启动 Steam 客户端。
因此,只要让 App.Client.Initialize 方法不执行任何内容,就可以阻止自动拉起 Steam。
使用 dnSpy 编辑 IL 指令, 在方法的开头直接插入ret, 使得该方法实际不执行任何内容

不要使用 dnSpy 的“编辑方法 (C#)”功能, 因为反编译代码包含编译器内部特性, 会导致奇奇怪怪的编译错误, 最好使用 编辑 IL 指令 直接修改中间语言.
修改后,该方法变为:
public static void Initialize(AppData appId)
{
// 空方法,立即返回
}
运行游戏 EXE, 不再自动启动 Steam.