最近忽然看到了js逆向感觉很有意思,简单学习了一点点的知识

猿人学js逆向Chanllenge

平台地址:https://match.yuanrenxue.cn/,没错,我就是看到这个平台才开始了解的,这个里面有的混淆题目我也不会。

Task 12

首先是第12题-入门级js(超级入门题目)

访问看到连接看到url中有一个加密参数

image-20240124134303328

然后这里直接下一个XHR断点(“api/match/12”),然后看堆栈,点进去看这个m参数是从哪里生成出来的,这个特别简单,在request中可以看到"m": btoa('yuanrenxue' + window.page)
简单说一下btoa()是js中base64编码的函数,atob()是base64解码的函数。

image-20240124134953214

验证一下

image-20240124135623866

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
import requests
import execjs
import re

cookies = {
# 写自己的cookie
}

headers = {
'authority': 'match.yuanrenxue.cn',
'accept': 'application/json, text/javascript, */*; q=0.01',
'accept-language': 'zh-CN,zh;q=0.9',
'cache-control': 'no-cache',
'pragma': 'no-cache',
'referer': 'https://match.yuanrenxue.cn/match/12',
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'x-requested-with': 'XMLHttpRequest',
}

def getData(page):
r = re.compile('"value": ([^}]+)}')
ctx = execjs.compile("""function getM(page){return btoa("yuanrenxue"+page);}""")
m = ctx.call('getM', page)
params = {
'page': page,
'm': m,
}

response = requests.get('https://match.yuanrenxue.cn/api/match/12', params=params, cookies=cookies,
headers=headers).text
# print(response)
return r.findall(response)


if __name__ == '__main__':
sum = 0
for i in range(1, 6):
dataList = getData(i)
for j in dataList:
sum = int(j) + sum

answerUrl = "https://match.yuanrenxue.cn/api/answers?answer="+str(sum)+"&id=12"
response = requests.get(answerUrl,cookies=cookies,headers=headers)
print(response.text)

image-20240124142635032

Task 13

打开后随便点击下一页,然后看一下包,根据题目入门cookie,肯定是有一个cookie需要构造,cookie中有一个yuanrenxue_cookie,比较显眼。仔细看控制台有一个请求/match/13,第一次的结果浏览器没有办法查看,所以用fiddler抓一下包。
image-20240124185050486

location.href=location.pathname+location.search这句js代码是刷新当前页面
这样就很简单了,只要每次获取到cookie添加一下就ok了

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
import requests
import re

cookies = {
# 'yuanrenxue_cookie': '1706093844|geXtMJX1Y1YBLA3rXIS3pAYle4xBPPOFI6opisWIBTOYdBhYS2ylGXAWIjJXG6rx2WY3SVcRwaiti7pj49Fx9kU3v7Oxo',
}

headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Referer': 'https://match.yuanrenxue.cn/match/13',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
'sec-ch-ua-platform': '"Windows"',
}

r = re.compile("\(\'([\S])\'\)")
r_data = re.compile('"value": ([^}]+)}')


def getCookie():
response = requests.get('https://match.yuanrenxue.cn/match/13', cookies=cookies, headers=headers)
cookieJs = response.text
cookieList = r.findall(cookieJs)
cookie = ''.join(cookieList)
if '=' in cookie:
return cookie.split('=')[1]
else:
return ''


if __name__ == '__main__':
sum = 0
for i in range(1, 6):
cookie = getCookie()
if cookie != '':
cookies['yuanrenxue_cookie'] = cookie
response = requests.get('https://match.yuanrenxue.cn/api/match/13?page=' + str(i), cookies=cookies,
headers=headers).text
for j in r_data.findall(response):
sum = int(j) + sum

answerUrl = "https://match.yuanrenxue.cn/api/answers?answer=" + str(sum) + "&id=13"
response = requests.get(answerUrl, cookies=cookies, headers=headers)
print(response.text)

学校登录参数分析

登录请求的参数有两个需要构造,一个是info,一个是chksum

image-20240125122205992

password是hmd5,下面有找这个参数的构造

image-20240125170502630

image-20240125153353655

然后开始找参数加密的过程,首先是info,先全局搜索一下info =内容比较多,然后尝试搜一下{SRBX1},直接定位到info的位置

image-20240125122605108

image-20240125122630150

然后直接在这里打个断点,重新登录一下,看看这里的infotoken是什么?

image-20240125122841679

