
2025新春挑战-猿人学
2025 新春挑战-猿人学
headers 中的 a
d[d.length - 1] ? console.log("func::",d[d.length - 2],"this::",d[d.length - 3],"arg::",a) : console.log("func::",d[d.length - 2],"this::",window,"arg::",a);false;
我们插装看到一个很熟悉的值
拿去百度一搜是 sha256
但是我们仔细对比 k 表发现 他的 k 值对不上 可以确信的是 a 应该为魔改的 sha256 我们知道 sha256 是 64 为 但实际上 a 的长度为 128 位
那么可能猜一下应该是分两段的
我们继续往下查看传参
第一段加密的是 b 的值
第二段加密的是 参赛 params 的内容
合起来得到的就是 128 位的 a 值 那么也就清楚了
魔改了 sha256 就先去 b 站看有具体的分析教程 我这里就不一个个分析了
headers 中的 b
b 加密是 aes 的 cbc 这里我是算法推理出来的 然后拿着 key 搜索 发现就是 websocket 中返回的东西 具体找 key 和 iv 的教程 也可以去 b 站看分析
key 是 ws 中返回的 key
iv 也是 ws 中返回的 key
插桩的地方可以看到
1
2
3
4
5
sha256_hash = encrypt.sha256(encrypt_array[-2])
print(sha256_hash)
big_int = int(sha256_hash, 16)
iv_at = big_int % (len(encrypt_array) - 1)
key_at = (int(encrypt_array[-1]) - iv_at + len(encrypt_array) - 1) % (len(encrypt_array) - 1)
响应中的 b
也可以算法推理出来
返回的 b 加密 是 aes ecb 模式。key 是 websocket 中返回 array 中的倒第二位 key
具体可以去 b 站看有分析教程 能学到一些技巧。
最终结果
代码部分
js 部分
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// SHA-256 Implementation in JavaScript (pure JS)
function sha256(ascii) {
const K = [
0, 0, 1116352408, 1899447441, -1245643825, -373957723, 961987163,
1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278,
1426881987, 1925078388, -2132889090, -1680079193, -1046744716, -459576895,
-272742522,
];
function rightRotate(value, amount) {
return (value >>> amount) | (value << (32 - amount));
}
function utf8Encode(str) {
return unescape(encodeURIComponent(str));
}
let words = [];
const preprocessed = utf8Encode(ascii);
const asciiBitLength = preprocessed.length * 8;
for (let i = 0; i < preprocessed.length; i++) {
words[i >> 2] |= preprocessed.charCodeAt(i) << (24 - (i % 4) * 8);
}
words[preprocessed.length >> 2] |=
0x80 << (24 - (preprocessed.length % 4) * 8);
words[(((asciiBitLength + 64) >> 9) << 4) + 15] = asciiBitLength;
let hash = [
0, 0, 1779033703, -1150833019, 1013904242, -1521486534, 1359893119,
-1694144372,
];
for (let j = 0; j < words.length; j += 16) {
const w = new Array(16).fill(0);
for (let i = 0; i < 16; i++) {
w[i] = words[j + i] | 0;
}
// for (let i = 16; i < 64; i++) {
// const s0 = rightRotate(w[i - 15], 7) ^ rightRotate(w[i - 15], 18) ^ (w[i - 15] >>> 3);
// const s1 = rightRotate(w[i - 2], 17) ^ rightRotate(w[i - 2], 19) ^ (w[i - 2] >>> 10);
// w[i] = (w[i - 16] + s0 + w[i - 7] + s1) | 0;
// }
let [a, b, c, d, e, f, g, h] = hash;
for (let i = 0; i < 64; i++) {
let mdeida;
let s00, s11;
if (i - 2 >= 0) {
s00 =
rightRotate(w[i - 2], 17) ^
rightRotate(w[i - 2], 19) ^
(w[i - 2] >>> 10);
} else {
s00 = 0;
}
if (i - 15 >= 0) {
s11 =
rightRotate(w[i - 15], 7) ^
rightRotate(w[i - 15], 18) ^
(w[i - 15] >>> 3);
} else {
s11 = 0;
}
mdeida = ((w[i - 16] | 0) + s00 + (w[i - 7] | 0) + s11) | 0;
w[i] = (w[i] + mdeida) | 0;
const s1 = rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25);
const ch = (e & f) ^ (~e & g);
const temp1 = (h + s1 + ch + K[i] + w[i]) | 0;
const s0 = rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22);
const maj = (a & b) ^ (a & c) ^ (b & c);
const temp2 = (s0 + maj) | 0;
h = g;
g = f;
f = e;
e = (d + temp1) | 0;
d = c;
c = b;
b = a;
a = (temp1 + temp2) | 0;
}
for (let i = 0; i < 8; i++) {
hash[i] = (hash[i] + [a, b, c, d, e, f, g, h][i]) | 0;
}
}
return hash
.map((h) => ("00000000" + (h >>> 0).toString(16)).slice(-8))
.join("");
}
// Example usage
console.log(sha256("123"));
python 部分
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# -*- coding: utf-8 -*-
"""
@author: 眠棠
@software: PyCharm
@file: requests_new.py
@time: 2025/1/20 上午9:54
@Software: PyCharm
"""
import base64
import json
import random
from functools import reduce
import websocket
import encrypt
import os
import pyhttpx
def get_header(post_data):
def get_encrypt_array():
def get_random_str():
base36_str = ''.join(
random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for _ in range(random.randint(9, 11)))
return base36_str
ws_obj = websocket.create_connection("wss://match.yuanrenxue.cn/api/match/22",
cookie="sessionid=wc9lak3tci1cukuxav3id54y38hwy3ek", header={
"Origin": "https://match.yuanrenxue.cn",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Sec-WebSocket-Key": base64.b64encode(os.urandom(16)).decode(),
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0",
"Sec-WebSocket-Version": "13",
"Sec-WebSocket-Extensions": "permessage-deflate; client_max_window_bits"
})
res_array = []
if ws_obj.status == 101:
while True:
ws_obj.send(get_random_str())
response = ws_obj.recv()
if response.isdigit():
res_array.append(response)
ws_obj.close()
break
else:
res_array.append(response)
print(res_array)
return res_array
# websocks返回的加密数组
encrypt_array = get_encrypt_array()
sha256_hash = encrypt.sha256(encrypt_array[-2])
print(sha256_hash)
big_int = int(sha256_hash, 16)
iv_at = big_int % (len(encrypt_array) - 1)
key_at = (int(encrypt_array[-1]) - iv_at + len(encrypt_array) - 1) % (len(encrypt_array) - 1)
print(iv_at, key_at, post_data)
print(encrypt_array[key_at], encrypt_array[iv_at])
A = encrypt.aes_encrypt_cbc(key_str=encrypt_array[key_at], iv_str=encrypt_array[iv_at], data=post_data)
B = encrypt.sha256(A) + encrypt.sha256(post_data)
return {
"a": A,
"b": B
}, encrypt_array
def get_page_requests(page):
cookies = {
"sessionid": "wc9lak3tci1cukuxav3id54y38hwy3ek",
}
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 Edg/132.0.0.0",
"referer": "https://match.yuanrenxue.cn/match/22",
}
data = json.dumps({
"page": page,
"url": "https://match.yuanrenxue.cn/match/22",
"c": json.dumps([
f"sessionid={cookies['sessionid']}"
], separators=(',', ':')),
}, separators=(',', ':'))
session = pyhttpx.HttpSession(http2=True, browser_type="chrome")
session.get("https://match.yuanrenxue.cn/api/loginInfo", cookies=cookies, headers=headers)
print("加密data", data)
new_headers, encrypt_array = get_header(data)
print(new_headers, encrypt_array)
# 直接更新 headers 字典
headers.update(new_headers)
# 验证更新后的 headers
print(headers)
response = session.post("https://match.yuanrenxue.cn/api/match/22", headers=headers, data=data, cookies=cookies)
json_res = response.json()
print(json_res)
ecb_key = encrypt_array[int(encrypt_array[-1])]
print('ecb->key', ecb_key)
print(json_res['B'])
decrypted_str = encrypt.aes_decrypt_ecb(key_str=ecb_key, data=json_res['B'])
# 去除不可见填充字符(常见的填充字符可能包括 \x05, \x00, \n, \r, 空格等)
cleaned_str = decrypted_str.rstrip("\x05\x00\n\r ")
# 转换为 JSON
try:
json_data = json.loads(cleaned_str)
extracted_data = json_data.get("data", []) # 提取 data 字段
print("提取的 data:", extracted_data)
return extracted_data
except json.JSONDecodeError as e:
print("JSON解析错误:", e)
def run():
sum_all = 0
for page in range(1, 6):
page_res = get_page_requests(page)
print(page_res)
if page_res:
sum_all += dict(reduce(lambda x, y: {"value": x['value'] + y['value']}, page_res))['value']
else:
print(f"当前page{page}出错")
print(sum_all)
if __name__ == '__main__':
run()
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
import json
import execjs
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
def sha256(text):
f = open("sha256.js", mode="r", encoding="utf-8")
js_code = f.read()
f.close()
js = execjs.compile(js_code) # 加载JS代码
mi = js.call("sha256", text) # 运行JS代码
return mi
# AES加密函数(CBC模式)
def aes_encrypt_cbc(key_str, iv_str, data):
# 将key和iv字符串转换为字节
key = key_str.encode('utf-8')
iv = iv_str.encode('utf-8')
# 确保key和iv的长度正确
key = key.ljust(16, b'\0')[:16] # 填充或截断为16字节
iv = iv.ljust(16, b'\0')[:16] # 填充或截断为16字节
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted_data = cipher.encrypt(pad(data.encode(), AES.block_size))
return base64.b64encode(encrypted_data).decode()
def aes_decrypt_ecb(key_str, data):
message = data
# 将key和iv字符串转换为字节
key = key_str.encode('utf-8')
message = base64.b64decode(message.encode())
aes = AES.new(key, AES.MODE_ECB)
aes_result = aes.decrypt(message).decode()
# print(aes_result)
return aes_result
if __name__ == '__main__':
print(sha256('123')) aes_decrypt_ecb('LjW9ax99r6DWYOMP','71NkvqbIDTN5ih80w+GbMnIczZVdsyMu/cbP74GchId1V9ATxawUG/TuMn2bvomjxAUxmjiaezYTAkEH7b2AAyYAV9AZs7HF5dAFIutgKjhHgFGx1tMeAkJU7dnJ+82+8S2utMGSwjQGQEJTir2kDT/KSZIxfDU2yr3fM7n8lmNqY+NFMls801ua/qCn9JK3CjUuXlc28eGZlAZ4KxVE26WPu7P2p5XD/RPs3079sl0CJwze2JqGGrowIsggYimMzLdhG5FhYSWwxQyi88YPOAfn5mLTwNXcXH9ClZMQQsI=')