xx查

声明

仅用于技术交流分享,严禁恶意利用,感谢大佬教学OrzOrz

正文


有个动态header,hook下http请求,XHR抓到的包可以用这个hook

代码片段导入运行,划取页面hook,点击继续运行至pid出现,再点下箭头就是动态加密串

查看前一个调用堆栈,p处已有,赋值给e,t,栈回溯追踪最后一次参数出现位置

一路跟踪到这,回到xx控案例的promise.then(.result/.reject)

打断点,hook脚本跳过一下,继续滑动刷新界面,程序断在设置好的断点这里,然后进去查看相关拦截器

1处reject,2处是t.exports的function引用,回到0处断点跟进

此时动态加密参数未出现,单步观察生成位置

范围减小至最后一个函数


刷新,跟进函数内部单步追踪

跟进查看i的生成

o.default:
charCodeAt()转ascii,一个换表

可以直接下断点console/copy(a)对象内容

再看a.default:

加盐的sha512

1
2
3
4
5
6
7
8
9
10
11
var CryptoJS = require("crypto-js");   
function HMACEncryption(message, key) {
return CryptoJS.HmacSHA512(message, key).toString(); // 128位
}
e="/api/home/getnewsflash?firstrankindex=&lastrankindex=1770346500208&lastranktime=1770346500208&pagesize=10{}"
t="iLAgiQ6rliBl4vl8kkiLkQBkgNk4NLvigvWlWl1iLk4NLvigvWlWlrkki6ANKiivi41iLk4NLvi4grllrkki6ANKiivi41ALBlkgkllriiLAgiQ6rliBl4vl8kkiLkQBkgNk4NLvigvWlWl1iLk4NLvigvWlWlrkki6ANKiivi41iLk4NLvi4grllrkki6ANKiivi41ALBlkgkllri"
res=HMACEncryption(e, t)
console.log(res.toString())
console.log(res.toString().length)
// aba89bc62ce1e7bad11f2c1710362ee0bd4bb915e52dfb6cf50b9848c3d4794425a74e50811dcc0ce878e962bf68844fdd8ca3cd5bf8152b3c0b4f07ba7d076f
// 128


完整解密
参数有变动,取对象时刷新了一下,重新取下用于解密校验

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
var CryptoJS = require("crypto-js");  

function HMACEncryption(message, key) {
return CryptoJS.HmacSHA512(message, key).toString(); // 128位
}
a =
{
"default": {
"n": 20,
"codes": {
"0": "W",
"1": "l",
"2": "k",
"3": "B",
"4": "Q",
"5": "g",
"6": "f",
"7": "i",
"8": "i",
"9": "r",
"10": "v",
"11": "6",
"12": "A",
"13": "K",
"14": "N",
"15": "k",
"16": "4",
"17": "L",
"18": "1",
"19": "8"
}
}
}
function enc()
{
for (var e = (arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "/").toLowerCase(), t = e + e, n = "", i = 0; i < t.length; ++i)
{
var o = t[i].charCodeAt() % a.default.n;
n += a.default.codes[o]
}
return n
}

e="/api/home/getnewsflash?firstrankindex=&lastrankindex=1770336575529&lastranktime=1770336575529&pagesize=10"

t=enc(e) //key生成
res=HMACEncryption(e + "{}", t).toLowerCase().substr(8,20) //注意是n+t
console.log(res.toString())
// a9e7722966e254b2adde

key:value,key有了,接着分析value

s.default:

window.tid个人理解类似根据浏览器等特性生成的指纹,固定不变用于反爬

r.default:

跟换表的地方一样,是个拼接


直接猜hmacsha256,不想看下去了

最后的解密脚本

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
var CryptoJS = require("crypto-js");  

function HMACEncryption(message, key) {
return CryptoJS.HmacSHA512(message, key).toString(); // 128位
}
a =
{
"default": {
"n": 20,
"codes": {
"0": "W",
"1": "l",
"2": "k",
"3": "B",
"4": "Q",
"5": "g",
"6": "f",
"7": "i",
"8": "i",
"9": "r",
"10": "v",
"11": "6",
"12": "A",
"13": "K",
"14": "N",
"15": "k",
"16": "4",
"17": "L",
"18": "1",
"19": "8"
}
}
}
function enc1()
{
for (var e = (arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "/").toLowerCase(), t = e + e, n = "", i = 0; i < t.length; ++i)
{
var o = t[i].charCodeAt() % a.default.n;
n += a.default.codes[o]
}
return n
}

function enc2()
{
var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}
, t = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : ""
, n = (arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "/").toLowerCase()
, i = JSON.stringify(e).toLowerCase();
return HMACEncryption(n+"pathString" + i + t,enc1(n))
}

str="/api/home/getnewsflash?firstrankindex=&lastrankindex=1770292572107&lastranktime=1770292572107&pagesize=10"
key=HMACEncryption(str + "{}", enc1(str)).toLowerCase().substr(8,20)
value=enc2(str,undefined,'6d56c773418f32926b76ce5ea9b69644')
console.log(key)
console.log(value)
// 94c37e63fb623335f64d
// 8cc8f825cd619acfb794353cca879bd59d65bd3de67b1e37ed0d3fe150107f76d316b11d55ee845d54860bfb22e2c774e564000e79f63d060224ca7e438df77e

小插曲

如果抓包的话可以发现这个参数加密不做校验😂😂


xx查
https://alenirving.github.io/2026/02/17/xx查/
作者
Ma5k
许可协议
CC-BY-NC-SA