image-20240125122928179

info就是登录的一些参数,顺着堆栈找一下token

image-20240125123305995

这里看到token,好像是某个请求的响应,然后停止debugger,去网络抓到的包里看一下

image-20240125123432686

只需要把encode()抠出来就能构造info参数了

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
function s(a, b) {
var c = a.length;
var v = [];

for (var i = 0; i < c; i += 4) {
v[i >> 2] = a.charCodeAt(i) | a.charCodeAt(i + 1) << 8 | a.charCodeAt(i + 2) << 16 | a.charCodeAt(i + 3) << 24;
}

if (b) v[v.length] = c;
return v;
}

function encode(str, key) {
if (str === '') return '';
var v = s(str, true);
var k = s(key, false);
if (k.length < 4) k.length = 4;
var n = v.length - 1,
z = v[n],
y = v[0],
c = 0x86014019 | 0x183639A0,
m,
e,
p,
q = Math.floor(6 + 52 / (n + 1)),
d = 0;

while (0 < q--) {
d = d + c & (0x8CE0D9BF | 0x731F2640);
e = d >>> 2 & 3;

for (p = 0; p < n; p++) {
y = v[p + 1];
m = z >>> 5 ^ y << 2;
m += y >>> 3 ^ z << 4 ^ (d ^ y);
m += k[p & 3 ^ e] ^ z;
z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF);
}

y = v[0];
m = z >>> 5 ^ y << 2;
m += y >>> 3 ^ z << 4 ^ (d ^ y);
m += k[p & 3 ^ e] ^ z;
z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD);
}

return l(v, false);
}
function l(a, b) {
var d = a.length;
var c = d - 1 << 2;

if (b) {
var m = a[d - 1];
if (m < c - 3 || m > c) return null;
c = m;
}

for (var i = 0; i < d; i++) {
a[i] = String.fromCharCode(a[i] & 0xff, a[i] >>> 8 & 0xff, a[i] >>> 16 & 0xff, a[i] >>> 24 & 0xff);
}

return b ? a.join('').substring(0, c) : a.join('');
}

image-20240125124203193

能跑的通,然后去验证一下是否正确,很遗憾结果不一样,我猜测是base64的问题
image-20240125124750932

果然base64编码结果不一样,那就只能偷base64了,这里的base64与正常的加密不一致,直接找到位置去偷:

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
var _ALPHA = "LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA";
function _encode(s) {
if (arguments.length !== 1) {
throw "SyntaxError: exactly one argument required"
}
s = String(s);
var i, b10, x = [], imax = s.length - s.length % 3;
if (s.length === 0) {
return s
}
for (i = 0; i < imax; i += 3) {
b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8) | _getbyte(s, i + 2);
x.push(_ALPHA.charAt(b10 >> 18));
x.push(_ALPHA.charAt((b10 >> 12) & 63));
x.push(_ALPHA.charAt((b10 >> 6) & 63));
x.push(_ALPHA.charAt(b10 & 63))
}
switch (s.length - imax) {
case 1:
b10 = _getbyte(s, i) << 16;
x.push(_ALPHA.charAt(b10 >> 18) + _ALPHA.charAt((b10 >> 12) & 63) + _PADCHAR + _PADCHAR);
break;
case 2:
b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8);
x.push(_ALPHA.charAt(b10 >> 18) + _ALPHA.charAt((b10 >> 12) & 63) + _ALPHA.charAt((b10 >> 6) & 63) + _PADCHAR);
break
}
return x.join("")
}

function _getbyte(s, i) {
var x = s.charCodeAt(i);
if (x > 255) {
throw "INVALID_CHARACTER_ERR: DOM Exception 5"
}
return x
}

到这里,info参数就解决了,然后是chksum,全局搜一下,打断点

image-20240125143942081

传入的参数有一堆,往上翻一翻,看一下这个字符串是怎么构造出来的

image-20240125144441112

好家伙,一顿乱拼

image-20240125144356187

这里的i就是上面的info参数,type = 1 应该是固定的,n = 200,ac_id = 0,hmd5 = md5(password, token) 此处的password为明文

