依然是我们的钓鱼游戏How to Fish

环境:Unity 游戏,Mono 后端,使用 Heathen.Steamworks 插件,无 SteamStub 壳。

啊, 如果能在u盘上带出去玩就好了, 但是一般来说steam上的游戏在exe启动时都会自动拉起steam, 这就很麻烦了

最初怀疑exe是被SteamStub加壳了, 导致 Steam 启动. 但是Steamless告诉我没壳.

1

用IDA看看导入表:

2

只引用了 kernel32.dllUnityPlayer.dllUnityMain2 函数, 说明主 EXE 只是一个 Unity 启动器, 并未包含 Steam 相关代码.

由于游戏使用 Unity 且为 Mono 后端,Steam 集成应该位于托管 DLL 中。

最初在 Assembly-CSharp.dll 中找到 SteamManager 类,但它只负责大厅和联机功能,没有初始化代码。

进一步发现项目使用了 Heathen.Steamworks 插件,初始化逻辑封装在 Heathen.Steamworks.dll 中。

使用dnSpy查看 Heathen.Steamworks.dll , 那么拉起steam的方法大概就应该在这里:

3

逐步定位到初始化调用链:

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, 使得该方法实际不执行任何内容

4

不要使用 dnSpy 的“编辑方法 (C#)”功能, 因为反编译代码包含编译器内部特性, 会导致奇奇怪怪的编译错误, 最好使用 编辑 IL 指令 直接修改中间语言.

修改后,该方法变为:

public static void Initialize(AppData appId)
{
    // 空方法,立即返回
}

运行游戏 EXE, 不再自动启动 Steam.