imfreedom/knowledgebase

Add msn

2022-04-09, Gary Kramlich
6f68cee9441e
Add msn
# Steam Friends
## Introduction
Steam Friends is an instant messaging protocol that is built into Steam, a game
content delivery system developed by Valve. This page details the protocol
specification for Steam Friends as was ascertained though reverse-engineering.
## Connection
Steam Friends uses UDP on port 27017. Connections have been made to at least
the following servers:
* 68.142.64.165
* 68.142.64.164 (resolves to valve-68-142-64-164.cust.phx3.llnw.net)
* 72.165.61.185
* 69.28.145.170
* 69.28.145.172
The client is using WSASendTo to send messages to friends
## Layers
On top of UDP, another layer is implemented to keep track of sequencing and
splitting of packets. This layers prepends every packet with the following
36-byte structure:
<table>
<tr>
<th>offset</th>
<th>0x00</th>
<th>0x02</th>
<th>0x04</th>
<th>0x06</th>
<th>0x08</th>
<th>0x0A</th>
<th>0x0C</th>
<th>0x0E</th>
</tr>
<tr>
<th>0x00</th>
<td colspan="2">"VS01"</td>
<td>packet len</td>
<td>type & bits</td>
<td colspan="2">source</td>
<td colspan="2">destination</td>
</tr>
<tr>
<th>0x10</th>
<td colspan="2">sequence #</td>
<td colspan="2"> last rcv.#</td>
<td colspan="2">split count</td>
<td colspan="2">seq. # of 1st packet</td>
</tr>
<tr>
<th>0x20</th>
<td colspan="2">data length</td>
</tr>
</table>
**Note**: These values are little-endian, which is not network order.
**Steam Protocol Header Fields Description**
Field | Type | Length (bytes) | Description
----- | ---- | -------------- | -----------
"VS01" | 4 chars | 4 | the 4 characters 'V', 'S', '0', '1' (0x56, 0x53, 0x30, 0x31)
packet len | integer | 2 | the length of the packet after this header
type & bits | byte & bit-field | 2 | the first byte is possibly some type identifier. It is always <8
destination | integer | 4 | the destination ID of the packet
source | integer | 4 | the source ID of the packet
sequence # | integer | 4 | the packet's sequence number. server and client keep track of own numbers
last recv. # | integer | 4 | the sequence number of the last packet received
split count | integer | 4 | the number of packets the current message was split in to
seq. # of 1st packet | integer | 4 | the sequence number of the first packet for current message
data length | integer | 4 | the length of the data in this message (which will be greater than packet length if the message is split)
## Login sequence
Client initiates the login by sending a type: 0x0001, seq: 1, src: 0x00000200,
dst: 0x00000000, split: 0, and no data to the server
```
00: 56 53 30 31 00 00 01 00 00 02 00 00 00 00 00 00
10: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00
```
Server responds with type: 0x0002, seq: 1, ack: 1, src: 0x00000000, dst:
0x00000200, split: 0, with 8 bytes of data attached
```
00: 56 53 30 31 08 00 02 00 00 00 00 00 00 02 00 00
10: 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00
20: 00 00 00 00 d6 3c 10 f0 a4 00 00 00
```
Client responds with type: 0x0403, sequence: 1, last: 1, dst: 0x00000200,
split: 1, with 4 bytes of data attached. This 4 bytes corresponds to the first
4 bytes that the server sent (in LE) XORed with 0xA426DF2B
```
00: 56 53 30 31 04 00 03 04 00 02 00 00 00 00 00 00
10: 01 00 00 00 01 00 00 00 01 00 00 00 01 00 00 00
20: 04 00 00 00 fd e3 36 54
```
Server responds with type: 0x0404, seq: 2, ack: 1, src: this becomes the dest
for all subsequent packets from client, split: 1
```
00: 56 53 30 31 00 00 04 04 00 eb b9 14 00 02 00 00
10: 02 00 00 00 01 00 00 00 01 00 00 00 02 00 00 00
20: 00 00 00 00
```
Server sends type: 0x0406, seq: 3, acq: 1, with the following 28 byte data
stream: "17 05 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 00 00
00 01 00 00 00"
```
00: 56 53 30 31 1c 00 06 04 00 eb b9 14 00 02 00 00
10: 03 00 00 00 01 00 00 00 01 00 00 00 03 00 00 00
20: 1c 00 00 00 17 05 00 00 ff ff ff ff ff ff ff ff
30: ff ff ff ff ff ff ff ff 01 00 00 00 01 00 00 00
```
Client responds type: 0x0406, seq: 2, acq: 3, with the following data stream:
"18 05 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 00 00 00 80 00
00 00 [128 byte RSA encrypted data block containing a 32 byte random session
key generated by the client, xx] [CRC32 of preceding 128 bytes, cc] 00 00 00
00".
```
00: 56 53 30 31 a4 00 06 04 00 02 00 00 00 34 7e fe
10: 03 00 00 00 03 00 00 00 01 00 00 00 03 00 00 00
20: a4 00 00 00 18 05 00 00 ff ff ff ff ff ff ff ff
30: ff ff ff ff ff ff ff ff 01 00 00 00 80 00 00 00
40: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
50: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
60: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
70: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
80: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
90: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
a0: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
b0: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
c0: cc cc cc cc 00 00 00 00
```
Server responds with type: 0x0406 with the following 24 bytes of data: "19 05
00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 00 00 00"
```
00: 56 53 30 31 18 00 06 04 00 34 7e fe 00 02 00 00
10: 04 00 00 00 03 00 00 00 01 00 00 00 04 00 00 00
20: 18 00 00 00 19 05 00 00 ff ff ff ff ff ff ff ff
30: ff ff ff ff ff ff ff ff 01 00 00 00
```
Server and Client now sends messages which are AES encrypted with Cipher-block
chaining (CBC). The key for the packets is transferred within the previous
message exchange. The IV used for the CBC is computed from the first 16 bytes
of each message. The decypted message appear to be compressed uses the zlib
libraries, however I've been unable to decompress them thus far.
## Encryption
The encryption method has yet to be determined. There was some discussion on
the pidgin mailing list that they might use the ICE (Information Concealment
Engine) for encryption. According to the Valve Developer pages, ICE is used to
encrypt script files used for games, so it does not seem completely
unreasonable that they could use it for their communication protocol, however,
it doesn't necessarily imply that they do use it for encryption of network
data.
Dissecting the steamclient.dll, there doesn't seem to be anything obvious that
would identify the use of ICE. However, there are several references to the
Crypto++ Library:
* CryptoPP.
* AlgorithmParametersBase
* IKeyCallback
* RSAFunction
* CipherModeBase: GetNextIV() must be called on an encryption object
* CCrypto::RSAEncrypt
* CCrypto::HexDecode
In addition, there is some thought that the 128 bytes transferred from the
client to the server (see above) might be a 1024-bit RSA public encryption key.
Noticing that the client begins sending data to the server before the server
has been able to send a key to the client, it is likely that the client has the
server's public key stored locally somewhere. However, this doesn't help with
figuring out the requests being sent by the client, unless we were to somehow
insert a fake public key for which we have the private key, then decrypt what
the client tries to send to the server. Once that's been done, the rest would
be fairly straightforward: Just send our own public key to the server, then
decrypt the responses we get back.
## Possible public keys
128 unique bytes marked with {}
### Public
```
30 81 9D 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01
05 00 03 81 8B 00 30 81 87 02 81 81 00{DF EC 1A
D6 2C 10 66 2C 17 35 3A 14 B0 7C 59 11 7F 9D D3
D8 2B 7A E3 E0 15 CD 19 1E 46 E8 7B 87 74 A2 18
46 31 A9 03 14 79 82 8E E9 45 A2 49 12 A9 23 68
73 89 CF 69 A1 B1 61 46 BD C1 BE BF D6 01 1B D8
81 D4 DC 90 FB FE 4F 52 73 66 CB 95 70 D7 C5 8E
BA 1C 7A 33 75 A1 62 34 46 BB 60 B7 80 68 FA 13
A7 7A 8A 37 4B 9E C6 F4 5D 5F 3A 99 F9 9E C4 3A
E9 63 A2 BB 88 19 28 E0 E7 14 C0 42 89}02 01 11
```
### Beta
```
30 81 9D 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01
05 00 03 81 8B 00 30 81 87 02 81 81 00{AE D1 4B
C0 A3 36 8B A0 39 0B 43 DC ED 6A C8 F2 A3 E4 7E
09 8C 55 2E E7 E9 3C BB E5 5E 0F 18 74 54 8F F3
BD 56 69 5B 13 09 AF C8 BE B3 A1 48 69 E9 83 49
65 8D D2 93 21 2F B9 1E FA 74 3B 55 22 79 BF 85
18 CB 6D 52 44 4E 05 92 89 6A A8 99 ED 44 AE E2
66 46 42 0C FB 6E 4C 30 C6 6C 5C 16 FF BA 9C B9
78 3F 17 4B CB C9 01 5D 3E 37 70 EC 67 5A 33 48
F7 46 CE 58 AA EC D9 FF 4A 78 6C 83 4B}02 01 11
```
## Externa Links
* [Third-party Plugin](http://code.google.com/p/pidgin-opensteamworks/)
developed for Pidgin (GNU GPL v3, uses Steam Mobile API as of version 1.0,
users of this appear to the network as if on a mobile device)
* Valve [developer wiki page](http://developer.valvesoftware.com/wiki/Friends)
for Steam Friends
* [Wikipedia page](http://en.wikipedia.org/wiki/Steam_%28content_delivery%29)
* [Ticket](http://developer.pidgin.im/ticket/3987) requesting support for the
Steam protocol within libpurple
* [Ticket request](http://developer.pidgin.im/ticket/14514): Create
cross-platform Steam chat plugin with Steamkit2
* December 2007 Pidgin mailing list
[thread](http://pidgin.im/pipermail/devel/2007-December/thread.html#4263)
* February 2008 Pidgin mailing list
[thread](http://pidgin.im/pipermail/devel/2008-February/thread.html#4876)
* Valve Developer Information about
[ICE](http://developer.valvesoftware.com/wiki/ICE)
* [Vapor](http://www.facepunch.com/threads/1057523-Vapor-Cross-Platform-Steam-Client) -
open-source Steam client for Linux/Windows
* [Open SteamWorks](https://bitbucket.org/VoiDeD/open-steamworks/overview) -
open-source, platform independent Steam client, written in Mono (MS NET)
* [SteamRE](https://bitbucket.org/VoiDeD/steamre/overview) - Successor of
Vapor, written in Mono
* [libsteam](https://github.com/SergeB/libsteam) - C-Library which offers basic
steam protocol functions such as login
* [SteamDroid](https://github.com/FlyingPie/SteamDroid) - SteamFriends chat
client for android devices (source, written in java)
* Even more implementations:
* [ChewieBot_SteamRE](https://github.com/cessna/ChewieBot_SteamRE/tree/master/ChewieBot_SteamRE)
* [BitlSteam](https://github.com/vahokif/BitlSteam)
* [python-steam](https://github.com/meltingwax/python-steam)
* [Vaporized](https://github.com/hekar/Vaporized)
* [pocketSteam](https://github.com/azzymaster/pocketSteam)
* [SteamMobileLib](https://github.com/Doridian/SteamMobileLib)