Repository navigation
Conversation
The ticket handler used to answer only when one cached blob existed (ConfigStore apptickets\7) and otherwise returned without a reply; the DRM then aborts the launch. Stored tickets were also served unvalidated, and the SteamID spoof was decided independently of the bytes served. TicketAuthority now owns the decision: - validate stored tickets before serving (embedded App ID, size, signature) - derive the expected identity once; the spoof reads the same decision - discover forge bases instead of a fixed list: user hints, Lua ids, installed apps, per-app credentials, and the client ticket last - probe every discovered id in both storage locations - keep a private vault so cache clears and reinstalls cannot empty it - best-effort default that records mixed_identity; strict mode optional - optional backend fallback and import validation at load time - report each decision to opensteamtool/tickets.json
- copy steamclient64.dll to bin\diversion64.dll and hook the copy so the original module stays untouched in memory - redirect module lookups and SteamUI's LoadModuleWithPath to the copy, with an automatic fallback to the original module on any failure - pin the module and skip cleanup during process termination - check the local metadata cache before the network and write it atomically - fix CloudRedirect library lookup and shutdown bookkeeping The diversion approach follows upstream OpenSteamTool PR #193 (BSD-3-Clause).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds TicketAuthority so the client answers ownership-ticket requests reliably,
and ports the diversion startup approach with startup hardening.
Why
When a DRM-wrapped game launches, Steam asks the client for the app ownership
ticket (IClientUser::GetAppOwnershipTicketExtendedData). The old handler
answered only when one cached blob existed (ConfigStore apptickets\7), and
otherwise returned without writing a reply. The DRM then aborts the launch,
which is the failure users report as error 54. Stored tickets were also served
unvalidated, and the SteamID spoof was decided independently of the bytes
served.
What this changes
TicketAuthority (src/Utils/Tickets/TicketAuthority.{h,cpp}) is the single
owner of the decision:
forging and are kept only as a last-resort rung
credential, imports, or ETicket) and the SteamID spoof reads the same
decision, so bytes and identity cannot disagree
(appmanifest_*.acf + libraryfolders.vdf), per-app credentials, and the
Steam client ticket last; every discovered id is probed in both storage
locations
base, imported, or backend blob, so cache clears and reinstalls cannot
empty the machine
signed bytes exist, and mixing is recorded as mixed_identity; setting
identity_mode = "strict" restores refusal-only behavior
setETicket, and a per-app report in opensteamtool/tickets.json
Startup:
so the original module stays untouched in memory; module lookups and
SteamUI's LoadModuleWithPath are redirected to the copy, with an automatic
fallback to the original on any failure
and CloudRedirect lookup and shutdown paths are fixed
Configuration keys added under [tickets] in opensteamtool.toml:
prefer_stored, allow_forge, require_appid_match, require_account_match,
scan_credential_store, identity_mode, vault, allow_backend, report, sources.
Verification
(single TokeerUri export)
answered and reported as expected
Notes
failure, while mixed bytes may still launch; strict mode is available for
anyone who prefers a clean refusal