游戏近期改变了登录方式,于是把之前的研究成果分享一下
研究仅供学习交流,如有侵权请联系删除
抓包
启动启动器,输入账号密码,点击登录,抓包得到一些信息
接口
1 | https://wskacchm.mini1.cn:14100/login/auth_security |
请求数据

加密的返回数据

调试分析
由于游戏更新后,原文件丢失了,这里就不详细演示调试过程了qwq,改用ida静态分析演示。
因为游戏启动需要解密数据构造 commandline 来启动,所以解密的代码应该就在启动器里.
启动ida,等待分析结束,搜索关键字符串 authinfo ,找到对应函数
调试分析的话,可以发现在走完 sub_45A180 后,就解密完成了,那么这个肯定就是解密函数了,第一个参数是加密的数据,第二个是iv

iv分析
分析一下这个函数,发现前面对iv做了一系列的运算,实际上就是取出iv中的数字拼接在了一起, 简化一下的python代码如下
1 | length = int(''.join(c for c in iv_ if c.isdigit())) |

加密算法分析
这里我是半调试半加直觉的,调试后发现他在获取完iv后,将加密数据分成了两部分,然后反过来拼接起来
经过测试后得出,iv是第二部分数据的长度
1 2 3 4 | length = int(''.join(c for c in iv_ if c.isdigit()))res = content[len(content) - length:] + content[:len(content) - length]# base64解码res = base64.b64decode(res) |
继续往下调试,走到 sub_44C2B0 发现传入了两个字符串参数
ida跟进分析了一下,发现很明显的AES的s_box
那么基本肯定这里就是AES的解密了,传入的两个字符串参数一个是key,一个是iv



key 和 iv
1 2 | key: fcafc12e17b93a30a8998fcbc7d5c786iv: 624df8d86de5dc35 |
测试解密
解密的流程清楚了 解析iv还原数据顺序->base64解码->aes解密
用 CyberChef 测试一下,成功解密

auth分析
在尝试自己发post的时候发现还有个auth参数不知道怎么得到,继续分析
调试得出auth就是 source=mini_micro&target=auth&time=时间戳 加盐后md5加密的值,盐值调试一下或者明文都能看到
1 2 3 4 5 6 | SALT = "2ddb7619717147439c83ab022e9d4d38"def get_auth(): string = "source=mini_micro&target=auth&time=" + str(TIMESTAMP) + SALT md5 = hashlib.md5() md5.update(string.encode()) return md5.hexdigest() |
全部代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | import requestsimport base64import uuidimport hashlibfrom datetime import datetimefrom Crypto.Cipher import AESrequests.packages.urllib3.disable_warnings()# ---------- config ----------UIN = "<Uin>"PASSWORD = "<Password>"APIID = 110CLTVERSION = 73472AES_KEY = "fcafc12e17b93a30a8998fcbc7d5c786"AES_IV = "624df8d86de5dc35"SALT = "2ddb7619717147439c83ab022e9d4d38"LOGIN_API = "https://wskacchm.mini1.cn:14100/login/auth_security"TIMESTAMP = int(datetime.now().timestamp())# -----------------------------def get_auth(): string = "source=mini_micro&target=auth&time=" + str(TIMESTAMP) + SALT md5 = hashlib.md5() md5.update(string.encode()) return md5.hexdigest()def get_device_id(): # 随便伪造的设备ID,不是游戏本身的算法 return "WIN" + uuid.uuid1().hexdef decrypt_data(content, iv_): # 根据iv取到第二部分的长度, 还原顺序 length = int(''.join(c for c in iv_ if c.isdigit())) res = content[len(content) - length:] + content[:len(content) - length] # base64解码 res = base64.b64decode(res) # AES解密 aes = AES.new(AES_KEY.encode(), AES.MODE_CBC, AES_IV.encode()) dec = aes.decrypt(res) return dec.decode()data = { "auth": get_auth(), "passwd_auth": { "DeviceID": get_device_id(), "apiid": APIID, "cltversion": CLTVERSION, "passwd": PASSWORD, "uin": UIN }, "source": "mini_micro", "target": "auth", "time": TIMESTAMP}if __name__ == '__main__': response = dict(requests.post(LOGIN_API, json=data, verify=False).json()) iv = response["iv"] print(decrypt_data(response["authinfo"], iv)) print(decrypt_data(response["baseinfo"], iv)) |
结尾
小白写的有点乱,有问题还请提出qwq
还有,看雪的Markdown编辑器字数多了变得好卡hh