Skip to main content
The “GSL” (Gate Server List) HTTP exchange is wrapped in a hybrid RSA+AES scheme. It looks like textbook envelope encryption at a glance, but the AES mode is ECB, not CBC, which turns out to make the whole thing simpler to reproduce, not harder.
Correction made during analysis. The C# source sets Mode = (CipherMode)2. It’s tempting to assume that’s CBC, it’s not. System.Security.Cryptography.CipherMode’s real ordinals are CBC=1, ECB=2, OFB=3, CFB=4, CTS=5. (CipherMode)2 is ECB. This was confirmed both by reading the enum and behaviorally: encrypting the same plaintext twice with the same key produces byte-identical ciphertext (the ECB signature), and decryption succeeds regardless of which unrelated cipher instance performs it, impossible under CBC. There is no IV because ECB has none to give.

Sequence

  1. Client generates a random 20-character salt (from an 84-char alphabet, non-cryptographic System.Random, the exact PRNG doesn’t matter to the server, only the resulting bytes do).
  2. Salt is RSA-PKCS1v1.5-encrypted against the server’s public key (delivered fresh every check-version response as base64 DER, no PEM armor) → base64 → URL-safe → this is the uuid POST field.
  3. The AES key is derived as ASCII(lowercase_hex(MD5(salt))), 32 ASCII bytes, not the raw 16-byte MD5 digest.
  4. The request body (form-encoded device/session fields) is AES-256-ECB-PKCS7 encrypted with that key → base64 → URL-safe → the data POST field. (Effective key size is 256 bits despite the source visually setting KeySize = 128, .NET’s Key setter silently overrides it based on the 32-byte key length actually assigned.)
  5. Response: if the top-level JSON has a non-empty bin field, decrypt it the same way (same salt-derived key) and re-parse as the same response shape.

Go implementation

Same key/AES-ECB scheme, reused elsewhere. The identical AESDecrypt function is reused with a hardcoded key 7a7611b0efc334a7cc229fe5d89c5997 to decrypt a server-pushed Lua snippet that’s fed directly to eval-equivalent (GameEntry.Lua.Env.DoString). Elsewhere the same client also uses a properly-chained AES-CBC-with-explicit-IV helper for a Zendesk webchat URL, so the ECB choice for GSL is a deliberate (if weak) design decision for that one path, not a general “forgot the IV” bug.