Decoded: Steam In-Home Streaming Control Protocol
January 26th, 2014
With the Discovery protocol done, the control protocol’s format has proven to be quite elusive. Looking at a packet capture, the format seemed to be, repeated:
- 3 bytes of unknown contents
- 2 bytes big-endian, which is the payload size
- N bytes, which is the payload
What eventually gave it away was that the string “steam” appeared in one of the packets, and following that in a disassembler pointed me to SSL PSK methods.
Of course, once I found that I noticed that it had been staring me in the face the whole time.
The next question then is, from where does the Pre-Shared Key (PSK) come from? That also turned out to have been staring me in the face for a while, as I found it quite quickly when looking at an old dump of Steam’s traffic from NetHook:
(Update: If you want to find your own key, Steam caches it in userdata/your Steam account ID/config/localconfig.vdf - look for ‘AuthData’ in the ‘SharedAuth’ section.)
A quick test of that key showed that I was right.
A few things are instantly recognisable - VT01 is Valve’s “Magic” value for the TCP protocol that the Steam client uses to communicate with the Steam servers. The other recognisable string in there is “Yavin”, which is my computer’s machine name.
Most likely then, this follows the standard “CM Client” protocol which is:
- Length: uint32, little-endian - length of the payload
- Magic: uint32, little-endian - “VT01”
- Payload: number of bytes specified in Length. The payload starts with a little-endiant uint32 EMsg value.
The relevant EMsg values for the Remote Control protocol are:
- Auth: 0x251C (9500)
- AuthResponse: 0x251D (9501)
- AppStatus: 0x251E (9502)
- StartStream: 0x251F (9503)
- StartStreamResponse: 0x2520 (9504)
- Ping: 0x2521 (9505)
- PingResponse: 0x2522 (9506)
Unfortunately I can’t feasibly progress any further as I can’t find any decent libraries that support TLS-PSK. The only one I can find is OpenSSL (which is what Valve uses), but it’s so low-level that there’s an enormous amount of overhead before I can even send or recieve any data that it might just not be worth it.
Any third-party client would need to connect to Steam to obtain the Pre-Shared Key, which while doable, also adds a lot more work before I can even launch a game to stream.
If anyone knows of any high-level TLS-PSK client libraries, please let me know.