# OpenSteamTool **Repository Path**: zyw19871007/OpenSteamTool ## Basic Information - **Project Name**: OpenSteamTool - **Description**: No description available - **Primary Language**: Unknown - **License**: GPL-3.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-12 - **Last Updated**: 2026-06-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # OpenSteamTool ![cpp](https://img.shields.io/badge/cpp-20%2B-green?logo=cplusplus) ![CMake](https://img.shields.io/badge/CMake-3.20%2B-green?logo=cmake) ![OnlyWindows](https://img.shields.io/badge/windows%20only-red?style=for-the-badge) [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/OpenSteam001/OpenSteamTool) OpenSteamTool is a Windows DLL project built with CMake. ## Feature ### Core Unlocks - Unlock an unlimited number of unowned games. - Unlock all DLCs for unowned games. - Support auto load depot decryption keys from Lua config. - Support auto manifest download via `opensteamtool` / `steamrun` / `wudrm` upstream APIs (default is `opensteamtool`), or a custom Lua endpoint (see [Manifest via Lua](#manifest-via-lua)). - Support downloading protected games or DLCs that require an access token. - Support binding manifest to prevent specific games from being updated. ### Hot Reload - Adding, modifying, deleting, or overwriting `.lua` files in any watched directory automatically triggers a reload. No restart, no offline/online toggle needed. ### Family Sharing and Remote Play - Bypass Steam Family Sharing restrictions for games that have been added to the library with `addappid` in Lua. All accounts in the Steam Family that participate in sharing must use OpenSteamTool for this to work. ### Compatible with games protected by Denuvo and SteamStub - SteamStub-only games do not require configuring `AppTicket`. OpenSteamTool can reuse Steam's local ConfigStore ticket and forge the requested AppId through a SteamDRMP off-by-four ticket parsing vulnerability, without injecting into the game process. - Denuvo-protected games still require explicit ticket data. In `HKEY_CURRENT_USER\Software\Valve\Steam\Apps\{AppId}`, both `AppTicket` and `ETicket` are `REG_BINARY` values. - Use `setAppTicket(appid, "hex")` and `setETicket(appid, "hex")` in Lua config to write these values to the registry automatically. - AppTicket priority: explicit tickets have the highest priority, including tickets configured by `setAppTicket` and existing `AppTicket` registry values. If no explicit AppTicket is available, OpenSteamTool falls back to the forged local ConfigStore ticket path. - SteamID priority: read `SteamID` as `REG_SZ` (numeric-only) first; if missing, parse from explicit `AppTicket`. #### Extracting tickets with `extract_tickets` The `extract_tickets` tool dumps the `AppTicket` and `ETicket` hex strings you need for `setAppTicket` / `setETicket`. Run it on a machine where Steam is running and logged into an account that **owns** the target game. 1. Build the tools (see [Build](#build)); the binary lands in `build/tools/Release/extract_tickets.exe`. 2. Run it with the target AppId (or run it with no argument and type the AppId when prompted): ```powershell extract_tickets.exe 1361510 ``` 3. It reads the Steam install path from the registry, loads `steamclient64.dll`, and writes everything into an `/` folder next to the executable: - `appticket.bin` — raw app ownership ticket (binary) - `eticket.bin` — raw encrypted app ticket (binary) - `tickets.txt` — plain-text summary with the hex strings: ``` appid:1361510 appticket(184 bytes):14000000... eticket(143 bytes):... ``` A ticket that could not be obtained is reported as `appticket:null` / `eticket:null`. 4. Paste the hex strings from `tickets.txt` into your Lua config: ```lua setAppTicket(1361510, "14000000...") setETicket(1361510, "...") ``` > **Note:** Tickets are only valid when extracted from an account that **genuinely owns** the game. ### Stats and Achievements - Enable stats and achievements for unowned games. - Uses `setStat(appid, "steamid")` to configure which SteamID's achievement data to pull. - If no `setStat` is configured for an app, falls back to the hardcoded default SteamID `76561198028121353`. ### Online Fix - Add `-onlinefix` to the Steam launch parameters to enable 480-based online play in games that use lobby matchmaking. The current limitation is that only one such game can run at a time.To revert, simply remove -onlinefix from the launch parameters — online play returns to normal on the next launch. ## Future - For games protected by Denuvo and SteamStub, find a safe timing to switch `GetSteamID` (see `src/Hook/Hooks_IPC.cpp#Handler_IClientUser_GetSteamID` TODO) so save files are not affected.(**Suggestions welcome — when is the earliest point after game initialization that we can safely switch the SteamID without affecting save file binding?**) - Steam Cloud synchronization support.(This is a huge project) - Add Auto Denuvo Authorization Sharing for Legitimate Accounts. ## Usage 1. Run `build.bat` from the project root to build the project. 2. Copy generated `dwmapi.dll`, `xinput1_4.dll` and `OpenSteamTool.dll` to the Steam root directory. 3. Create Lua directory (for example `C:\steam\config\lua`) and place Lua scripts there. The DLL will automatically load and execute them. 4. Lua example: ```lua addappid(1361510) -- unlock game with appid 1361510 addappid(1361511, 0,"5954562e7f5260400040a818bc29b60b335bb690066ff767e20d145a3b6b4af0") -- unlock game with appid 1361511 depotKey is "5954562e7f5260400040a818bc29b60b335bb690066ff767e20d145a3b6b4af0" addtoken(1361510,"2764735786934684318") -- add access token ("2764735786934684318") for game with appid 1361510 -- No Longer Supported: --pinApp(1361510) -- pin game with appid 1361510 to prevent it from being updated setManifestid(1361511,"5656605350306673283") -- pin depotid:1361511 manifest_gid:5656605350306673283, size defaults to 0 setManifestid(1361511,"5656605350306673283", 12345678) -- same but with explicit size setAppTicket(1361510,"0100000000000000...") -- write AppTicket (REG_BINARY) to HKCU\Software\Valve\Steam\Apps\1361510\AppTicket setETicket(1361510,"0100000000000000...") -- write ETicket (REG_BINARY) to HKCU\Software\Valve\Steam\Apps\1361510\ETicket setStat(1361510, "76561197960287930") -- use the specified SteamID's achievement data for appid 1361510 -- If not configured, default SteamID 76561198028121353 is used. ``` All function names are **case-insensitive**. `setAppTicket`, `setappticket`, `SetAppticket`, `SETAPPTICKET` etc. are all equivalent. The same applies to every registered function (`addAppId`, `AddToken`, `SETManifestid`, etc.). ### Configuration (optional) Rename `opensteamtool.example.toml` to `opensteamtool.toml` and place it in the Steam root directory (next to `steam.exe`). If no config file is found, built-in defaults are used — no auto-creation. ```toml [log] # Debug build only. Level: trace, debug, info, warn, error level = "info" [manifest] # Upstream API for depot manifest request codes. Options: "opensteamtool", "steamrun", "wudrm" url = "opensteamtool" # HTTP timeouts for manifest requests (milliseconds) timeout_resolve_ms = 5000 timeout_connect_ms = 5000 timeout_send_ms = 10000 timeout_recv_ms = 10000 # Additional Lua config directories (optional). # Files are loaded after the default /config/lua folder. # The default folder is always loaded last so user files take priority. [lua] paths = [] # Optional metadata mirror. See "Steam version compatibility" below. [remote] # url_template = "https://your.server/{channel}/{component}/{sha256}.toml" ``` ### Manifest via Lua Two manifest code functions are supported: #### `fetch_manifest_code(gid)` Basic function that receives only the manifest GID. #### `fetch_manifest_code_ex(app_id, depot_id, gid)` *(recommended)* Extended function that receives `app_id`, `depot_id`, and `gid`. Allows constructing API endpoints that require app identification. The C++ runtime provides two Lua helpers: | Function | Signature | Returns | |----------|-----------|---------| | `http_get` | `http_get(url [, headers])` | `body, status_code` | | `http_post` | `http_post(url, body [, headers])` | `body, status_code` | `headers` is an optional table: `{["Key"]="Value", ...}`. ### Steam version compatibility OpenSteamTool no longer ships byte-pattern signatures inside the DLL. Instead, on each launch it computes the SHA-256 of `steamclient64.dll` and `steamui.dll` on disk and looks up a matching pattern file from the upstream tracker at [`OpenSteam001/steam-monitor`](https://github.com/OpenSteam001/steam-monitor) (`pattern` branch). Lookup order (every launch): 1. **GitHub raw** — `https://raw.githubusercontent.com/OpenSteam001/steam-monitor/pattern/...`. Canonical source. 2. **jsDelivr CDN** — automatic fallback if GitHub raw is unreachable (connection refused / timeout / 5xx). No configuration required. Useful in regions where `raw.githubusercontent.com` is blocked but jsDelivr is reachable (e.g. mainland China). 3. **Local cache** — `\opensteamtool\pattern\\.toml`. Used **only** when remote is unreachable. The cache is overwritten after every successful remote fetch. Remote is consulted on every launch so users automatically pick up upstream re-publications (e.g. the bot adding a new signature, or fixing an existing one) without having to clear any cache. If a step returns **HTTP 404** the mirror loop stops immediately — all mirrors serve the same content, so a 404 means the upstream bot has not yet published a TOML for this Steam build. The code then falls back to the local cache if one exists; otherwise a one-shot popup appears with the unmatched DLL name, its SHA-256, the expected cache path, and the upstream URL. Only the hooks tied to that DLL are disabled — the rest of OpenSteamTool keeps working. You can also drop a pattern TOML into the cache directory manually if you know the layout for a given build; the file name must be `.toml`. The cache fallback will pick it up the next time remote is unreachable. > A short outbound HTTPS request is performed at every launch (one per DLL: `steamclient64.dll`, `steamui.dll`). The downloaded bodies are tiny (~10 KB each) and the work runs on a worker thread, so it never blocks Steam's loader. #### Using a different mirror For most users, the built-in **GitHub -> jsDelivr** fallback is enough. To use a private mirror or intranet server, configure a full URL template. A custom mirror replaces the built-in remote sources; local cache fallback remains available. The template must include `{channel}`, `{component}`, and `{sha256}`. Channels currently used are `pattern` and `ipc`. ```toml [remote] url_template = "https://your.server/{channel}/{component}/{sha256}.toml" # url_template = "https://fast.jsdelivr.net/gh/OpenSteam001/steam-monitor@{channel}/{component}/{sha256}.toml" ``` ### Debug logging Debug builds write per-module log files under `/opensteamtool/`: | File | Source | Content | |------|--------|---------| | `main.log` | General | Init, config loading, Lua parsing,Utils | | `ipc.log` | `LOG_IPC_*` | IPC commands, InterfaceCall dispatch, spoofing | | `netpacket.log` | `LOG_NETPACKET_*` | Network packet send/recv, eMsg dispatch | | `manifest.log` | `LOG_MANIFEST_*` | Manifest download, `fetch_manifest_code`,manifest binding | | `decryptionkey.log` | `LOG_DECRYPTIONKEY_*` | Depot decryption key injection | | `keyvalue.log` | `LOG_KEYVALUE_*` | KeyValues patching (manifest binding) | | `misc.log` | `LOG_MISC_*` | Engine pointer capture, AppId hints | | `winhttp.log` | `LOG_WINHTTP_*` | HTTP requests | | `achievement.log` | `LOG_ACHIEVEMENT_*` | UserStats requests/responses, steamid spoofing | | `pics.log` | `LOG_PICS_*` | PICS access token injection | | `package.log` | `LOG_PACKAGE_*` | Package injection, FileWatcher events | | `onlinefix.log` | `LOG_ONLINEFIX_*` | Online fix (480 AppId spoofing) | The log level is controlled by `[log] level` in `opensteamtool.toml`. ## Build ### Requirements - Windows 10/11 - CMake 3.20+ - Visual Studio 2022 with MSVC (x64 toolchain) ### Runtime requirements - Outbound HTTPS access to `raw.githubusercontent.com` on first launch after a Steam update (see [Steam version compatibility](#steam-version-compatibility)). Cached afterwards. ### Quick build ```powershell build.bat ``` ### Output - Debug: `build/Debug/OpenSteamTool.dll`, `build/Debug/dwmapi.dll`, `build/Debug/xinput1_4.dll` - Release: `build/Release/OpenSteamTool.dll`, `build/Release/dwmapi.dll`, `build/Release/xinput1_4.dll` ## Disclaimer This project is provided for research and educational purposes only. You are responsible for complying with local laws, platform terms of service, and software licenses.