tralph3 / Steam-Metadata-Editor

An easy to use GUI that edits the metadata of your Steam Apps
GNU General Public License v3.0
161 stars 18 forks source link

Support r/w of cd keys cache #28

Open mirh opened 1 year ago

mirh commented 1 year ago

As I reported here, steam caches the cd key of installed games (the legacy ones at least?) inside of localconfig.vdf. There's just the small problem that it's unclear where the cdk_9decdigits name comes from, and how the actual cd key value is hashed.

(as you may figure, this wouldn't just be a somewhat academical feature " just for the records", but it could help fixing certain abandoned games)

tralph3 commented 1 year ago

Figuring out how that works is going to be a pain.

On the other hand, that file is really cool, it documents all your configs. I have tested modifying launch parameters for a game though there and it worked! It's also possible to set default launch options, although that uses some weird key which I'm not sure what it's about.

Anyway, if someone figures out what that long hex string means, then maybe we can work something out.

mirh commented 1 year ago

I thought default launch parameters were set in appinfo? Or you meant the recently added "always use this launch option" thing?

Anyway, I guess like the first mystery to crack is that "cdk" thing. I found 268417985 is dead space, 268417995 is mass effect while 268427515 is cod 4. What gives? I couldn't find them anywhere, be it the registry or the steam folders.

tralph3 commented 1 year ago

I have a single one which is "268413495" but I don't know what game that belongs to. I tried to see if I could find those numbers somewhere in SteamDB's page for each game, no dice.

mirh commented 1 year ago

It should be pretty easy to figure. Just sync your steam games list with steamdb, and then filter by owned games the query in my second link above. You can then randomly try to install what comes out of it, and you should find everything. You don't even need to wait full installation and all, just starting the download is enough to populate the cache.

mirh commented 1 year ago

If it can be of any help, after 30 minutes of decompilation I found out steamclient.dll is the magic place that handles everything. Too bad I'm too stupid to understand ghidra any further.

mirh commented 3 months ago

268417985 is dead space, 268417995 is mass effect

Ok, wait, lmao, bear with me. Their normal appid is also respectively 17470 and 17460. Note how they are still spaced by 10, but with the normally higher number now being encoded lower. As if their order was inverted, starting from a common beginning of 268.435.455.

268427515+7940 is also 268.435.455. Which of course happens to be 10****²⁸ minus one. 268413495 should be Far Cry 2: Fortunes Pack? (note they killed it last month) EDIT: in more technical terms cyanic said this is the appid xored by 0xfffffff


As for the hashing, I think you really need a decompiler to understand how they do CDKEY_HASHPART. Presumably they use V_SplitStringInternal to split cd keys with dashes.. and then they somehow normalize every possible variation of them to this 1088 (1024+64?) digits long number?

Interestingly enough I found out that it's already enough for you to just open steam://cdkeys/41700 to populate the config file (only those with a "ShowCD*" attribute will immediately display in the Steam client, but still)

GMMan commented 3 months ago

The value of each cdk_* entry under UserLocalConfigStore/apps/cache is a 516-byte encrypted blob. The blob is filled with random bytes, then from offset 4, contains the string with the key, up to 512 bytes. Encryption is standard Valve CCrypto symmetric encryption with AES256-CBC-PKCS5.

Description of Valve CCrypto symmetric encryption: in the encrypted blob, the first 16 bytes is the encrypted IV. The remaining blob is the encrypted data. To decrypt, first decrypt the IV with AES-ECB, then switch to AES-CBC-PKCS5 to decrypt the rest. The same key is used for decrypting the IV and the data.

Example code for decrypting CD-key blob in C#: https://gist.github.com/GMMan/2a96925005ee8ed1aa2ce55f3461e42b