PrimeBot 启元 Q1 & T1 技能整活工作台
SM4 CRYPTO LAYER · 传输层加解密底座

国密 SM4-CBC 装甲运钞车源码精讲

从前端 Web Bundle 逆向还原的混淆密钥重排算法与 SM4-CBC 加解密实现

😜 调皮课代表大白话划重点(30 秒读懂核心)
为什么自己拿 Postman 调 PrimeHub 接口全是乱码?因为人家给请求体穿了国密 SM4-CBC 防弹衣!这个小巧的模块干了一件极客味十足的事:用 7 步逆向切片移位函数 unscramble() 把混淆过的十六进制字符串还原成真正的 16 字节 KEY 和 IV,帮 primehub_publish.py 把所有收发包裹自动加密解密!

🔍 核心机关与修改指南

🧩 7步逆向解混淆 unscramble()

复刻了前端 JS 打包代码里的数组切片移位算法,算出真实的 SM4 密钥与初始化向量。

💻 完整源码与配置内容(共 47 行 · 支持行号定位与一键复制)

📄 共 47 行
1#!/usr/bin/env python3
2"""PrimeHub API client - SM4-CBC encrypted transport, reverse-engineered from web bundle.
3Usage: primehub_client.py <path> '<json-params>'
4"""
5import json, urllib.request, urllib.parse, uuid, time, sys
6from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
7
8IV_S = '38fed878322f002e58db85fdf0417a0f'
9KEY_S = '160a505137ed9d6efbf089ebfec49a93'
10def unscramble(s):
11 e = list(s); n = [[1,3],[3,8],[2,5],[1,9],[11,15],[11,15],[1,3]]
12 for t in reversed(n):
13 L = len(e)-(t[1]-t[0]); seg = e[L:]; del e[L:]; e[t[0]:t[0]] = seg
14 return ''.join(e)
15KEY = bytes.fromhex(unscramble(KEY_S)); IV = bytes.fromhex(unscramble(IV_S))
16BASE = 'https://primehub.primebot.com'
17
18def call(path, params, token=None):
19 params = dict(params); params['timestamp'] = int(time.time()*1000); params['requestId'] = str(uuid.uuid4())
20 t = json.dumps(params, separators=(',',':'))
21 inner = urllib.parse.quote(t, safe='')
22 c = CryptSM4(); c.set_key(KEY, SM4_ENCRYPT)
23 ct = c.crypt_cbc(IV, inner.encode()).hex()
24 body = json.dumps({'data': ct}).encode()
25 h = {'Content-Type':'application/json','request-t':'true','X-Request-Id':'req-'+uuid.uuid4().hex[:8],
26 'Origin':BASE,'Referer':BASE+'/'}
27 if token: h['Authorization'] = 'Bearer '+token
28 req = urllib.request.Request(BASE+path, data=body, headers=h)
29 try:
30 r = urllib.request.urlopen(req, timeout=30)
31 raw = r.read().decode()
32 except urllib.error.HTTPError as ex:
33 raw = ex.read().decode()
34 d = json.loads(raw)
35 if isinstance(d.get('data'), str) and d.get('code') == 1000:
36 try:
37 c2 = CryptSM4(); c2.set_key(KEY, SM4_DECRYPT)
38 pt = c2.crypt_cbc(IV, bytes.fromhex(d['data']))
39 d['data'] = json.loads(urllib.parse.unquote(pt.decode()))
40 except Exception as e:
41 d['_decrypt_error'] = str(e)
42 return d
43
44if __name__ == '__main__':
45 path = sys.argv[1]; params = json.loads(sys.argv[2]) if len(sys.argv)>2 else {}
46 token = sys.argv[3] if len(sys.argv)>3 else None
47 print(json.dumps(call(path, params, token), ensure_ascii=False, indent=1)[:4000])