下面为自己写的垃圾代码:

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
// md5.js
function t(n, t) {
var r = (65535 & n) + (65535 & t);
return (n >> 16) + (t >> 16) + (r >> 16) << 16 | 65535 & r
}
function r(n, t) {
return n << t | n >>> 32 - t
}
function e(n, e, o, u, c, f) {
return t(r(t(t(e, n), t(u, f)), c), o)
}
function o(n, t, r, o, u, c, f) {
return e(t & r | ~t & o, n, t, u, c, f)
}
function u(n, t, r, o, u, c, f) {
return e(t & o | r & ~o, n, t, u, c, f)
}
function c(n, t, r, o, u, c, f) {
return e(t ^ r ^ o, n, t, u, c, f)
}
function f(n, t, r, o, u, c, f) {
return e(r ^ (t | ~o), n, t, u, c, f)
}
function i(n, r) {
n[r >> 5] |= 128 << r % 32,
n[14 + (r + 64 >>> 9 << 4)] = r;
var e, i, a, d, h, l = 1732584193, g = -271733879, v = -1732584194, m = 271733878;
for (e = 0; e < n.length; e += 16)
i = l,
a = g,
d = v,
h = m,
g = f(g = f(g = f(g = f(g = c(g = c(g = c(g = c(g = u(g = u(g = u(g = u(g = o(g = o(g = o(g = o(g, v = o(v, m = o(m, l = o(l, g, v, m, n[e], 7, -680876936), g, v, n[e + 1], 12, -389564586), l, g, n[e + 2], 17, 606105819), m, l, n[e + 3], 22, -1044525330), v = o(v, m = o(m, l = o(l, g, v, m, n[e + 4], 7, -176418897), g, v, n[e + 5], 12, 1200080426), l, g, n[e + 6], 17, -1473231341), m, l, n[e + 7], 22, -45705983), v = o(v, m = o(m, l = o(l, g, v, m, n[e + 8], 7, 1770035416), g, v, n[e + 9], 12, -1958414417), l, g, n[e + 10], 17, -42063), m, l, n[e + 11], 22, -1990404162), v = o(v, m = o(m, l = o(l, g, v, m, n[e + 12], 7, 1804603682), g, v, n[e + 13], 12, -40341101), l, g, n[e + 14], 17, -1502002290), m, l, n[e + 15], 22, 1236535329), v = u(v, m = u(m, l = u(l, g, v, m, n[e + 1], 5, -165796510), g, v, n[e + 6], 9, -1069501632), l, g, n[e + 11], 14, 643717713), m, l, n[e], 20, -373897302), v = u(v, m = u(m, l = u(l, g, v, m, n[e + 5], 5, -701558691), g, v, n[e + 10], 9, 38016083), l, g, n[e + 15], 14, -660478335), m, l, n[e + 4], 20, -405537848), v = u(v, m = u(m, l = u(l, g, v, m, n[e + 9], 5, 568446438), g, v, n[e + 14], 9, -1019803690), l, g, n[e + 3], 14, -187363961), m, l, n[e + 8], 20, 1163531501), v = u(v, m = u(m, l = u(l, g, v, m, n[e + 13], 5, -1444681467), g, v, n[e + 2], 9, -51403784), l, g, n[e + 7], 14, 1735328473), m, l, n[e + 12], 20, -1926607734), v = c(v, m = c(m, l = c(l, g, v, m, n[e + 5], 4, -378558), g, v, n[e + 8], 11, -2022574463), l, g, n[e + 11], 16, 1839030562), m, l, n[e + 14], 23, -35309556), v = c(v, m = c(m, l = c(l, g, v, m, n[e + 1], 4, -1530992060), g, v, n[e + 4], 11, 1272893353), l, g, n[e + 7], 16, -155497632), m, l, n[e + 10], 23, -1094730640), v = c(v, m = c(m, l = c(l, g, v, m, n[e + 13], 4, 681279174), g, v, n[e], 11, -358537222), l, g, n[e + 3], 16, -722521979), m, l, n[e + 6], 23, 76029189), v = c(v, m = c(m, l = c(l, g, v, m, n[e + 9], 4, -640364487), g, v, n[e + 12], 11, -421815835), l, g, n[e + 15], 16, 530742520), m, l, n[e + 2], 23, -995338651), v = f(v, m = f(m, l = f(l, g, v, m, n[e], 6, -198630844), g, v, n[e + 7], 10, 1126891415), l, g, n[e + 14], 15, -1416354905), m, l, n[e + 5], 21, -57434055), v = f(v, m = f(m, l = f(l, g, v, m, n[e + 12], 6, 1700485571), g, v, n[e + 3], 10, -1894986606), l, g, n[e + 10], 15, -1051523), m, l, n[e + 1], 21, -2054922799), v = f(v, m = f(m, l = f(l, g, v, m, n[e + 8], 6, 1873313359), g, v, n[e + 15], 10, -30611744), l, g, n[e + 6], 15, -1560198380), m, l, n[e + 13], 21, 1309151649), v = f(v, m = f(m, l = f(l, g, v, m, n[e + 4], 6, -145523070), g, v, n[e + 11], 10, -1120210379), l, g, n[e + 2], 15, 718787259), m, l, n[e + 9], 21, -343485551),
l = t(l, i),
g = t(g, a),
v = t(v, d),
m = t(m, h);
return [l, g, v, m]
}
function a(n) {
var t, r = "", e = 32 * n.length;
for (t = 0; t < e; t += 8)
r += String.fromCharCode(n[t >> 5] >>> t % 32 & 255);
return r
}
function d(n) {
var t, r = [];
for (r[(n.length >> 2) - 1] = void 0,
t = 0; t < r.length; t += 1)
r[t] = 0;
var e = 8 * n.length;
for (t = 0; t < e; t += 8)
r[t >> 5] |= (255 & n.charCodeAt(t / 8)) << t % 32;
return r
}
function h(n) {
return a(i(d(n), 8 * n.length))
}
function l(n, t) {
var r, e, o = d(n), u = [], c = [];
for (u[15] = c[15] = void 0,
o.length > 16 && (o = i(o, 8 * n.length)),
r = 0; r < 16; r += 1)
u[r] = 909522486 ^ o[r],
c[r] = 1549556828 ^ o[r];
return e = i(u.concat(d(t)), 512 + 8 * t.length),
a(i(c.concat(e), 640))
}
function g(n) {
var t, r, e = "";
for (r = 0; r < n.length; r += 1)
t = n.charCodeAt(r),
e += "0123456789abcdef".charAt(t >>> 4 & 15) + "0123456789abcdef".charAt(15 & t);
return e
}
function v(n) {
return unescape(encodeURIComponent(n))
}
function m(n) {
return h(v(n))
}
function p(n) {
return g(m(n))
}
function s(n, t) {
return l(v(n), v(t))
}
function C(n, t) {
return g(s(n, t))
}
function A(n, t, r) {
return t ? r ? s(t, n) : C(t, n) : r ? m(n) : p(n)
}
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
import hashlib
import re
import execjs
import requests
import time

