客户端与服务端通信建立流程
服务端首先通过http协议发送query_gateway
(protobuf,未加密,内涵base64格式的ec2b Key),客户端接收后通过ec2b解密,得到第一个xor Key,并与PlayerGetTokenCsReq
异或后发送给服务器,服务器根据第一个xor Key得到PlayerGetTokenCsReq
,并以相同的xor Key加密并发送PlayerGetTokenScRsp
(内涵SecretKeySeed)给客户端,客户端以SecretKeySeed作为MT19937-64算法的Seed得到第二个xor Key,此后的通信都使用此xor Key加密
PlayerGetTokenScRsp/CsReq解密分析
以下是我根据此游戏2.1Live真实wireshark抓包数据仿写的PlayerGetTokenScRsp
数据包
b8 c1 12 00 4c 5e fa e9 51 00 00 01 5a b2 0f 2a 00 00 00 00 01 00 00 00 1b 00 00 00 8f be 1b 26 61 ef 1a a5 08 57 b3 e6 f5 a8 c9 29 3f 8e c7 92 5c ed e3 d7 47 f4 bc
这段数据由KCP协议头(28 bytes,此游戏的Conv为8 bytes)与实际数据(27 bytes)组成
KCP协议
以下是正常KCP协议的构成
- Conv :连接号,因为其底层基于Udp,Udp无连接,所以需要一个连接号来确定本次消息来自于哪个客户端相当于代替了虚拟连接
- Cmd:控制字符,其中包括IKCP_CMD_PUSH(推送数据)、IKCP_CMD_ACK(回应)、IKCP_CMD_WASK(问问客户端接口窗口多大)、IKCP_CMD_WINS(告诉服务器接收窗口多大)
- Frg:分片,要传输的数据会分成几个Kcp包丢出去
- Wnd:窗口大小
- Ts:时间序列
- Sn:Kcp包的序列号
- Una:确认包的序列号,比如收到sn=1的包,回复的Ack包的una就为sn+1
- Len:数据长度
- Data:实际传输的用户数据,默认的Mtu为1400Byte
KCP协议头结构解析
b8 c1 12 00 4c 5e fa e9 (Conv) 51 (Cmd) 00 (Frg) 00 01 (Wnd) 5a b2 0f 2a (Ts) 00 00 00 00 (Sn) 01 00 00 00 (Una) 1b 00 00 00 (Len)
这里 Conv 是由最开始两个包规定的连接号,Cmd 0x51 是 IKCP_CMD_PUSH 的代码,Frg 0x00,表示没有分片,一次发送完毕 Len 0x1b 00 00 00以小端模式读取即为27 bytes数据,等等
Data数据结构
// Fields
private readonly int HeadSize; // 0x10
private readonly int BodySize; // 0x14
private uint _HeadMagic; // 0x18
private ushort _CmdID; // 0x1C
private ushort _HeadLen; // 0x1E
private uint _BodyLen; // 0x20
private MemoryStream _Head; // 0x28
private EBFAOGNJJBG _Body; // 0x30
private uint _TailMagic; // 0x38
private uint _PacketID; // 0x3C
private BIPALGMCALK _MsgProtoHead; // 0x40
private IMessage _Data; // 0x48
private byte[] _RawData; // 0x50
private uint _Seed; // 0x58
private ulong _RecvTimeStampMs; // 0x60
private bool isInUse; // 0x68
private const uint HeadMagic = 2641676052;
private const uint TailMagic = 3617673928;
private const ushort HeadVersion = 1;
private const int PacketHeadLen = 12;
private const int PacketTailLen = 4;
可以看出,每次通信由
HeadMagic + CmdID + HeadLen + BodyLen + Head+Body + TailMagic
组成,均以大端传输
Data解析
接下来我们关注
8f be 1b 26 61 ef 1a a5 08 57 b3 e6 f5 a8 c9 29 3f 8e c7 92 5c ed e3 d7 47 f4 bc
由于PlayerGetTokenScRsp
经过了ec2b的异或加密,因此此数据并不是HeadMagic($2641676052_{10} = 9d74c714_{16}$)开头,TailMagic($3617673928_{10} = d7a152c8_{16}$)结尾
根据异或的特性,$A \oplus Key = B \Rightarrow B \oplus Key = A$当我们知道ec2b Key和密文时,将两者异或即为明文
这里我给出2.1Live从query_gateway得到并通过ec2b解密后的第一个xor Key
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
两者异或后即可发现HeadMagic与TailMagic
9d 74 c7 14 00 3c 00 00 00 00 00 0b 08 d2 fe 06 58 c2 80 9c fe a9 21 d7 a1 52 c8
根据Data数据结构,我们可以发现
9d 74 c7 14 (HeadMagic) 00 3c (CmdID) 00 00 (HeadLen) 00 00 00 0b (BodyLen) 08 d2 fe 06 58 c2 80 9c fe a9 21 (Body) d7 a1 52 c8 (TailMagic)
这就是PlayerGetTokenScRsp
的具体内容,将Body进行Protobuf解析可以得到
结合
syntax = "proto3";
//CmdId:60
message PlayerGetTokenScRsp {
uint64 secret_key_seed = 11;
BlackInfo black_info = 15;
uint32 uid = 1;
string msg = 5;
uint32 retcode = 7;
}
可以发现,服务器向客户端发送了值为 1145141919810 的secret_key_seed ,值为114514 的 uid
PlayerLoginScRsp以及后续数据包解密分析
从PlayerGetTokenScRsp
以后的数据包,客户端将通过SecretKeySeed作为MT19937-64的Seed得到新的xor Key
以下同样是我仿写的PlayerLoginScRsp
数据包
b8 c1 12 00 4c 5e fa e9 51 00 00 01 e6 b2 0f 2a 01 00 00 00 02 00 00 00 50 00 00 00 32 5e c0 15 d0 f5 1f b2 fd 2a 1c 79 90 3f 24 d2 8f 2b cd dc 8f 0f ef 37 63 53 0b 7d 89 28 97 da 9b 55 40 84 07 81 8e 8e 67 78 ed 20 63 9d 98 91 29 fd 57 75 46 51 ca ed eb 58 a2 79 0c 48 e9 91 f0 41 90 c1 ca 2d 3e 56 21 56 8d c6 83 e8 61 a8
首先去除28 bytes的KCP协议头
32 5e c0 15 d0 f5 1f b2 fd 2a 1c 79 90 3f 24 d2 8f 2b cd dc 8f 0f ef 37 63 53 0b 7d 89 28 97 da 9b 55 40 84 07 81 8e 8e 67 78 ed 20 63 9d 98 91 29 fd 57 75 46 51 ca ed eb 58 a2 79 0c 48 e9 91 f0 41 90 c1 ca 2d 3e 56 21 56 8d c6 83 e8 61 a8
由于经过MT19937-64,xor Key已经与上个包不同,想要解出内容,需要先求出新的xor Key
梅森旋转算法
梅森旋转算法(Mersenne twister),可以快速产生高质量的伪随机数,修正了古典随机数发生算法的很多缺陷
常见的两种为基于32位的 MT19937和基于64位的 MT19937-64
由于梅森旋转算法是利用 线性反馈移位寄存器(LFSR) 产生随机数的,对于LFRS有结论:一个k位的移位寄存器,选取合适的特征多项式(即加1为本原多项式)时,取得最大周期$2^{k}-1$
而MT19937梅森旋转算法的周期为$2^{19937}-1$(正如算法名,这是一个梅森素数),说明它是一个19937级的线性反馈移位寄存器,梅森旋转算法是利用线性反馈寄存器一直进行移位旋转
Data解析
MT19937-64一次会生成一个64位的二进制数字(16位hex,8 bytes)共生成512次,合并为4096 bytes的xor Key
这里我给出createXorPad(1145141919810)的结果
af2a0701d0d41fb2fd2a1c3998cef33322daf3ce9f39d80e53613f4da47ea5f4aa1929f262a986be8479bf366995c8fd5c89381c3528daabdbf19141a5a95997b047e815778fa2e8eceb1bbe54493360076e8b9fbcd6cbd49b540a725b5e67dea42b4dc1d7f027e7aa23efce7885f24a3a4932ed0bfce1462eb84d16cce4e3c4de3d3a49dc1e2cafb3e6eecfe64daa0fe923ff0ef3ed2cedbba70fea778260e530a01ea35cfc93f4142510d4bfdfa7baa2e37a309007a192a7dd4fbfa16bf35e8a127bcd4a9c0defafb028efddea350afe09075fd22f2c4ec98649f4de795137e3dadd821c1a126a0acd1c66e06ea5441dc911dff92b87463d0909e06bb9c656951c16f5e48676b708424d47e7b404e62fb765a85d040268e46e6375ef3677e708114b4b7d22db86be333eb5e5e4e46bbec22b11b8712a1eb83352db924f5261633be9c59c6042ffa5c369635c2e1e84ae88c048708c1e8e4f9e1a1f2f8a2ca1801385541a04cbffe4e3de02daf733b46f2f7eb88e19c8828b0501d1e276b1504fc674bb32a1b424ce4d39a936f353b321fc8706e338740a9fe02a53bff39196789804b35ad136e90ba120dddb58a2350eadfac67bd99b793c5453d1836a8c7e3f5f51ca2979bf30862020ac04381c4dc0189ba07113a09bd7cda5f3199bf5fd579fe031bda6c1801d91058cb91009bf475f87bff51223e38767e817aed6477f66d4f804962ff3673823f6eaa89b458cb5f3f83794ac6eb1ff1ec4de10bdb90cc5cc8b82b947585d05d4cb6a0e4e879a367bbe5998db0bf2e4569ef6dea2d05454a8462de4549605c404c6f3613eef7af54679b40416a1a63b72986cb226494dcde4fd53afdc597bc7196d20de93cc060c435d7aeb4de2df7424915db111dbc710369d2ddbee9f08274bc91baac2677bdaf8c1755a642201805965926d3dde91d11b11ae0f3fad043bed0ec185492aeb2f0109cb210881479aba4bde20d4de894ab6423a1e08de5dd894a782ac7f265a77e32f7630334379e37882e0d6f6c5fa58f500586b0aa710807db72dbe98e34374f870b3d257c612df0c4a9950ed88a684cb1dab4a0bf7caab8d04efa471bc3110f362c4a30d25f1d0febf83c5d6bf9acc453de3cf5b12f260d8276b5b6647a09879ed9f2c7779f7325b68f17f7f6fab0a4fb0794ea6c69bf3474d6ef1ff594e721cee957c1398e7005aeca1a89ef72dcf83cfb064048a37aa47d8ffb392668320042f1bf2977ec0399e659cdbae07610451541b6cb83e7d83383148f6b9c0650391f127cfe04a9e604f736d43ffdfd78c2b8f4b7e576e9b91601e1712302833334ec1731a319bce82373a19917307a93253a96ad430bdceb5db7ee5fcccb1275b8befc0120576bc5842a450c139818960db57c0bbc882240833fb1ec1daec1796028ec93de06adf1fbe0ddc942891d2955c5ff3ba64f36e8c4be1fd55558ae48b708f53401d46a666c8261cc4237b5bfdc7327b94e7c4812566332a78671f48b869afd1f4067c19fb52cf8de65f6fc249f30cf3e76df08a095f503601b44ad432b8c3f1680ea0c55e3f3b169c6b624ac669097f47ffe4b6c86b73558bcca0031da680e02fe8403ed24b364eb766d87d02c656ea4831b28d05e3ba7ebfddf7fd42de5eb912174c6c8ccd608a42188c91369a7702dcb14e732328ea4033de3af6816a28d0fae50a2cd508cffe92d470b79e1c9eb477ac02e1d31a87f0dc72a60f633e46777f6212660b9bf5c80a8930efe62c5fa356b713117cce4ac6893f3bfc8748897775e6c5aa2d2d5874bdb61403b33ba65c904ba657a8b8947a6d7afc02373a6b8feac694762d4cd89559f9606e4353dc2658445788b93b9af290119958a623c759d3c25d336b55453fcda44b74be0b0270f3ca3f1c0060fe197a660d1e297a63d1e996736321e2fad34aaef6e5a921f13c9a5d0207408d25fbaa725b47b6b4940459651eba539e32cce29a81c864123e1ca441652fccacd554a4daffda5bee834d045e22fd5717b641b0dc5cc87f5452b75b0d86e4b18c5bc47e4c0dcd1e8584ad254f7b55e89c7bd90e0cfa0bf2e82c913ffbf10718ed900ca7a765621995e34c3943a976086b4baa9b429463e71b904272e56e85759315bb7f64677233a8f54403e02556ff4d6e5598ab4271e808b4e790138b5f6c27380e3bdb20633f70f97ff4979b95ac92d434eb071d0aa5759d39447b7ccce4f2dd200b0fac00a6cf860b3be544cae859f1b094b81ab68fb4dc5f42a13c614dbe0ed5bcf31369fb0e5f20e9cb8609dd184ff9d84534d92931e1e0673b89a10fa87513bb50110ded07ece21d4aaa7f7a5d3c300b10ce883461e44baeab7dd8849a2bb412208a3d6b374a406ce80fe0ad9a3f18b2aeecc585a10cebdc0ecced8c9a2216b90f33df4f0372491f4f6e5320de320e95e92be740eefb825420344863ecfeffa7ce5b4186d9ba1504f1f8ee7c4f3861863f12b76e18ee0e7e33ba712bc93d54ba158af7c52d6df5604790b21003e127003a905b4beb60955e5488f96f11d707249128b07b364e1eb1ddb21d0f437e56efea508c2fa27e715af4fb940aaba6ddd0c7c3c4e5a48118aee41da52d3509b283c6ca33221d3f856308020492d5680d97d16f48923e6cca7b8da55c316c8948f223b71b3165af68fb784b35926d3650cf948e5b63dfc7e5f63008c402c2f2be0c7816f1231cb7fe6b26e9ff0e4317ba30b16284fc607acdb1c4eafe45fdb40e26e8ac6ed06fb46733b70fdb51d28ad898a2748b4f5967e275c9a924fdf8ed159dea43a69b425f6f16ab120ad80dba301166b50c09c912f58413ac3b8384b6e08882bd8eb5c6a41c1ace12359366b19c45f486c9bde2caeaa8135cb948e7c3cf50875be551672eae8a483a57ac99813c21dc20fd589822aeaaee5da291b8bd71d7db8c0c3b4f8281889b8c9685260556aaa1375d443485e6289a2ce4688abaedfd4d1f1fba659883354f1131c3c0f3581e06d07d4c75d6d4854d86a28207dc3847b19db5aa0fe0c1e62d9f3f03e6a4ce509759e1cebfa95c434ff0a56e5044ea1359bbed21caf3e3976e65ad9fc9c4f34af421879cf3276999cc0810d11ee715bfb5fe64143354e851fdae04718af0a06e5c975613bac5877ad3c6120ac540052e5801e89dbefc4115520f33f6433b9a848d88c4b47995c18c376c3e6ecba0f91a62d5402fb65f2ec719a374d951926c21681e37d8c6b333b2f56786a561b1e917da34c13f36d567f8f79fe40e46d02d07f4ad65ffb0dda463b91fa639ae28db8bf27e20b21f7dc0bc2f1b9d7db4b851ad04b397345877f07362f96b98ebd921681059fbc2f1f59a2ebc1fa8e562a5ed77b78e3a7e94828a3d354995c18925b3f4d4b9e79fe274bd1f7c8cbd559f6beb1fc83edd0bf26b553abc46bbfcf443942fe5d7a6d9c98086b20f8a5ef512863f164ef0ca9489f78f863510c950db3b8c9d0a18145a639be2af6c6c17db76f2ace9fd57986211db1318292453b521b9f451089c1b511975f8b6e0b90c7452671112a6020740ef7e5d78976ed8c3d9709f1bebdad59c9a7916ffa8c0b2aa7315b988dabe63134050e11842cbb1fb63ac92d6e442829f88ea62f2d06ffb8a4a72d8b25c4b2d93e167af0770223192b91f87e9b790bf6142966f1325c580f71994a8f723973a708a2e6bc206ffceeb98fdad2e67f17cc3e1a3e14a3c38e4640622523595e019ee84810501b253be0ba8f34d4e58c6fb75d14d4d2b5fc48b9e420aac8df0c2725a01dfbe16da8c9eed34205c373bbc64b86a907e596e22e687311c09f5f7c30fdb3bb860a9db8f8d72f3eaa43fb78022138ea6133c45671d1cf7e06b3f937461d80d8d1505b45957d33912a813cd79efb8d6d36838471738f001e054f78f176dde25280779ca3470923e94de7ced06f34b6c4b543288c8601eeb331f3f263eb2a49a9e4c20d20584adda43d4a8c1bedb882dd426938ac0c5fcee9bcd146b33310f2316d8860053beef49d536e3539e9b3241b74863777864f81adc18bcc3902f4de8ca4cfc95464a2f0f23059bb8323625d5c8e34f77628ab29c9203838f2b3df6bb5d021cc46cd95dc216dc6e825add1b55bc11771b407250ef2d35ea7750edcc6d68459a5135a45c4b11823479d5236b4618154967be5df63e7c9fe7fdf0e0c4c62cf377a0b72459fe943fadf8212ed12c87f9b459e06a67a9cc976d5b4973ef0eaec12147e07f1c0013cdb6077ae1a152b93be7be54475095a3fac602ebd3bdb57a4ef46a274d765149f83d85f8a0893e893371e306a9f9c3e43e9c216d5149048b6870b52c9fa3fe13617a1d4b31a087f409b8ccfba6ab8b66a5fb7ccd903b4110f704b541ae615d1bf48f7ccc4ab69c4930980fb969ddc1af2cb295e8fe35fd5114a215ad217a08fa2eb32e9d4edad80f4cb8aa35539acaac410c2e3fda677ed242c36402231f2f5927de4a40c71a04b5f40f5268f2d67768928b0741662e9e43ddfa5fa821bcdf145e6c13aab9088662d1d501dbcd519a4cd129f0303cc76a595dd2500f814233d18042baef608f5fb44986eaada8e5f0c2160cef30d53f9342adfa74617c68ff3e8969a732e1893c966272391fe3dd2a3682d27fea8037d7d3fea2fab17f543d9861418e5bdff2fff5f120fc260c875dee689ab8ff6aa219f9e06a5ae43b6e2b519b8429c7670524d81ff779f0c5547512535d4c73191ef50d606188c4cc6624c035f7777eacf5e44c7411268c094c2373e4dc6ff0e70e4c845c94d51f3169649377b6e8f943e0686130743af1f0a037d741f3a0d1fc1c95e3f98e7bf55a3f1376d19cccacf892cdc832abf3f74eb159b03f4fbdf969cdfdb70700d05d3cfbf586341c563c390588fd9d5cc589ff7c15a3c653a7dd019815bad7919bd5e9b55898f4b20389b78959a5dd7fdec0487d4b2a5d776c0bb92d40d7d36f294e3b4046c9ef741db78e64b7997a0c275a55869168b0542b95160eaeb083b91295bbdfd28f3465c5411c8fb4e1c116efe7f4fe4f2e880a87985595d593b31007dc01c240383c7cf6209afbfae7296cf440f34f3eed7ad14d0dddd2ce7de55ba8b05f30bf6e53e92a536bbaa966a7a2b7bbcb92c62dbf7c87c727e386ae2cbd60418af1bc20f162c84b1e6388e87af7b652a2bba5c202bb1566f7d8174e5d8e3ca92578fc79e1c8e37b580657ba35b905f5e7ef5919b907beca624862a37d44da8e21b7dd3c65df706bcf81e5c95f656064ea9f9cd7551aaac894a33f92ada96e5a59068725888a84e0ca28fe0e46f080941bcf2dbc90a601a028d30fcbbebefd9a447b535b117171fcc0f0037493690f6d35be62a3651f405de9166deffacefa09677a04ae16e8b462929222fb1b4b9f4be2272c9f2645c59927014496d850cc68921a0cf4b1b493a514f0a4be1bdeae13551ec80f414e2fcbce928a7896cf6640f68b5fe879d39b9d09faa85503b039f932d124eac440147bde2ad358da25ea09d6f18b54a47cf5669f6d46339b070a0cf12bf2a868eb5006befc47124758b16ecadbe00bfe25f5f56d444f2c23cca55793d2b87d7484fbd59060b3d4fad6840ebc095b1e8741ea77cd081666404eab242d76927d0b0f7caf37d8097230ba5ebc67d3244c64ea04c98b009ba8e8b53254f5f34c850baa93f17e9dcf221682a8f279dddd0cbb5251a5736eab3f1125211eb92f476931ccbfedf53ed745048b8ac269b69a7109a12b72980ff166ba0f06c3d7fef80fcde420b5efdcc89caabcc3500c5e4ca493bf7fba8
两者异或后同样可发现HeadMagic与TailMagic
我们取出 Body
08 f1 d7 e1 ad f1 3e 12 10 36 37 39 30 32 34 30 2d 56 32 2e 31 4c 69 76 65 28 08 30 e3 01 52 16 0a 08 50 6c 75 74 6f 69 73 79 10 46 30 a9 33 38 a9 e1 b0 06 40 06 78 d4 bd a2 9c be cd bd 96 78
进行Protobuf解码
结合
syntax = "proto3";
//CmdId:33
message PlayerLoginScRsp {
uint32 retcode = 13;
uint64 server_timestamp_ms = 1;
uint64 login_random = 15;
PlayerBasicInfo basic_info = 10;
uint32 stamina = 6;
sint32 cur_timezone = 5;
}
message PlayerBasicInfo {
string nickname = 1;
uint32 level = 2;
uint32 exp = 3;
uint32 stamina = 4;
uint32 mcoin = 5;
uint32 hcoin = 6;
uint32 scoin = 7;
uint32 world_level = 8;
}
至此,我们已经得到了想要的内容