From 5df433548452965ecea2a7e622530d20cf4b3453 Mon Sep 17 00:00:00 2001 From: stkptr <85911392+stkptr@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:55:50 -0800 Subject: [PATCH 1/4] Clarify encryption scheme --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2067514..a45586b 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,9 @@ information here is from reverse engineering `v1.20.50` of the game. LAN discovery is done on the `7551` port. Clients send a request packet to the broadcast address of the network. Servers broadcast back a response packet with their name, game mode, and other information. -Discovery packets are encrypted and are prefixed with a checksum. The encryption algorithm itself is `AES-ECB` with the -key being the `SHA-256` hash of `0xdeadbeef`. The checksum is an `HMAC` with `SHA-256` and the same key. +Discovery packets are encrypted and are prefixed with a checksum. The encryption algorithm itself is `AES-ECB` with +PKCS5/7 padding. The encryption key is the `SHA-256` hash of `0xdeadbeef` encoded as a 64 bit little endian integer. +The checksum is a `SHA-256` `HMAC` of the unencrypted packet, using the same key as for encryption. Each discovery packet starts with the packet length (`uint16`), packet type (`uint16`), and sender ID (`uint64`). After that, there is an 8-byte padding, followed by the actual packet data. From 53c70d96ab7940a94556e6f4e823c19012268610 Mon Sep 17 00:00:00 2001 From: stkptr <85911392+stkptr@users.noreply.github.com> Date: Thu, 7 Mar 2024 16:21:47 -0800 Subject: [PATCH 2/4] Clarify data types --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a45586b..3bf4be1 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,17 @@ The protocol is currently not very well documented, so this covers everything ne since this is a new protocol, it is subject to change at any time and thus this document may become outdated. All information here is from reverse engineering `v1.20.50` of the game. +## Data formats + +All numbers are encoded little-endian. Strings are length prefixed, with either a uint8 or uint32 integer. + ## LAN discovery LAN discovery is done on the `7551` port. Clients send a request packet to the broadcast address of the network. Servers broadcast back a response packet with their name, game mode, and other information. Discovery packets are encrypted and are prefixed with a checksum. The encryption algorithm itself is `AES-ECB` with -PKCS5/7 padding. The encryption key is the `SHA-256` hash of `0xdeadbeef` encoded as a 64 bit little endian integer. +PKCS5/7 padding. The encryption key is the `SHA-256` hash of `0xdeadbeef` encoded as a 64 bit little-endian integer. The checksum is a `SHA-256` `HMAC` of the unencrypted packet, using the same key as for encryption. Each discovery packet starts with the packet length (`uint16`), packet type (`uint16`), and sender ID (`uint64`). After @@ -52,11 +56,12 @@ There are three discovery packets that are currently used: `DiscoveryRequestPacket` does not have any additional data. It is broadcasted by clients to look for servers on LAN. -`DiscoveryResponsePacket` sends a hex-encoded `ServerData` payload. The structure of it is as follows: +`DiscoveryResponsePacket` sends a `ServerData` payload, which is a uint32 prefixed string. The string contains hex +encoded data. The structure of the hex decoded data is as follows: - Version (`uint8`) -- Server name (`string`) -- Level name (`string`) +- Server name (`string`, uint8 prefix) +- Level name (`string`, uint8 prefix) - Game type (`int32`) - Player count (`int32`) - Max player count (`int32`) From 311cc547e3bc1e72be4e3a134c80eeddc675406c Mon Sep 17 00:00:00 2001 From: stkptr <85911392+stkptr@users.noreply.github.com> Date: Thu, 7 Mar 2024 22:20:59 -0800 Subject: [PATCH 3/4] Expand on WebRTC, formatting fixes --- README.md | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3bf4be1..c952466 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ information here is from reverse engineering `v1.20.50` of the game. ## Data formats -All numbers are encoded little-endian. Strings are length prefixed, with either a uint8 or uint32 integer. +All numbers are encoded little-endian. Strings are length prefixed, with either a `uint8` or `uint32` integer. ## LAN discovery @@ -60,8 +60,8 @@ There are three discovery packets that are currently used: encoded data. The structure of the hex decoded data is as follows: - Version (`uint8`) -- Server name (`string`, uint8 prefix) -- Level name (`string`, uint8 prefix) +- Server name (`string`, `uint8` prefix) +- Level name (`string`, `uint8` prefix) - Game type (`int32`) - Player count (`int32`) - Max player count (`int32`) @@ -117,7 +117,7 @@ There are three message types used for WebRTC negotiation: - `CONNECTRESPONSE` - `CANDIDATEADD` -The connection ID is a unique ID for each connection. +The connection ID is a unique ID for each connection. For a given negotiation, all messages will have the same ID. `CONNECTREQUEST` just contains the SDP offer from the client. The server responds with a `CONNECTRESPONSE` containing the SDP answer. After that, the client sends `CANDIDATEADD` messages with its ICE candidates. Once it has sent around @@ -171,17 +171,39 @@ Below is an example of a client's SDP offer: } ``` +The following is an actual CONNECTREQUEST sent by a client, some elements replaced with ``: + +``` +CONNECTREQUEST v=0 +o=- 2 IN IP4 127.0.0.1 +s=- +t=0 0 +a=group:BUNDLE 0 +a=extmap-allow-mixed +a=msid-semantic: WMS +m=application 9 UDP/DTLS/SCTP webrtc-datachannel +c=IN IP4 0.0.0.0 +a=ice-ufrag:<4 characters> +a=ice-pwd:<24 characters> +a=ice-options:trickle +a=fingerprint:sha-256 DB:23:<28 hex encoded bytes>:A1:D9 +a=setup:actpass +a=mid:0 +a=sctp-port:5000 +a=max-message-size: +``` + Effectively the same thing is done for the SDP answer, except the `setup` attribute is set to `active` instead of `actpass`. `CANDIDATEADD`'s data follows the standard ICE candidate string format. An example of one is below: ``` -candidate:XXXXXXXXXX 1 udp XXXXXXXXXX 127.0.0.1 12345 typ host generation 0 ufrag +2gl network-id 1 network-cost 10 +CANDIDATEADD candidate:XXXXXXXXXX 1 udp XXXXXXXXXX 127.0.0.1 12345 typ host generation 0 ufrag XXXX network-id 1 network-cost 10 ``` ## WebRTC connection Once the ICE connection is made, the client will also attempt to set up DTLS and then SCTP. Once SCTP is set up, the -client will create two data channels: +client will create two (non-negotiated, defined in-band) data channels: - `ReliableDataChannel` - `UnreliableDataChannel` From bf8a04582287b4a0c94cc6b5eeb0807c44da6e46 Mon Sep 17 00:00:00 2001 From: stkptr <85911392+stkptr@users.noreply.github.com> Date: Thu, 7 Mar 2024 23:21:32 -0800 Subject: [PATCH 4/4] Bump version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c952466..82b02cb 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ on LAN and Xbox Live games. It cannot currently be used over direct connections. The protocol is currently not very well documented, so this covers everything needed to implement it. Keep in mind that since this is a new protocol, it is subject to change at any time and thus this document may become outdated. All -information here is from reverse engineering `v1.20.50` of the game. +information here is from reverse engineering `v1.20.50` of the game, with updates from testing with `v1.20.62`. ## Data formats