关于dy的a_bogus逆向,jsvmp
进行抖音抓包,对应的位置在
url = "https://www.douyin.com/aweme/v1/web/aweme/post/"
可以看一下调用栈,不难发现主要的逻辑在bdms_1.0.1.19_fix.js
直接跳过去可以看到d就是指令操作
先一点一点的去看
这个位置调用了atob,代表了对下面的那个字符进行了base64的解密,随后取第 4~7 字节求和得到单字节 key
再用自定义 map 函数 _ 对余下字节逐个异或,最后把结果送进自带的 DEFLATE 解压器,从而得到可执行的数据块,这里可以很好的看出来这一块是一个压缩文件的格式,对应base64的UEsC
import base64, zlib, re, hashlib, os, sys
from pathlib import Path
BASE64_DATA = r"""
""".strip()
# ==============================================
def sanitize_b64(s: str) -> str:
return re.sub(r'[^A-Za-z0-9+/=]', '', s)
def xor_transform(decoded: bytes) -> tuple[bytes, int, int]:
key_sum = sum(decoded[4:8]) & 0xFFFFFFFF
km = key_sum % 256
step = km % 10
tail = decoded[8:]
out = bytearray(len(tail))
for i, b in enumerate(tail):
out[i] = (b ^ ((km + step * i) % 256)) & 0xFF
return bytes(out), key_sum, km
def inflate_raw(data: bytes) -> bytes:
return zlib.decompress(data, -15)
def main():
b64 = sanitize_b64(BASE64_DATA)
raw = base64.b64decode(b64)
mapped = xor_transform(raw)
payload = inflate_raw(mapped)
out_path = Path(os.getcwd()) / "payload.bin"
out_path.write_bytes(payload)
if __name__ == "__main__":
main()
可以和dump的东西进行对应上
function W(t) {
for (var r = 0, e = 0; ; ) {
var n = t.d[t.i++];
if (r |= (127 & n) << e,
e += 7,
!(128 & n))
return e < 32 && 64 & n ? r | -1 << e : r
}
}
最开始的e9 07
0xe9 = 1110 1001
低 7 位 0x69 = 105
0x07 = 0000 0111
低 7 位 0x07 = 7
累加:val += 7 << 7 = 7 * 128 = 896
总和:105 + 896 = 1001
所以字符串池的条数为1001条
字符串的位置走过后,这个位置是函数表对应的条数
0x1C | 0x80 = 0x9C
计算后这个位置应该是796条,下图调试的位置吻合
打印出来:
字符串表
a_bogus对应的是表的Z[220]
调试位置对应的url的方法
调试到这里可以看到对应的字节码的东西为
{"f": [34, 54, 0, 3, 34, 30, 214, 41, 212, 34, 30, 214, 30, 70, 54, 0, 4, 74, 0, 4, 30, 218, 54, 0, 5, 74, 0, 5, 30, 72, 54, 0, 6, 33, 74, 2, 33, 74, 0, 6, 0, 1, 54, 0, 7, 74, 0, 7, 41, 5, 74, 0, 6, 53, 11, 60, 161, 74, 0, 6, 60, 216, 30, 178, 59, 2, 54, 0, 8, 74, 0, 8, 30, 162, 18, 30, 219, 73, 165, 0, 1, 29, 17, 5, 74, 2, 3, 30, 150, 41, 18, 74, 0, 8, 30, 162, 18, 30, 163, 73, 165, 74, 2, 3, 30, 150, 0, 2, 26, 74, 0, 8, 30, 162, 18, 30, 219, 73, 220, 0, 1, 29, 41, 45, 33, 74, 3, 14, 0, 0, 26, 33, 74, 2, 37, 74, 0, 8, 30, 162, 18, 30, 9, 0, 0, 74, 0, 2, 0, 2, 54, 0, 9, 74, 0, 8, 30, 162, 18, 30, 163, 73, 220, 74, 0, 9, 0, 2, 26, 74, 0, 7, 29, 41, 10, 74, 0, 5, 74, 0, 8, 30, 178, 20, 72, 34, 30, 214, 18, 30, 51, 63, 108, 0, 1, 26, 33, 74, 2, 36, 74, 0, 8, 30, 215, 0, 1, 41, 7, 33, 74, 2, 5, 0, 0, 26, 34, 73, 214, 25, 26, 74, 1, 4, 18, 30, 126, 34, 74, 0, 2, 39, 1, 0, 2, 26, 33, 76], "i": 1, "u": true, "s": []},
这个序列是给"a_bogus"赋值的序列
观察这个a_bogus的赋值的情况,是在var m = n.apply(d, e)中给值放到了v[p++]中,观察e的值的来源,在观察整个虚拟机,可以看到所有的v[p]都参与了基本指令运算,关于+-*/%&>><<,而且观察所有的基本运算所虚拟机表示的中的位置只有一个,那么可以思考就是对于每一个opcode,这个虚拟机只对应了简单的指令运算,然后进行大量的拼接得到的算法,所以只需要对这些基本运算进行插庄打log就可以看到整个流程的生成了
打log的位置:所有基本运算,以及最后的放到v[++p]位置的地方
'm:',m,'n:',n,'d:',d,'e:',e
'v[p]:',v[p] > w ,'=','v[p]:',v[p],'>','w:',w
'v[p]:',v[p] % E ,'=','v[p]:',v[p],'%','E:',E
'v[p]:',v[p] & E ,'=','v[p]:',v[p],'&','w:',w
'v[p]:',v[p] >>> w ,'=','v[p]:',v[p],'>>>','w:',w
'v[p]:',v[p] - E ,'=','v[p]:',v[p],'-','E:',E
'v[p]:',v[p] >> w ,'=','v[p]:',v[p],'>>','w:',w
'v[p]:',v[p] / E ,'=','v[p]:',v[p],'/','E:',E
'v[p]:',v[p] * E ,'=','v[p]:',v[p],'*','E:',E
'v[p]:',v[p] | w ,'=','v[p]:',v[p],'|','w:',w
'v[p]:',v[p] << w ,'=','v[p]:',v[p],'<<','w:',w
'v[p]:',v[p] + E ,'=','v[p]:',v[p],'+','E:',E
'v[p]:',v[p] ^ w ,'=','v[p]:',v[p],'^','w:',w
直接开始跑,我们从最后生成往上回溯分析
可以看到a_bogus,这里满足base64变表,直接写个脚本测试一下
import random
BASE_TABLE = "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"
def b64_swap_decode(s: str, alphabet: str = BASE_TABLE) -> bytes:
table = {ch: i for i, ch in enumerate(alphabet)}
s = s.strip()
if len(s) % 4:
s += "=" * ((4 - len(s) % 4) % 4)
out = bytearray()
for i in range(0, len(s), 4):
block = s[i:i+4]
pad = block.count("=")
vals = []
for ch in block:
if ch == "=":
vals.append(0)
else:
if ch not in table:
raise ValueError(f"字母表中不存在字符: {repr(ch)}")
vals.append(table[ch])
v = (vals[0] << 18) | (vals[1] << 12) | (vals[2] << 6) | vals[3]
out.append((v >> 16) & 0xFF)
if pad < 2:
out.append((v >> 8) & 0xFF)
if pad < 1:
out.append(v & 0xFF)
return bytes(out)
def b64_swap_encode(b: bytes, alphabet: str = BASE_TABLE) -> str:
res = []
for i in range(0, len(b), 3):
chunk = b[i:i+3]
pad = 3 - len(chunk)
if pad:
chunk = chunk + b"\x00" * pad
val = (chunk[0] << 16) | (chunk[1] << 8) | chunk[2]
res.append(alphabet[(val >> 18) & 0x3F])
res.append(alphabet[(val >> 12) & 0x3F])
res.append("=" if pad == 2 else alphabet[(val >> 6) & 0x3F])
res.append("=" if pad >= 1 else alphabet[val & 0x3F])
return "".join(res)
if __name__ == "__main__":
encoded = "Q6UVhHtyDdWRKVFGuCcOeJKU2Uj/rPuynlTdbzPPtBtTOq0aBSP2MnbScouJskbjL8BziKVHqEtlbDnczGU0Z99kzmpDSm4fosVCV68oZqwgTeGmLrD/ehhzuwBC0QJwl5C6NAU51sBn2jVAIq5uWd3GH5To5bEdSrZ6D/LytEAgfCSkk93kOCDdEgaFUvcG"
raw = b64_swap_decode(encoded, BASE_TABLE)
print("Decoded bytes:", raw)
print("Decoded as UTF-8:", raw.decode("utf-8", errors="replace"))
print("Decimal values:", " ".join(str(byte) for byte in raw))
可以看到和刚过来的数组是一样的
在这里可以看到,这里的字符是拼接来的,前4字节和后面进行了拼接,先看一下后面的字节的来源
追上去后可以看到两个部分的线索,直接直接就可以根据rc4的特征来看到,这部分上面是表的生成,下面是标准的rc4的算法(除了表生成位置)
表生成位置:
直接根据他给的写就行,写一下算法,key可以很好的看到是211
import random
BASE_TABLE = "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"
def rc4(data: bytes, key: bytes) -> bytes:
seed = (sum(key) & 0xff) if key else 0
raw = list(range(255, -1, -1))
z = 0
n = len(raw)
for i in range(n):
a = (z + seed) % 256
raw[i], raw[a] = raw[a], raw[i]
if i + 1 < n:
z = raw[i + 1] * a + a
i = 0
j = 0
out = bytearray()
for b in data:
i = (i + 1) & 0xff
j = (j + raw[i]) & 0xff
raw[i], raw[j] = raw[j], raw[i]
K = raw[(raw[i] + raw[j]) & 0xff]
out.append(b ^ K)
return bytes(out)
def b64_swap_decode(s: str, alphabet: str = BASE_TABLE) -> bytes:
table = {ch: i for i, ch in enumerate(alphabet)}
s = s.strip()
if len(s) % 4:
s += "=" * ((4 - len(s) % 4) % 4)
out = bytearray()
for i in range(0, len(s), 4):
block = s[i:i+4]
pad = block.count("=")
vals = []
for ch in block:
if ch == "=":
vals.append(0)
else:
if ch not in table:
raise ValueError(f"字母表中不存在字符: {repr(ch)}")
vals.append(table[ch])
v = (vals[0] << 18) | (vals[1] << 12) | (vals[2] << 6) | vals[3]
out.append((v >> 16) & 0xFF)
if pad < 2:
out.append((v >> 8) & 0xFF)
if pad < 1:
out.append(v & 0xFF)
return bytes(out)
def b64_swap_encode(b: bytes, alphabet: str = BASE_TABLE) -> str:
res = []
for i in range(0, len(b), 3):
chunk = b[i:i+3]
pad = 3 - len(chunk)
if pad:
chunk = chunk + b"\x00" * pad
val = (chunk[0] << 16) | (chunk[1] << 8) | chunk[2]
res.append(alphabet[(val >> 18) & 0x3F])
res.append(alphabet[(val >> 12) & 0x3F])
res.append("=" if pad == 2 else alphabet[(val >> 6) & 0x3F])
res.append("=" if pad >= 1 else alphabet[val & 0x3F])
return "".join(res)
if __name__ == "__main__":
encoded = "Q6UVhHtyDdWRKVFGuCcOeJKU2Uj/rPuynlTdbzPPtBtTOq0aBSP2MnbScouJskbjL8BziKVHqEtlbDnczGU0Z99kzmpDSm4fosVCV68oZqwgTeGmLrD/ehhzuwBC0QJwl5C6NAU51sBn2jVAIq5uWd3GH5To5bEdSrZ6D/LytEAgfCSkk93kOCDdEgaFUvcG"
raw = b64_swap_decode(encoded, BASE_TABLE)
print("Decoded bytes:", raw)
print("Decoded as UTF-8:", raw.decode("utf-8", errors="replace"))
print("Decimal values:", " ".join(str(byte) for byte in raw))
rc4_decoded = rc4(raw[4:], bytes([211]))
print("RC4 Decoded bytes:", rc4_decoded)
print("RC4 Decoded as UTF-8:", rc4_decoded.decode("utf-8", errors="replace"))
print("RC4 Decimal values:", " ".join(str(byte) for byte in rc4_decoded))
RC4 Decimal values: 3 84 32 64 33 16 162 84 145 78 212 47 217 0 218 161 17 64 33 0 221 1 3 144 201 90 33 149 230 218 40 130 200 239 38 227 60 31 8 2 65 66 51 156 107 4 20 27 128 0 206 12 194 64 44 16 155 97 185 240 16 67 40 0 144 43 208 32 107 108 40 17 148 2 29 32 165 113 26 49 253 55 27 54 178 126 17 112 52 113 22 49 236 120 57 56 34 62 49 113 36 49 54 49 124 122 25 56 35 62 53 113 53 113 30 49 108 121 48 56 179 124 105 92 224 35 105 75 255 54 73 100 125 50 52 38 164 110 183 29
rc4这个位置是没有错的,继续往下分析
前面四个字节的来源,前四个字节是41 71 82 23看一下来源
def gen_s() -> str:
# a = (int(random.random() * 65535)) & 0xFF
# b = int(random.random() * 40)
a = (int(0.5446416885859573 * 65535)) & 0xFF
b = int(0.5832301287563609 * 40)
s = []
s.append(chr((a & 0xAA) | 0x01))
s.append(chr((a & 0x55) | 0x02))
s.append(chr((b & 0xAA) | 0x50))
s.append(chr((b & 0x55) | 0x02))
return ''.join(s)
#Generated 4 bytes: b')GR\x17'
#Generated Decimal values: 41 71 82 23
再往上追可以看到,这个刚才rc4解密的数组是通过8为数组+132位数组来的
第一组的地方3, 84, 32, 64
第二组的地方33, 16, 162, 84
def gen_r_head2() -> str:
# a= (int(random.random() * 240)) & 0xFF
# b = (int(random.random() * 255)) & 0xFF & 77
a = (int(0.20071909122733345 * 240)) & 0xFF
b = (int(0.83287578221808 * 255)) & 0xFF & 77
w = [1, 4, 5, 7]
for i in range(4):
b = b | (1 << w[i]);
s = []
s.append(chr((a & 0xAA) | 0x1))
s.append(chr((a & 0x55) | 0x0))
s.append(chr((b & 0xAA) | 0x0))
s.append(chr((b & 0x55) | 0x0))
return ''.join(s)
对应8字节后面的四位33, 16, 162, 84
def gen_r_head1() -> str:
# z = int(random.random() * 65535)
# a = z & 0xFF
# b = (z >> 8) & 0xFF
a = (int(0.37632919615333793 * 65535)) & 0xFF
b = (int(0.37632919615333793 * 65535) >> 8) & 0xFF
s = []
s.append(chr((a & 0xAA) | 0x1))
s.append(chr((a & 0x55) | 0x0))
s.append(chr((b & 0xAA) | 0x0))
s.append(chr((b & 0x55) | 0x0))
return ''.join(s)
Length of gen: 8
Generated r_head Decimal values: 3 84 32 64 33 16 162 84
正好对应上了
网上回溯看一下这个是怎么生成的,这个时候可以看到这里面永远都会一组重复的数字145, 110, 66, 189, 44, 211
根据上面可以写出加密逻辑
import random
key = [145, 110, 66, 189, 44, 211]
data = [1,14,252,201,0,242,0,0,1,220,1,3,217,24,5,230,154,0,201,239,34,44,31,0,208,0,31,123,6,24,0,0,206,82,0,0,154,97,177,0,1,0,0,41,240,123,44,0,4,0,49,53,49,50,124,55,55,50,124,49,53,49,50,124,56,57,51,124,49,53,49,50,124,56,57,51,124,49,53,49,50,124,57,56,50,124,77,97,99,73,110,116,101,108,50,52,53,44,159]
result = []
rad = [0.21538688661648553,0.9212125883092179,0.11329993696990215,0.4012867884874777,0.7397694321593413,0.2345646507296566,0.48677241706302965,0.02660945354489941,0.3556811964939194,0.7736328373701941,0.6529429229670689,0.4924646761384377,0.7613914142703988,0.3780540061140839,0.9141587354910575,0.10551554793573337,0.15838251707991813,0.7137565040911108,0.4114927013372691,0.21053933074769915,0.5965956170259822,0.23215038617850303,0.2901816263862327,0.29295876428660983,0.6021625523305605,0.039574963495331406,0.6054109386072396,0.09645229970364944,0.5053147091841774,0.938315440828625,0.41117788486726015,0.05572314150793589,0.9985371346724156]
for i in range(0, len(data), 3):
#v = (int(random.random() * 1000)) & 0xFF
v = (int(rad[i // 3] * 1000)) & 0xFF
result.append(chr((v & key[0]) | (data[i] & key[1])))
result.append(chr((v & key[2]) | (data[i + 1] & key[3])))
result.append(chr((v & key[4]) | (data[i + 2] & key[5])))
result.append(chr((data[i] & key[0]) | (data[i + 1] & key[2]) | (data[i + 2] & key[4])))
data_result = ''.join(result).encode("latin-1")
print(data_result)
print("values:", " ".join(str(byte) for byte in data_result))
同理解密逻辑为
def decode_data(data) -> str:
key = [145, 110, 66, 189, 44, 211]
out = []
for i in range(0, len(data), 4):
r0, r1, r2, r3 = data[i:i+4]
a = (r0 & key[1]) | (r3 & key[0])
b = (r1 & key[3]) | (r3 & key[2])
c = (r2 & key[5]) | (r3 & key[4])
out.extend([a, b, c])
return bytes(out)
对应了:
[1,14,252,201,0,242,0,0,1,220,1,3,217,24,5,230,154,0,201,239,34,44,31,0,208,0,31,123,6,24,0,0,206,82,0,0,154,97,177,0,1,0,0,41,240,123,44,0,4,0,49,53,49,50,124,55,55,50,124,49,53,49,50,124,56,57,51,124,49,53,49,50,124,56,57,51,124,49,53,49,50,124,57,56,50,124,77,97,99,73,110,116,101,108,50,52,53,44,159
]
继续往上根
他把刚才的这些数据进行了分组
[1,14,252,201,0,242,0,0,1,220,1,3,217,24,5,230,154,0,201,239,34,44,31,0,208,0,31,123,6,24,0,0,206,82,0,0,154,97,177,0,1,0,0,41,240,123,44,0,4,0]
[49,53,49,50,124,55,55,50,124,49,53,49,50,124,56,57,51,124,49,53,49,50,124,56,57,51,124,49,53,49,50,124,57,56,50,124,77,97,99,73,110,116,101,108]
[50,52,53,44]
[159]
中间的第二组,从刚才的解密结果可以发现,这个数组是一些可能带有的参数
1512|772|1512|893|1512|893|1512|982|MacIntel%
那么剩下关心的就是剩下的这几组的参数了
四位的情况向上回溯,和时间戳有关系
可以看到最后的那个单个的数字159是经过很多次的xor得到的
如果你的记忆里很好的话,看到这里的时候你就一定会知道这些东西你见过,就是之前那个随机的8位数
Generated r_head Decimal values: 3 84 32 64 33 16 162 84
这个时候就会疑问这个41后面的都是哪里来的,重新trace看一下对应的位置
Xor 41索引位置24
依次把x都拿出来,就可以得到索引
[24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 55, 56, 57, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 79, 80, 84, 85]
写代码实现就是
w = [24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 55, 56, 57, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 79, 80, 84, 85]
w_8 = [169, 21, 136, 81, 137, 81, 162, 21]
table_gobal = [
[
{
"5": {
"aid": 6383,
"pageId": 6241,
"boe": 0,
"ddrt": 8.5,
"paths": {
"include": [
{},
{},
{},
{},
{},
{},
{},
{}
],
"exclude": [
{}
]
},
"track": {
"mode": 0,
"delay": 300,
"paths": []
},
"slU": "",
"dump": 1,
"rpU": "",
"ic": 8.5
}
},
{},
"dhzx",
1763021788706,
5,
{
"name": "Chrome"
},
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
{
"0": 1,
"1": 0,
"2": 8,
"3": "device_platform=webapp&aid=6383&channel=channel_pc_web&sec_user_id=MS4wLjABAAAAofq0Vvn8ISgdgZ-eX4lgGoJb1BQDtjB3K7I8XzjTfW3hMgZ9gaaJnYy-Er1k5QRi&max_cursor=0&locate_query=false&show_live_replay_strategy=1&need_time_list=1&time_list_query=0&whale_cut_token=&cut_version=1&count=18&publish_video_strategy_type=2&from_user_page=1&update_version_code=170400&pc_client_type=1&pc_libra_divert=Mac&support_h265=1&support_dash=1&cpu_core_num=10&version_code=290100&version_name=29.1.0&cookie_enabled=true&screen_width=1512&screen_height=982&browser_language=zh-CN&browser_platform=MacIntel&browser_name=Chrome&browser_version=142.0.0.0&browser_online=true&engine_name=Blink&engine_version=142.0.0.0&os_name=Mac+OS&os_version=10.15.7&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7537255736499029513&uifid=ecb38e5e86f1f8799c3256ca6c3446710d152cd7b76a2f92ca888d379e861b9ef6c3c057199fbabeb251493a65cd070d26b3aeca82ccc95af03dc3a8930e7db657234d4ca4acb8174f8b9e3cab43ff6260ae432fd24dfe6de26ecc544bf0426c0fb819444e48099c31f99143dab6d5c48975b8b37a257b159ef2fe6dacc5252904813ff4b25bebd8458d1565ef36ce45b9144f443029919505f73dca564bcd4a&msToken=_ldHApyvIwdTTeKAtEdJ420xs1ltIcgsNMzR0bX8PJ5sv86p7ORbTipL0ylgxU3ZmrrxoR-Rv6qwyig0-yZPE26FFFIFwRgTGONu1NN5FlswqC5B2WRWvp3ESGTQNFgQOgIor-bnh8BYHfUnAyQGwl_VuKgrY2s_WeRVHHN4nLRd1nxcNjjF-A%3D%3D",
"4": "",
"5": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
"6": 6241,
"7": 6383,
"8": "1.0.1.19-fix.01"
},
1,
0,
8,
"device_platform=webapp&aid=6383&channel=channel_pc_web&sec_user_id=MS4wLjABAAAAofq0Vvn8ISgdgZ-eX4lgGoJb1BQDtjB3K7I8XzjTfW3hMgZ9gaaJnYy-Er1k5QRi&max_cursor=0&locate_query=false&show_live_replay_strategy=1&need_time_list=1&time_list_query=0&whale_cut_token=&cut_version=1&count=18&publish_video_strategy_type=2&from_user_page=1&update_version_code=170400&pc_client_type=1&pc_libra_divert=Mac&support_h265=1&support_dash=1&cpu_core_num=10&version_code=290100&version_name=29.1.0&cookie_enabled=true&screen_width=1512&screen_height=982&browser_language=zh-CN&browser_platform=MacIntel&browser_name=Chrome&browser_version=142.0.0.0&browser_online=true&engine_name=Blink&engine_version=142.0.0.0&os_name=Mac+OS&os_version=10.15.7&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7537255736499029513&uifid=ecb38e5e86f1f8799c3256ca6c3446710d152cd7b76a2f92ca888d379e861b9ef6c3c057199fbabeb251493a65cd070d26b3aeca82ccc95af03dc3a8930e7db657234d4ca4acb8174f8b9e3cab43ff6260ae432fd24dfe6de26ecc544bf0426c0fb819444e48099c31f99143dab6d5c48975b8b37a257b159ef2fe6dacc5252904813ff4b25bebd8458d1565ef36ce45b9144f443029919505f73dca564bcd4a&msToken=_ldHApyvIwdTTeKAtEdJ420xs1ltIcgsNMzR0bX8PJ5sv86p7ORbTipL0ylgxU3ZmrrxoR-Rv6qwyig0-yZPE26FFFIFwRgTGONu1NN5FlswqC5B2WRWvp3ESGTQNFgQOgIor-bnh8BYHfUnAyQGwl_VuKgrY2s_WeRVHHN4nLRd1nxcNjjF-A%3D%3D",
"",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
6241,
6383,
"1.0.1.19-fix.01",
{
"ink": 1763021788706
},
3,
{
"value": "0X21",
"writable": 0,
"enumerable": 1,
"configurable": 1
},
1763021788708,
{
"reg": [
1937774191,
1226093241,
388252375,
3666478592,
2842636476,
372324522,
3817729613,
2969243214
],
"chunk": [],
"size": 0
},
1,
14,
[
75,
88,
25,
204,
46,
136,
235,
122,
51,
23,
207,
160,
3,
48,
143,
135,
1,
25,
54,
194,
0,
108,
224,
238,
26,
252,
36,
188,
147,
131,
240,
57
],
[
64,
253,
156,
240,
44,
96,
159,
150,
27,
122,
82,
52,
197,
120,
234,
119,
245,
89,
71,
177,
99,
98,
28,
142,
5,
99,
123,
199,
176,
9,
152,
240
],
"eWgvhqF7obsvc6EpmziycV7XL8a0cgI1T8jgTKeNbjPeaKF1gvtiAPTEZavZAo08AIP6CdZALC6EbNqevfpUebcct0j7VPPDkRfsBmBXxwdsjBBMnjZ8biljt0Eg1OEzGvPt3LjptJUTYvu+JLsMBZ6mXcXV",
[
34,
2,
135,
211,
192,
208,
65,
120,
79,
137,
215,
252,
68,
7,
137,
60,
10,
133,
247,
147,
234,
206,
193,
40,
81,
115,
135,
232,
128,
141,
33,
199
],
1763021788706,
[
3,
82
],
41,
[
1,
0,
1,
0,
1
],
34,
6,
5,
36,
150,
73,
124,
154,
1,
1,
0,
[
0,
0,
0,
0,
1
],
1,
0,
0,
0,
0,
0,
14,
0,
0,
0,
23,
54,
3,
204,
82,
177,
4,
44,
252,
206,
5,
208,
34,
150,
73,
124,
154,
1,
3,
97,
24,
0,
0,
239,
24,
0,
0,
{
"innerWidth": 1512,
"innerHeight": 772,
"outerWidth": 1512,
"outerHeight": 893,
"availWidth": 1512,
"availHeight": 893,
"sizeWidth": 1512,
"sizeHeight": 982,
"platform": "MacIntel"
},
"1512|772|1512|893|1512|893|1512|982|MacIntel",
[
49,
53,
49,
50,
124,
55,
55,
50,
124,
49,
53,
49,
50,
124,
56,
57,
51,
124,
49,
53,
49,
50,
124,
56,
57,
51,
124,
49,
53,
49,
50,
124,
57,
56,
50,
124,
77,
97,
99,
73,
110,
116,
101,
108
],
44,
44,
0,
"39,",
[
51,
57,
44
],
3,
3,
0,
[
169,
21,
136,
81,
137,
81,
162,
21
],
104,
[
1,
14,
252,
150,
0,
36,
0,
0,
1,
54,
1,
3,
204,
24,
5,
23,
154,
0,
150,
239,
34,
44,
73,
0,
208,
0,
73,
124,
6,
24,
0,
0,
206,
82,
0,
0,
154,
97,
177,
0,
1,
0,
0,
41,
34,
124,
44,
0,
3,
0,
49,
53,
49,
50,
124,
55,
55,
50,
124,
49,
53,
49,
50,
124,
56,
57,
51,
124,
49,
53,
49,
50,
124,
56,
57,
51,
124,
49,
53,
49,
50,
124,
57,
56,
50,
124,
77,
97,
99,
73,
110,
116,
101,
108,
51,
57,
44,
104
],
"\u000b\u0003r\u0007",
[
128,
12,
216,
47,
150,
2,
40,
180,
0,
0,
9,
0,
55,
3,
7,
16,
220,
90,
1,
132,
150,
216,
40,
19,
134,
173,
42,
242,
44,
11,
40,
64,
208,
0,
97,
152,
236,
70,
28,
26,
128,
0,
194,
12,
67,
0,
36,
16,
155,
33,
145,
240,
1,
3,
40,
0,
129,
107,
38,
32,
108,
44,
32,
16,
2,
66,
21,
33,
164,
51,
62,
49,
237,
55,
63,
54,
50,
126,
29,
112,
165,
115,
50,
49,
252,
120,
49,
56,
51,
124,
29,
113,
53,
51,
26,
49,
124,
122,
29,
56,
178,
60,
21,
113,
37,
115,
50,
49,
236,
121,
20,
56,
35,
62,
65,
92,
113,
99,
69,
75,
239,
54,
97,
100,
253,
115,
25,
42,
44,
104
],
"Õ5¨6°ø+¸¢¬¦ÿTëÉ\u001f4#øFbÏëÔ®\u0019¨sêaÊ.>(Ê) fL4\u0017åä·\u000fÞ \u0004º·×e\u001f|Á´Ñ°pPÔ¶HÕf\u0016xEåÚH0*üÑm¾Ro6em¯ö\u0018pã\u0019(Zv¨pµûýªvi¤\u0002s1ð\u0000yvÞ\u0007\u0015\u0003Ã\u0001\u0017dé«`CBgs",
"\u000b\u0003r\u0007Õ5¨6°ø+¸¢¬¦ÿTëÉ\u001f4#øFbÏëÔ®\u0019¨sêaÊ.>(Ê) fL4\u0017åä·\u000fÞ \u0004º·×e\u001f|Á´Ñ°pPÔ¶HÕf\u0016xEåÚH0*üÑm¾Ro6em¯ö\u0018pã\u0019(Zv¨pµûýªvi¤\u0002s1ð\u0000yvÞ\u0007\u0015\u0003Ã\u0001\u0017dé«`CBgs",
"dj0nkt67Op5jCdKbYOnoe7VlcSLlNT8ymei2RueP7Qb4OZMORRNQBNbYnxoE4LjyhbpwiCVHLEeAYDVcztUwZHrkzmpvuZkfqtV9V0XohqihGUTmErDOe0hzFwsF0Yiw-5CWNlRRWsBN2VxAIq5YWB1ae5T955fdWrZjDZw9HEWXDS8kh93TO9kpP6sqWj=="
]
key = []
key = w_8
for i in range(len(w)):
key.append(table_gobal[w[i]])
s = key[0]
for i in range(1, len(key)):
s = s ^ key[i]
print("s:", s)
可以对应上
同理上面如果继续看的还会看到一个表
[34, 44, 56, 61, 73, 29, 70, 45, 35, 49, 38, 66, 51, 68, 28, 48, 64, 47, 30, 71, 26, 55, 31, 69, 59, 40, 62, 63, 27, 72, 41, 74, 57, 52, 42, 39, 33, 67, 53, 43, 65, 46, 36, 24, 60, 32, 79, 80, 84, 85]
这个就是50位生成的地方,可以看到可以很完美的对应上
继续向上看的话,可以看一个新的值
这个位置对应了刚才分析到拿出来参数的这个位置
可以很好的看出来这是一个sm3加密算法
这个位置和js的某一个地方的源码一样,key = sum
那么参数应该就是那个加密后的base64字符串
def sm3_hex(s: str) -> str:
def rol(x, n): return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF
def P0(x): return x ^ rol(x, 9) ^ rol(x, 17)
def P1(x): return x ^ rol(x, 15) ^ rol(x, 23)
V = [
0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600,
0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E,
]
m = bytearray(s.encode("utf-8"))
bitlen = (len(m) * 8) & ((1 << 64) - 1)
m.append(0x80)
while (len(m) + 8) % 64 != 0:
m.append(0x00)
m += bitlen.to_bytes(8, "big")
for off in range(0, len(m), 64):
B = m[off:off+64]
W = [int.from_bytes(B[i*4:i*4+4], "big") for i in range(16)] + [0]*52
for i in range(16, 68):
W[i] = (P1(W[i-16] ^ W[i-9] ^ rol(W[i-3], 15)) ^ rol(W[i-13], 7) ^ W[i-6]) & 0xFFFFFFFF
W1 = [(W[i] ^ W[i+4]) & 0xFFFFFFFF for i in range(64)]
A,Bb,C,D,E,F,G,H = V
for j in range(64):
T = 0x79CC4519 if j <= 15 else 0x7A879D8A
SS1 = rol((rol(A,12) + E + rol(T, j & 31)) & 0xFFFFFFFF, 7)
SS2 = SS1 ^ rol(A,12)
FF = (A ^ Bb ^ C) if j <= 15 else ((A & Bb) | (A & C) | (Bb & C))
GG = (E ^ F ^ G) if j <= 15 else ((E & F) | ((~E) & G))
TT1 = (FF + D + SS2 + W1[j]) & 0xFFFFFFFF
TT2 = (GG + H + SS1 + W[j]) & 0xFFFFFFFF
D, C, Bb, A = C, rol(Bb, 9), A, TT1
H, G, F, E = G, rol(F, 19), E, P0(TT2)
V = [(V[0]^A)&0xFFFFFFFF, (V[1]^Bb)&0xFFFFFFFF, (V[2]^C)&0xFFFFFFFF, (V[3]^D)&0xFFFFFFFF,
(V[4]^E)&0xFFFFFFFF, (V[5]^F)&0xFFFFFFFF, (V[6]^G)&0xFFFFFFFF, (V[7]^H)&0xFFFFFFFF]
return "".join(f"{x:08x}" for x in V)
if __name__ == "__main__":
s = "eWgvhqF7obsvc6EpmziycV7XL8a0cgI1T8jgTKeNbjPeaKF1gvtiAPTEZavZAo08AIP6CdZALC6EbNqevfpUebcct0j7VPPDkRfsBmBXxwdsjBBMnjZ8biljt0Eg1OEzGvPt3LjptJUTYvu+JLsMBZ6mXcXV"
dec_s = sm3_hex(s)
print("SM3 Hash:", dec_s)
print("values:", " ".join(str(int(dec_s[i:i+2], 16)) for i in range(0, len(dec_s), 2)))
34 2 135 211 192 208 65 120 79 137 215 252 68 7 137 60 10 133 247 147 234 206 193 40 81 115 135 232 128 141 33 199
和加密位置吻合
这上面生成的还是之前那个base64变表,只是table换成了:ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe
再往上看就是rc4的变种
不过很奇怪,这个console的问题复制的变化后的表,不过可以通过输入和输出反推s盒
def rc4_reverse_initial_s(plaintext: bytes, ciphertext: list[int], s_final: list[int]) -> list[int]:
assert len(plaintext) == len(ciphertext)
K = [p ^ c for p, c in zip(plaintext, ciphertext)]
N = len(K)
S = s_final.copy()
for r in range(N, 0, -1):
i = r & 0xFF
kbyte = K[r-1]
q = S.index(kbyte)
val = (q - S[i]) & 0xFF
j = S.index(val)
S[i], S[j] = S[j], S[i]
return S
p = b"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36"
c = [140,165,135,67,153,198,40,136,15,88,221,45,145,102,31,34,14,215,234,84,3,223,159,233,
21,43,30,231,92,190,76,138,7,196,171,154,89,46,118,89,242,253,199,34,54,46,101,113,
255,123,71,91,175,154,109,84,114,32,41,141,138,157,195,176,120,7,236,228,14,186,87,
175,153,105,244,128,158,187,60,242,102,168,43,233,122,180,166,124,195,121,110,230,
176,224,84,14,205,14,120,149,190,185,143,127,188,19,174,63,202,187,28]
s_final = [110,11,105,14,79,174,199,147,251,20,88,215,152,179,85,128,74,18,80,163,155,195,197,176,246,145,208,172,144,114,48,148,16,90,180,118,154,96,245,139,34,84,162,229,39,193,243,108,240,42,0,9,221,87,106,70,81,29,31,189,102,164,55,219,157,64,30,38,109,196,142,183,236,217,228,115,224,182,177,123,86,125,213,140,233,175,36,51,111,22,10,250,78,222,7,127,46,137,171,104,97,158,43,225,204,3,93,166,146,67,178,63,198,89,57,23,254,242,239,207,192,150,45,44,40,59,17,65,237,223,132,37,253,50,238,188,21,100,230,226,200,27,28,248,99,116,13,247,165,1,210,249,131,206,107,138,161,191,168,26,141,194,186,143,4,72,202,68,135,56,83,218,98,190,117,227,15,201,12,173,235,205,69,77,120,209,61,129,231,181,241,60,41,66,214,119,94,8,71,82,76,62,6,75,167,112,25,95,156,19,160,151,159,122,47,136,134,24,203,73,92,58,121,113,187,32,211,153,101,126,54,130,252,91,220,35,234,2,149,52,232,216,5,244,124,184,169,33,170,255,49,103,53,133,185,212]
s_initial = rc4_reverse_initial_s(p, c, s_final)
print(s_initial)
[110, 89, 245, 118, 200, 160, 49, 72, 67, 201, 108, 116, 250, 208, 8, 68, 126, 125, 165, 214, 55, 40, 217, 42, 66, 221, 189, 22, 123, 88, 122, 249, 159, 204, 198, 94, 163, 74, 105, 242, 87, 172, 252, 243, 174, 146, 206, 225, 43, 65, 229, 169, 168, 148, 248, 196, 247, 153, 150, 226, 48, 84, 240, 162, 139, 59, 157, 164, 31, 129, 52, 80, 103, 161, 81, 237, 75, 0, 177, 234, 219, 186, 223, 70, 155, 197, 37, 180, 246, 11, 56, 46, 62, 199, 86, 10, 179, 251, 181, 85, 193, 83, 97, 166, 141, 4, 230, 154, 51, 7, 36, 30, 233, 38, 57, 23, 254, 63, 239, 207, 192, 109, 45, 44, 195, 64, 17, 176, 115, 213, 132, 178, 253, 50, 238, 188, 21, 100, 93, 152, 79, 27, 28, 106, 99, 215, 13, 228, 183, 1, 210, 34, 131, 182, 107, 138, 175, 191, 145, 26, 90, 194, 18, 143, 3, 147, 202, 128, 135, 127, 158, 218, 98, 190, 117, 227, 15, 20, 12, 173, 235, 205, 69, 77, 120, 209, 61, 140, 231, 171, 241, 60, 41, 111, 114, 119, 14, 104, 71, 82, 76, 78, 6, 224, 167, 112, 25, 95, 156, 19, 39, 151, 16, 102, 47, 136, 134, 24, 203, 73, 92, 58, 121, 113, 187, 32, 211, 29, 101, 96, 54, 130, 137, 91, 220, 35, 144, 2, 149, 142, 232, 216, 5, 244, 124, 184, 9, 33, 170, 255, 222, 236, 53, 133, 185, 212]
加密逻辑:
import random
BASE_TABLE = "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe"
def b64_swap_decode(s: str, alphabet: str = BASE_TABLE) -> bytes:
table = {ch: i for i, ch in enumerate(alphabet)}
s = s.strip()
if len(s) % 4:
s += "=" * ((4 - len(s) % 4) % 4)
out = bytearray()
for i in range(0, len(s), 4):
block = s[i:i+4]
pad = block.count("=")
vals = []
for ch in block:
if ch == "=":
vals.append(0)
else:
if ch not in table:
raise ValueError(f"字母表中不存在字符: {repr(ch)}")
vals.append(table[ch])
v = (vals[0] << 18) | (vals[1] << 12) | (vals[2] << 6) | vals[3]
out.append((v >> 16) & 0xFF)
if pad < 2:
out.append((v >> 8) & 0xFF)
if pad < 1:
out.append(v & 0xFF)
return bytes(out)
def b64_swap_encode(b: bytes, alphabet: str = BASE_TABLE) -> str:
res = []
for i in range(0, len(b), 3):
chunk = b[i:i+3]
pad = 3 - len(chunk)
if pad:
chunk = chunk + b"\x00" * pad
val = (chunk[0] << 16) | (chunk[1] << 8) | chunk[2]
res.append(alphabet[(val >> 18) & 0x3F])
res.append(alphabet[(val >> 12) & 0x3F])
res.append("=" if pad == 2 else alphabet[(val >> 6) & 0x3F])
res.append("=" if pad >= 1 else alphabet[val & 0x3F])
return "".join(res)
def sm3_hex(s: str) -> str:
def rol(x, n): return ((x << n) | (x >> (32 - n))) & 0xFFFFFFFF
def P0(x): return x ^ rol(x, 9) ^ rol(x, 17)
def P1(x): return x ^ rol(x, 15) ^ rol(x, 23)
V = [
0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600,
0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E,
]
m = bytearray(s.encode("utf-8"))
bitlen = (len(m) * 8) & ((1 << 64) - 1)
m.append(0x80)
while (len(m) + 8) % 64 != 0:
m.append(0x00)
m += bitlen.to_bytes(8, "big")
for off in range(0, len(m), 64):
B = m[off:off+64]
W = [int.from_bytes(B[i*4:i*4+4], "big") for i in range(16)] + [0]*52
for i in range(16, 68):
W[i] = (P1(W[i-16] ^ W[i-9] ^ rol(W[i-3], 15)) ^ rol(W[i-13], 7) ^ W[i-6]) & 0xFFFFFFFF
W1 = [(W[i] ^ W[i+4]) & 0xFFFFFFFF for i in range(64)]
A,Bb,C,D,E,F,G,H = V
for j in range(64):
T = 0x79CC4519 if j <= 15 else 0x7A879D8A
SS1 = rol((rol(A,12) + E + rol(T, j & 31)) & 0xFFFFFFFF, 7)
SS2 = SS1 ^ rol(A,12)
FF = (A ^ Bb ^ C) if j <= 15 else ((A & Bb) | (A & C) | (Bb & C))
GG = (E ^ F ^ G) if j <= 15 else ((E & F) | ((~E) & G))
TT1 = (FF + D + SS2 + W1[j]) & 0xFFFFFFFF
TT2 = (GG + H + SS1 + W[j]) & 0xFFFFFFFF
D, C, Bb, A = C, rol(Bb, 9), A, TT1
H, G, F, E = G, rol(F, 19), E, P0(TT2)
V = [(V[0]^A)&0xFFFFFFFF, (V[1]^Bb)&0xFFFFFFFF, (V[2]^C)&0xFFFFFFFF, (V[3]^D)&0xFFFFFFFF,
(V[4]^E)&0xFFFFFFFF, (V[5]^F)&0xFFFFFFFF, (V[6]^G)&0xFFFFFFFF, (V[7]^H)&0xFFFFFFFF]
return "".join(f"{x:08x}" for x in V)
def rc4_2(data: bytes) -> bytes:
table = [110,89,245,118,200,160,49,72,67,201,108,116,250,208,8,68,126,125,165,214,55,40,217,42,66,221,189,22,123,88,122,249,159,204,198,94,163,74,105,242,87,172,252,243,174,146,206,225,43,65,229,169,168,148,248,196,247,153,150,226,48,84,240,162,139,59,157,164,31,129,52,80,103,161,81,237,75,0,177,234,219,186,223,70,155,197,37,180,246,11,56,46,62,199,86,10,179,251,181,85,193,83,97,166,141,4,230,154,51,7,36,30,233,38,57,23,254,63,239,207,192,109,45,44,195,64,17,176,115,213,132,178,253,50,238,188,21,100,93,152,79,27,28,106,99,215,13,228,183,1,210,34,131,182,107,138,175,191,145,26,90,194,18,143,3,147,202,128,135,127,158,218,98,190,117,227,15,20,12,173,235,205,69,77,120,209,61,140,231,171,241,60,41,111,114,119,14,104,71,82,76,78,6,224,167,112,25,95,156,19,39,151,16,102,47,136,134,24,203,73,92,58,121,113,187,32,211,29,101,96,54,130,137,91,220,35,144,2,149,142,232,216,5,244,124,184,9,33,170,255,222,236,53,133,185,212]
out = bytearray()
i = 0
j = 0
for b in data:
i = (i + 1) % 256
j = (j + table[i]) % 256
table[i], table[j] = table[j], table[i]
K = table[(table[i] + table[j]) % 256]
out.append(b ^ K)
return bytes(out)
if __name__ == "__main__":
data = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36"
rc4_encoded = rc4_2(data.encode("utf-8"))
print("RC4 Encoded bytes:", rc4_encoded)
decoded_data = b64_swap_encode(rc4_encoded)
print("Encoded string:", decoded_data)
sm3_data = sm3_hex(decoded_data)
print("SM3 Hash:", sm3_data)
print("SM3 Decimal values:", " ".join(str(int(sm3_data[i:i+2], 16)) for i in range(0, len(sm3_data), 2)))
这里是UA进行加密
再刷新一下,发现这个rc4的表是会变的,那就说明这个表的key是每一次不一样的,看一下为什么
这里应该是索引:[0.00390625, 1, 14]
这个第一个应该是固定的,可以很明显的看出来是1/256 = 0.00390625
def rc4_2(data: bytes) -> bytes:
r = []
k = 0
y = [0, 1, 14]
for i in range(255, -1, -1):
r.append(i)
for i in range(len(r)):
a = r[i]
k = (k * a + k + y[i % 3]) % 256
b = r[k]
r[i], r[k] = b, a
table = r
out = bytearray()
i = 0
j = 0
for b in data:
i = (i + 1) % 256
j = (j + table[i]) % 256
table[i], table[j] = table[j], table[i]
K = table[(table[i] + table[j]) % 256]
out.append(b ^ K)
return bytes(out)
这样表就可以生成了
后面就没可以逆的算法了,都是sm3,请求参数拼接一个dhzx进行两次sm3,再对dhzx单独做两次sm3
修改sm3函数
def enc_sum(n_str: str, as_hex: bool = False):
def rotl(x, n):
n &= 31
return ((x << n) | (x >> (32 - n))) & 0xffffffff
def Tj(j):
if 0 <= j < 16:
return 0x79cc4519 # 2043430169
elif 16 <= j < 64:
return 0x7a879d8a # 2055708042
else:
raise ValueError("invalid j for Tj")
def FF(j, x, y, z):
if 0 <= j < 16:
return (x ^ y ^ z) & 0xffffffff
elif 16 <= j < 64:
return ((x & y) | (x & z) | (y & z)) & 0xffffffff
else:
raise ValueError("invalid j for FF")
def GG(j, x, y, z):
if 0 <= j < 16:
return (x ^ y ^ z) & 0xffffffff
elif 16 <= j < 64:
return ((x & y) | (~x & z)) & 0xffffffff
else:
raise ValueError("invalid j for GG")
class SM3:
def __init__(self):
self.reg = [0] * 8
self.chunk = bytearray()
self.size = 0
self.reset()
def reset(self):
self.reg[0] = 0x7380166f # 1937774191
self.reg[1] = 0x4914b2b9 # 1226093241
self.reg[2] = 0x172442d7 # 388252375
self.reg[3] = 0xda8a0600 # 3666478592
self.reg[4] = 0xa96f30bc # 2842636476
self.reg[5] = 0x163138aa # 372324522
self.reg[6] = 0xe38dee4d # 3817729613
self.reg[7] = 0xb0fb0e4e # 2969243214
self.chunk = bytearray()
self.size = 0
def write(self, data):
if isinstance(data, str):
bs = data.encode("utf-8")
elif isinstance(data, (bytes, bytearray)):
bs = bytes(data)
else:
bs = bytes(int(b) & 0xff for b in data)
self.size += len(bs)
self.chunk.extend(bs)
while len(self.chunk) >= 64:
block = self.chunk[:64]
self._compress(block)
self.chunk = self.chunk[64:]
def _compress(self, block: bytes):
if len(block) < 64:
raise ValueError("compress error: not enough data")
W = [0] * 132
for i in range(16):
W[i] = (
(block[4 * i] << 24)
| (block[4 * i + 1] << 16)
| (block[4 * i + 2] << 8)
| (block[4 * i + 3])
) & 0xffffffff
for i in range(16, 68):
tmp = W[i - 16] ^ W[i - 9] ^ rotl(W[i - 3], 15)
tmp = tmp ^ rotl(tmp, 15) ^ rotl(tmp, 23)
W[i] = (tmp ^ rotl(W[i - 13], 7) ^ W[i - 6]) & 0xffffffff
for i in range(64):
W[i + 68] = (W[i] ^ W[i + 4]) & 0xffffffff
a, b, c, d, e, f, g, h = self.reg
for j in range(64):
ss1 = (rotl(a, 12) + e + rotl(Tj(j), j)) & 0xffffffff
ss1 = rotl(ss1 & 0xffffffff, 7)
ss2 = ss1 ^ rotl(a, 12)
tt1 = (FF(j, a, b, c) + d + ss2 + W[j + 68]) & 0xffffffff
tt2 = (GG(j, e, f, g) + h + ss1 + W[j]) & 0xffffffff
d = c
c = rotl(b, 9)
b = a
a = tt1 & 0xffffffff
h = g
g = rotl(f, 19)
f = e
e = (tt2 ^ rotl(tt2, 9) ^ rotl(tt2, 17)) & 0xffffffff
self.reg = [
(self.reg[0] ^ a) & 0xffffffff,
(self.reg[1] ^ b) & 0xffffffff,
(self.reg[2] ^ c) & 0xffffffff,
(self.reg[3] ^ d) & 0xffffffff,
(self.reg[4] ^ e) & 0xffffffff,
(self.reg[5] ^ f) & 0xffffffff,
(self.reg[6] ^ g) & 0xffffffff,
(self.reg[7] ^ h) & 0xffffffff,
]
def _fill(self):
t = self.size * 8
self.chunk.append(0x80)
while (len(self.chunk) % 64) != 56:
self.chunk.append(0)
high = (t >> 32) & 0xffffffff
low = t & 0xffffffff
for e in range(4):
self.chunk.append((high >> (8 * (3 - e))) & 0xff)
for e in range(4):
self.chunk.append((low >> (8 * (3 - e))) & 0xff)
def sum(self, data=None, mode=None):
if data is not None:
self.reset()
self.write(data)
self._fill()
for i in range(0, len(self.chunk), 64):
self._compress(self.chunk[i:i + 64])
if mode == "hex":
out = "".join(f"{x:08x}" for x in self.reg)
else:
out = []
for x in self.reg:
out.extend([
(x >> 24) & 0xff,
(x >> 16) & 0xff,
(x >> 8) & 0xff,
x & 0xff,
])
self.reset()
return out
sm3 = SM3()
if as_hex:
return sm3.sum(n_str, mode="hex")
else:
return sm3.sum(n_str)
测试解密均可以
后续再整理,以上是整个过程中自己的所有思路,很乱!仅供参考