millis = int(round(time.time() * 1000))
def getInfo(data, token):
info_code = """
var _ALPHA = "LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA";
function s(a, b) {
var c = a.length;
var v = [];

for (var i = 0; i < c; i += 4) {
v[i >> 2] = a.charCodeAt(i) | a.charCodeAt(i + 1) << 8 | a.charCodeAt(i + 2) << 16 | a.charCodeAt(i + 3) << 24;
}

if (b) v[v.length] = c;
return v;
}

function encode(str, key) {
if (str === '') return '';
var v = s(str, true);
var k = s(key, false);
if (k.length < 4) k.length = 4;
var n = v.length - 1,
z = v[n],
y = v[0],
c = 0x86014019 | 0x183639A0,
m,
e,
p,
q = Math.floor(6 + 52 / (n + 1)),
d = 0;

while (0 < q--) {
d = d + c & (0x8CE0D9BF | 0x731F2640);
e = d >>> 2 & 3;

for (p = 0; p < n; p++) {
y = v[p + 1];
m = z >>> 5 ^ y << 2;
m += y >>> 3 ^ z << 4 ^ (d ^ y);
m += k[p & 3 ^ e] ^ z;
z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF);
}

y = v[0];
m = z >>> 5 ^ y << 2;
m += y >>> 3 ^ z << 4 ^ (d ^ y);
m += k[p & 3 ^ e] ^ z;
z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD);
}

return l(v, false);
}
function l(a, b) {
var d = a.length;
var c = d - 1 << 2;

if (b) {
var m = a[d - 1];
if (m < c - 3 || m > c) return null;
c = m;
}

for (var i = 0; i < d; i++) {
a[i] = String.fromCharCode(a[i] & 0xff, a[i] >>> 8 & 0xff, a[i] >>> 16 & 0xff, a[i] >>> 24 & 0xff);
}

return b ? a.join('').substring(0, c) : a.join('');
}


function _encode(s) {
if (arguments.length !== 1) {
throw "SyntaxError: exactly one argument required"
}
s = String(s);
var i, b10, x = [], imax = s.length - s.length % 3;
if (s.length === 0) {
return s
}
for (i = 0; i < imax; i += 3) {
b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8) | _getbyte(s, i + 2);
x.push(_ALPHA.charAt(b10 >> 18));
x.push(_ALPHA.charAt((b10 >> 12) & 63));
x.push(_ALPHA.charAt((b10 >> 6) & 63));
x.push(_ALPHA.charAt(b10 & 63))
}
switch (s.length - imax) {
case 1:
b10 = _getbyte(s, i) << 16;
x.push(_ALPHA.charAt(b10 >> 18) + _ALPHA.charAt((b10 >> 12) & 63) + _PADCHAR + _PADCHAR);
break;
case 2:
b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8);
x.push(_ALPHA.charAt(b10 >> 18) + _ALPHA.charAt((b10 >> 12) & 63) + _ALPHA.charAt((b10 >> 6) & 63) + _PADCHAR);
break
}
return x.join("")
}

function _getbyte(s, i) {
var x = s.charCodeAt(i);
if (x > 255) {
throw "INVALID_CHARACTER_ERR: DOM Exception 5"
}
return x
}
function info(data,token){
return _encode(encode(data,token));
}
"""


