免责声明:本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

逆向目标

逆向过程

无感验证属于极验验证码中最简单的了,w参数生成过程基本跟滑块,消消乐,五子棋,文字点选一致。如果看了前面的滑块,消消乐,文字点选等逆向过程,这个无感基本就是小儿科,并且之前生成w的代码只需稍加修改就可以直接拿来用。

看下e结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"device_id":"9f5faf6dc7a77e1d394c8634f0893812",
"lot_number":"89b5360c20ea4820b7c098bea3f291bf",
"pow_msg":"1|0|md5|2023-05-24T22:14:37.410573+08:00|54088bb07d2df3c46b79f80300b0abbe|89b5360c20ea4820b7c098bea3f291bf||f62dd1e38c706b4d",
"pow_sign":"6b5ebf3f4fd0e1223a5f93d80196715a",
"geetest":"captcha",
"lang":"zh",
"ep":"123",
"biht":"1426265548",
"em":{
"ph":0,
"cp":0,
"ek":"11",
"wd":1,
"nt":0,
"si":0,
"sc":0
}
}

与前面不同的是,没了userresponse和pastime,这点不难理解,既然是无感验证,自然不需要人工操作,而之前userresponse保存的要么是滑块的轨迹,要么是坐标,要么是位置比例。在无感验证里userresponse自然没有意义,没有人工操作的话,passtime也不需要。

直接贴一下全部的w生成的代码吧。如下:

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
const crypto = require('crypto');
const md5 = crypto.createHash('md5');
const CryptoJS = require('crypto-js');

const deviceId = "9f5faf6dc7a77e1d394c8634f0893812";


function s(lot_number, guid) {
const chapterId = "54088bb07d2df3c46b79f80300b0abbe";
const hashFunc = "md5";
const version = 1;
const bits = 0;
let _ = version + "|" + bits + "|" + hashFunc + "|" + new Date().toISOString() + "|" + chapterId + "|" + lot_number + "|" + "" + "|";
let l = _ + guid;
return {
"pow_msg": l,
"pow_sign": md5.update(l).digest('hex')
}
}

function uuid () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0;
var v = c === 'x' ? r : r & 0x3 | 0x8;
return v.toString(16);
});
};

function encrypt(word, key, iv) {
let src = CryptoJS.enc.Utf8.parse(word);
let encrypted = CryptoJS.AES.encrypt(src, CryptoJS.enc.Utf8.parse(key), { iv: CryptoJS.enc.Utf8.parse(iv), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
return encrypted.ciphertext;
}

function FvBQ(t) {
var e = 5381;
var n = t.length;
var o = 0;
while (n--) {
e = (e << 5) + e + t.charCodeAt(o++);
}
e &= ~(1 << 31);
return e;
}

function GRmF(t) {
t['e0vm'] = FvBQ(GRmF.toString() + FvBQ(FvBQ.toString())) + '';
return FvBQ(FvBQ.toString());
}

function get_e(lotNumber, guid) {
let e = {};
e["device_id"] = deviceId;
e["lot_number"] = lotNumber;
const pow = s(lotNumber, guid);
e["pow_msg"] = pow['pow_msg'];
e["pow_sign"] = pow['pow_sign'];
e["geetest"] = "captcha";
e["lang"] = "zh";
e["ep"] = "123";
e["e0vm"] = GRmF({
"geetest": "captcha",
"lang": "zh",
"ep": "123"
});
e["em"] = {
"ph": 0,
"cp": 0,
"ek": "11",
"wd": 1,
"nt": 0,
"si": 0,
"sc": 0
}
return e;
}

function get_w(lotNumber, guid) {
let e = get_e(lotNumber, guid);
let c = encrypt(JSON.stringify(e), guid, "0000000000000000");
let o = [];
for(let a = 0, i = c.sigBytes; a < i; a++) {
var u = c.words[a >>> 2] >>> 24 - a % 4 * 8 & 255;
o.push(u);
}
return arrayToHex(o)//, JSON.stringify(e);
}

function arrayToHex(e) {
for (var t = [], n = 0, s = 0; s < 2 * e["length"]; s += 2) t[s >>> 3] |= parseInt(e[n], 10) << 24 - s % 8 * 4, n++;
for (var r = [], i = 0; i < e["length"]; i++) {
var o = t[i >>> 2] >>> 24 - i % 4 * 8 & 255;
r["push"]((o >>> 4)["toString"](16)), r["push"]((15 & o)["toString"](16));
}
return r["join"]("");
}

运行与测试

image-20230524223353798

运行结果如上,无感验证通过率一定是100%。

若需要完整代码,扫描加微信。

image-20230517010053227