Skip to content
This repository has been archived by the owner on Dec 9, 2021. It is now read-only.

Protocol

clanner edited this page Feb 9, 2015 · 4 revisions

Protocol

Packet format

ofs size contents
+00 2byte message id, see Protocol Messages
+02 3byte payload length
+05 2byte unknown
+07 encrypted message

Protocol

  • The client initializes 2 rc4 streams, with key: basekey+"nonce"

    • len(+"nonce") bytes are skipped initially.
    • One stream for client->server, and one stream for server->client communication.
  • The client connects to port 9339 ( or 843, 1863, 3724, 30000 ) of the server gamea.clashofclans.com

    • note: the server seems to be hosted in the amazon cloud.
  • The client sends a Login packet

    • When logging in for the first time, the uid fields are set to 0
    • this packet contains the 'client seed' value
    • NOTE: the masterhash has to be correct, if not you will get a LoginFailed message, containing the updated fingerprint.json contents.
  • The server responds with a Encryption packet, containing the server random value.

  • The client calculates a new nonce by scrambling the serverrandom with the client seed, using the algorithm listed below.

  • The client creates 2 new rc4 streams, now with key: basekey+servernonce

  • Then the server continues with a LoginOk message

  • Followed by the gamestate in a OwnHomeData message.

import struct
def lshift(num, n):
    return (num*(2**n))%(2**32)
def rshift(num, n):
    highbits= 0
    if num&(2**31):
        highbits= (2**n-1)*(2**(32-n))
    return (num/(2**n))|highbits
def isneg(num):
    return num&(2**31)
def negate(num):
    return (~num)+1
class prng:
    def __init__(self, seed):
        self.seed= seed
    def next(self):
        mask=0x100000000
        v3= self.seed if self.seed else 0xffffffff

        v3 ^= lshift(v3,13)
        v3 ^= rshift(v3,17)
        v3 ^= lshift(v3,5)

        self.seed= v3
        if isneg(v3):
            v3= negate(v3)
        return v3%0x100

def scramble(data, seed):
    rng= prng(seed)
    return "".join(chr(ord(c)^rng.next()) for c in data)
Clone this wiki locally