关于dya_bogus逆向,jsvmp

进行抖音抓包,对应的位置在

image-20251112152426947

url = "https://www.douyin.com/aweme/v1/web/aweme/post/"

可以看一下调用栈,不难发现主要的逻辑在bdms_1.0.1.19_fix.js

image-20251112152556501

直接跳过去可以看到d就是指令操作

image-20251112153117133

先一点一点的去看

image-20251112160500559

这个位置调用了atob,代表了对下面的那个字符进行了base64的解密,随后取第 4~7 字节求和得到单字节 key

image-20251112160806447

再用自定义 map 函数 _ 对余下字节逐个异或,最后把结果送进自带的 DEFLATE 解压器,从而得到可执行的数据块,这里可以很好的看出来这一块是一个压缩文件的格式,对应base64的UEsC

image-20251112161227168

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的东西进行对应上

image-20251112162756570

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

image-20251112174006274

字符串的位置走过后,这个位置是函数表对应的条数

0x1C | 0x80 = 0x9C

计算后这个位置应该是796条,下图调试的位置吻合

image-20251112174451286

打印出来:

image-20251112175425724

字符串表

image-20251112175912681

a_bogus对应的是表的Z[220]

调试位置对应的url的方法

image-20251112165013930

调试到这里可以看到对应的字节码的东西为

image-20251112165335680

{"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就可以看到整个流程的生成了

image-20251113103317350

打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

直接开始跑,我们从最后生成往上回溯分析

image-20251113105409137

可以看到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))

image-20251113105808231

可以看到和刚过来的数组是一样的

image-20251113105827094

在这里可以看到,这里的字符是拼接来的,前4字节和后面进行了拼接,先看一下后面的字节的来源

image-20251113105939089

追上去后可以看到两个部分的线索,直接直接就可以根据rc4的特征来看到,这部分上面是表的生成,下面是标准的rc4的算法(除了表生成位置)

image-20251113110100556

表生成位置:

image-20251113110217140

直接根据他给的写就行,写一下算法,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

image-20251113110433448

rc4这个位置是没有错的,继续往下分析

前面四个字节的来源,前四个字节是41 71 82 23看一下来源

image-20251113110915960

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位数组来的

image-20251113111746995

第一组的地方3, 84, 32, 64

image-20251113112712347

第二组的地方33, 16, 162, 84

image-20251113113012341

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)

image-20251113115048560

对应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

正好对应上了

image-20251113124243229

网上回溯看一下这个是怎么生成的,这个时候可以看到这里面永远都会一组重复的数字145, 110, 66, 189, 44, 211

image-20251113130011811

根据上面可以写出加密逻辑

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)

image-20251113135029934

对应了:

[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
]

继续往上根

image-20251113135403102

他把刚才的这些数据进行了分组

[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%

那么剩下关心的就是剩下的这几组的参数了

四位的情况向上回溯,和时间戳有关系

image-20251113140027821

可以看到最后的那个单个的数字159是经过很多次的xor得到的

image-20251113141944377

如果你的记忆里很好的话,看到这里的时候你就一定会知道这些东西你见过,就是之前那个随机的8位数

image-20251113142714362

Generated r_head Decimal values: 3 84 32 64 33 16 162 84

这个时候就会疑问这个41后面的都是哪里来的,重新trace看一下对应的位置

image-20251113162251756

Xor 41索引位置24

image-20251113162549630

依次把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ŸëÉ\u001fŽ“4#øFbÏëÔ®\u0019¨sêaˆÊ.>(Ê) fL4\u0017€å‡ä·’\u000fÞ \u0004º·×e\u001f|Á´€Ñ°pPŸÔ¶HÕf\u0016xEåÚHƒ0*üÑm¾Ro6ˆem¯œö\u0018p’ã\u0019(žZv¨pµûýªvi¤\u0002s1ð\u0000yvÞ\u0007\u0015\u0003Ã\u0001\u0017dé«`C­Bgs",
    "\u000b\u0003r\u0007Õ5¨6°ø+¸¢¬¦ÿTŸëÉ\u001fŽ“4#øFbÏëÔ®\u0019¨sêaˆÊ.>(Ê) fL4\u0017€å‡ä·’\u000fÞ \u0004º·×e\u001f|Á´€Ñ°pPŸÔ¶HÕf\u0016xEåÚHƒ0*üÑm¾Ro6ˆem¯œö\u0018p’ã\u0019(žZv¨pµûýªvi¤\u0002s1ð\u0000yvÞ\u0007\u0015\u0003Ã\u0001\u0017dé«`C­Bgs",
    "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)

image-20251113164322948

可以对应上

image-20251113164505338

同理上面如果继续看的还会看到一个表

[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位生成的地方,可以看到可以很完美的对应上

image-20251113165524893

继续向上看的话,可以看一个新的值

image-20251113165800930

这个位置对应了刚才分析到拿出来参数的这个位置

image-20251113165900174

可以很好的看出来这是一个sm3加密算法

image-20251113171114854

这个位置和js的某一个地方的源码一样,key = sum

image-20251113172357696

那么参数应该就是那个加密后的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

和加密位置吻合

image-20251113182718468

这上面生成的还是之前那个base64变表,只是table换成了:ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe

再往上看就是rc4的变种

image-20251113203632399

不过很奇怪,这个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]

image-20251113204457190

加密逻辑:

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进行加密

image-20251113204910673

再刷新一下,发现这个rc4的表是会变的,那就说明这个表的key是每一次不一样的,看一下为什么

image-20251113215810862

这里应该是索引:[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)

这样表就可以生成了

image-20251113221023510

后面就没可以逆的算法了,都是sm3,请求参数拼接一个dhzx进行两次sm3,再对dhzx单独做两次sm3

image-20251113210525323

image-20251113205140533

修改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)

image-20251113222334728

测试解密均可以

image-20251113222653610

后续再整理,以上是整个过程中自己的所有思路,很乱!仅供参考