enXov/steam-leaderboards-finder

GitHub: enXov/steam-leaderboards-finder

该工具通过在运行时 Hook Steam 接口拦截函数调用,自动发现并记录游戏使用的排行榜名称。

Stars: 0 | Forks: 0

# Steam 排行榜查找工具 通过在运行时 Hook `ISteamUserStats` 接口,自动发现任意游戏使用的 Steam 排行榜名称。 ## 为什么存在这个项目 要使用 Steam API 的 `UploadLeaderboardScore` 函数,你需要一个排行榜句柄(leaderboard handle)——这需要通过调用 `FindLeaderboard` 并传入**确切的排行榜名称**来获取。但是 Steam 并没有提供列出游戏所有排行榜的方法,而且这些名称只有游戏开发者知道。 这个工具通过拦截游戏自己对 `FindLeaderboard` 的调用并记录其使用的名称来解决这个问题。一旦你获得了这些名称,就可以在自己的项目中使用它们来上传分数、下载条目或以编程方式与排行榜进行交互。 👉 **请参阅 [steam-leaderboards](https://github.com/enXov/steam-leaderboards) 以实际操作上传分数和与排行榜交互。** ## 工作原理 1. 通过一个通常被加载的 Windows DLL 在游戏启动时被加载 2. 修补 `SteamInternal_FindOrCreateUserInterface` 以拦截 `ISteamUserStats` 的创建 3. 将 `FindLeaderboard`(索引 22)和 `FindOrCreateLeaderboard`(索引 21)的 vtable 条目替换为 Hooks 4. 将发现的排行榜名称写入 `leaderboards.txt` ## 输出格式 ``` Normal Leaderboard | SortMethod=N/A | DisplayType=N/A Hard Leaderboard | SortMethod=Ascending | DisplayType=Numeric ``` ## 构建 需要 MSVC (x64)。通过 GitHub Actions 构建: 1. 前往 **Actions** → **Build DLL Proxy** 2. 选择 `winmm` 作为 DLL 类型,选择 `runtime` 作为代理方法 3. 下载构建产物 或者在本地构建: ``` cmake -B build -DDLL_TYPE=winmm -DPROXY_METHOD=runtime cmake --build build --config Release ``` ## 使用方法 1. 将构建好的 DLL 放在游戏的可执行文件目录中(紧挨着 `.exe` 文件) 2. 在 Steam 启动选项中添加以下内容: WINEDLLOVERRIDES="winmm=n,b" %command% *(在原生 Windows 上,不需要启动选项 —— DLL 会自动加载)* 3. 正常启动游戏 4. 进行游戏(浏览排行榜界面、不同模式等) 5. 在游戏可执行文件旁边的 `leaderboards.txt` 中检查发现的排行榜名称 ## 为什么采用这种方法? `FindLeaderboard` 是一个 C++ 虚方法 —— 它没有固定的地址可以直接进行 Hook。它仅作为指针存在于 `ISteamUserStats` vtable 中。要 Hook 它,首先需要 `ISteamUserStats*` 指针,以便交换其 vtable 条目。 朴素的方法是从后台线程轮询该接口。但这会产生一个**竞态条件**:游戏在主线程上创建 `ISteamUserStats` 并调用 `FindLeaderboard` 的速度非常快,后台线程无法及时安装 Hook。 解决方案是 Hook `SteamInternal_FindOrCreateUserInterface` —— 即*创建* `ISteamUserStats` 的那个函数。这样,当游戏请求该接口的那一刻,我们的 Hook 会首先触发,交换 vtable,并将修改后的接口返回给游戏。等到游戏调用 `FindLeaderboard` 时,我们的 Hook 已经就位了。 ``` Game: SteamAPI_Init() → SteamInternal_FindOrCreateUserInterface("STEAMUSERSTATS...") ↓ OUR HOOK → get ISteamUserStats* → swap vtable[22] → return to game ↓ Game: FindLeaderboard("Normal Leaderboard") → hits our hook ✅ → logged to file ``` ## 技术细节 - **接口版本**: `STEAMUSERSTATS_INTERFACE_VERSION013` - **VTable 索引**: `FindOrCreateLeaderboard` 位于 21(偏移量 168),`FindLeaderboard` 位于 22(偏移量 176) - **Hook 技术**: 对 `SteamInternal_FindOrCreateUserInterface` 执行 Inline hook(x64 绝对 JMP)+ vtable 指针交换 - **SDK**: 仅包含公共头文件用于类型定义 —— 不涉及库链接 ## 致谢 本项目构建时使用了 **[dll-proxy](https://github.com/enXov/dll-proxy)**。本 README 不打算详细说明 DLL 注入机制的工作原理 —— 如需了解 DLL 代理概念、导出转发如何工作以及如何在您自己的项目中使用它,请参考该仓库。 ## 许可证 MIT —— 详见 [LICENSE](LICENSE)。
标签:API, Bash脚本, C++, CMake, DLL 劫持, DNS解析, Hook, ISteamUserStats, MSVC, Steam, VTable, 云资产清单, 函数拦截, 大语言模型, 安全, 安全意识培训, 客户端加密, 工具, 开源项目, 排行榜, 数据擦除, 游戏开发, 端点可见性, 超时处理, 运行时补丁, 逆向工程