点击上方↑↑↑蓝字[协议分析与还原]关注我们
“ 分析金某麻将的长连接数据加密算法。”
近期,不小心碰到了一个棋牌游戏,叫xx麻将,使用长连接进行数据的传输,但三天两头换传输的内容格式,它的编码方式也很有意思(乱七八糟的意思),特分享给大家,这个棋牌游戏没在应用市场上架,但存在自己的传播渠道,大家应该能想象得到它是干啥的,看看就好。里面玩的大概是这样:
01
—
长连接识别
它的长连接采用的是固定IP端口进行交互,从服务器下发,因此需要从服务器取数据来进行识别,当然,一段时间内,它的服务器地址及端口是不变的,否则规模很大,或者成本很高,这不用怀疑。
这个长连接,没有用常见的成熟的方案,而是自己实现了一套TCP长连接方案,粗略地看下,会发现这个游戏的代码质量很差,TCP没管理好,没用的数据过多,浪费了很多资源。
02
—
长连接内容
接下来看下这个长连接里面传输的内容,是下面这样子。
内容看着很有规律,里面有一段BASE64,在BASE64之前,可以认为是数据块头,经过分析,有自己的格式,最开始说它的编码方式很有意思,说的就是这里。
这个TCP长连接里面传输的是数据块,这个游戏是啥数据都在这个TCP连接里面传,但是,开发者能力有限,无法hold住稍微长点的数据的传输,然后就比较蛋疼了,导致游戏非常卡顿,动不动就死就挂,另外数据块还分成多层嵌套,估计是一层层的补丁。
常规情况,这些TCP流内的数据块头里面都有个字段来标示数据块的长度,在这个游戏里,数据块头的前4字节就是这个长度值,理论上,能传输的长度很大的。但是,它却没有充分利用它,根据分析,推测原因是资源消耗以及数据加密和BASE64编码不方便处理导致的。
这个游戏长连接里面传输的内容有多种情况,最常见的是一块数据就是一块加密内容,解开就能看到里面的内容了:
1008:{"ids":[1216,1710,1712,1713,1714,1715,1716,1717,1718,1719,1720,1722,1723,1724,1725,1726,1732,1733,1749,1753,1754,1756,1761,1772,1800,1801,1802,2000,2001,2002,2003,2004,2005,2006]}
还有一个大块数据里嵌套多个加密块,每个BASE64块带自己的块头,再拼一起,组成一个大块,再加上一个外层的块头,类似下面这样:
这种就需要根据外层块头进行处理,然后里面循环提取内层块,再进行块内容的处理,这还算简单的。
接下来还有一个加密块被分到多个数据块里面的情况,这种通常是加密块太大了,然后就被拆分成小些的块,每块相当于前面的第一种情况。
是不是以为这种情况是最后一种情况了,不是的,它还有一种情况,是多个加密块组成一个大块,然后再被分到多个数据块里,我不禁在想,这个开发者是不是俄罗斯套娃的小迷弟。
03
—
长连接数据解密
长连接里面的base64,是一个加密的消息内容,当然需要解密,这里给出简单的解密代码。
def decmsgdata(self,data):
decdata = b''
if len(data) == 0:
return decdata
try:
encdata = base64.b64decode(data)
if len(encdata) == 0:
return decdata
if len(encdata) % 16 != 0:
return data
except:
return data
key, iv = deck()
try:
model = {'ECB': AES.MODE_ECB, 'CBC': AES.MODE_CBC}['CBC']
padding = 'pkcs7'
aes = AES.new(key, model, iv)
decdata = unpad(aes.decrypt(encdata), 16, padding)
return decdata.strip(b'\0')
except:
return data
04
—
结束
有想要交流长连接处理解密经验朋友,可以畅所欲言。
别忘点“在看”、“赞”和“分享”
新的规则,及时收推文要先给公号星标
别忘了星标一下,不然就错过了
长按进行关注,时刻进行交流。