ctx = execjs.compile(info_code)

result = ctx.call("info",
data,
token)

return '{SRBX1}' + result


def getChksum(username, hmd5, token, ip, info):
str = token + username
str += token + hmd5
str += token + '0' # ac_id
str += token + ip
str += token + '200' # n
str += token + '1' # type
str += token + info
return hashlib.sha1(str.encode("utf-8")).hexdigest()


def getToken(username, ip,callback):
re_token = re.compile('"challenge":"([^"]+)"')
headers = {
'Accept': 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
# 'Cookie': 'lang=zh-CN',
'Pragma': 'no-cache',
'Referer': 'https://login.hdu.edu.cn/srun_portal_pc?ac_id=0&theme=pro',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
'sec-ch-ua': '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
}

params = {
'callback': callback+'_'+str(millis),
'username': username,
'ip': ip,
'_': millis+2,
}
session = requests.session()
response = session.get('https://login.hdu.edu.cn/cgi-bin/get_challenge', params=params,
headers=headers).text
return session, re_token.findall(response)[0]


def get_hmd5(password, token):
with open("./md5.js") as f:
js_code = f.read()
ctx = execjs.compile(js_code)
result = ctx.call("A", password, token)
return result


def login(session, username, password, chksum, info, ip,callback):
cookies = {
'lang': 'zh-CN',
}
headers = {
'Accept': 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
# 'Cookie': 'lang=zh-CN',
'Pragma': 'no-cache',
'Referer': 'https://login.hdu.edu.cn/srun_portal_pc?ac_id=0&theme=pro',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
'sec-ch-ua': '"Not A(Brand";v="99", "Google Chrome";v="121", "Chromium";v="121"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
}
params = {
'callback': callback+'_'+str(millis),
'action': 'login',
'username': username,
'password': "{MD5}" + password,
'os': 'Windows 10',
'name': 'Windows',
'double_stack': '0',
'chksum': chksum,
'info': info,
'ac_id': '0',
'ip': ip,
'n': '200',
'type': '1',
'_': millis+3,
}

response = session.get('https://login.hdu.edu.cn/cgi-bin/srun_portal', params=params, cookies=cookies,
headers=headers)

print(response.text)


if __name__ == '__main__':
ctx = execjs.compile('function test(){ return ("jQuery" + ("1.12.4" + Math.random()).replace(/\D/g, ""));}')
callback = ctx.call("test")
username = "xxxxxxx"
password = "xxxxx"
ip = "10.25.10.161"
data = '{"username":"' + username + '","password":"' + password + '","ip":"' + ip + '","acid":"0","enc_ver":"srun_bx1"}'
session, token = getToken("xxxxxxx", "10.25.10.161",callback)
info = getInfo(data, token)
hmd5 = get_hmd5(password, token)
chksum = getChksum(username, hmd5, token, ip, info)
login(session, username, hmd5, chksum, info, ip,callback)

md5()在js中传了两个参数,我不懂密码学,不知道这个应该调用哪个python函数,所以就把对应的js代码抠出来了。
最后可以达到运行脚本一键登录的效果,其实这个破脚本没啥卵用