saul / demofile

Node.js library for parsing Counter-Strike: Global Offensive demo files
https://demofile.dev
MIT License
481 stars 53 forks source link

Valve Matchmaking Encrypted Chat #322

Closed BeepIsla closed 2 years ago

BeepIsla commented 2 years ago

Hey,

I was thinking of the possibility of adding decryption for svc_EncryptedData to this library. The encrypted data includes all chat and team chat for matchmaking demos. Although team chat uses a private encryption key not available to anyone but Valve I think. Maybe svc_EncryptedData includes more data as well, I do not know.

Anyways, I figured out how to decrypt them using the leaked CSGO source code for help. Its basically just ICE encryption with the cl_decryptdata_key/cl_decryptdata_key_pub key from the CDataGCCStrike15_v2_MatchInfo protobuf (Stored in replays/*.dem.info or received via request to the CSGO backend with MatchID, ReservationID, etc) with some random irrelevant data as well.

The JS code I attached below is my quick and dirty implementation of it all (Sorry for the ugly code) with comments linking to various parts of the CSGO source code, would love to have it implemented directly into the library! Maybe have a method to set private/public key?

encrypted-data-parsing.zip

saul commented 2 years ago

Thanks for pointing this out. Unfortunately I can't look at the code you've provided as any functionality that I add to this library must be clean room reverse engineered (or taken from Valve's open source projects, like demoinfogo). If I was to incorporate code that was written from the leaked engine code, I'd be liable for copyright violations.

I'll see if I can add new APIs like setDecryptionKeys which would enable parsing of svc_EncryptedData messages. I'd then leave it up to the consumer to extract this data from the match info protobufs.

saul commented 2 years ago

This is now available in v2.2.0. You can use it like:

import { DemoFile, extractPublicEncryptionKey } from "demofile";

const demoFile = new DemoFile();
// setup event handlers as usual

// 🌟 NEW: Read public key from `.dem.info` file
demoFile.setEncryptionKey(extractPublicEncryptionKey(fs.readFileSync("path/to/my.dem.info")));

demoFile.parse(...);
OnlyReFLeX commented 2 years ago

Hi @saul, could you help me, where I can get .dem.info file? (public key)

saul commented 2 years ago

The .dem.info file is actually the CMsgGCCStrike15_v2_MatchList message for a given match. You can get this by using a tool like https://github.com/akiver/boiler-writter. You will need the share code of the match and decode it into a matchId, outcomeId and tokenId.

markus-wa commented 2 years ago

:wave: - looks like both of our decryption implementations fail to decrypt certain messages in certain demos.

see https://github.com/markus-wa/demoinfocs-golang/issues/326 for some repoduction examples.

It looks like the first issue is paddingBytes > message length - so I assume that: A: the decryption is not working correctly B: or the decryption key is not being read correctly C (unlikely): the data is corrupted (either key in .info or message in .dem)

I'll let you know if/when I find out more :slightly_smiling_face:

saul commented 2 years ago

Thanks for the report @markus-wa. I've raised a PR here with some encrypted message improvements: https://github.com/saul/demofile/pull/362