1. 初步观察与请求分析
首先,我们需要通过浏览器开发者工具观察滑动验证码的工作流程。通常会有以下几个关键请求:
gettype.php: 获取核心 JS 文件链接。
get.php: 无感验证的一部分,收集浏览器信息并上报。c 和 s 参数比较关键,后续的请求会用到它们。
ajax.php: 执行无感验证。如果验证失败,会返回验证类型,如滑块验证、点选验证等。
slide.x.x.x.js: 正式进入滑动验证部分,加载相关 JS 文件。
get.php: 获取滑动验证的一些基本数据,如 bg, c, challenge, fullbg, gt, slice, s。
ajax.php: 执行滑动验证,成功后返回 validate。
2. 解析关键参数
在这些请求中,gt 和 challenge 是非常重要的参数。gt 是一个定值,是和极验申请的 ID。challenge 是一个行为的 ID,每次操作会生成一个新的 challenge。
最关键的是 w 参数,它是一段被加密的数据,校验通过与否的核心。我们的目标是破解这个 w 参数。
3. 破解 w 参数
首先在本地代码中搜索 w 参数的生成过程,然后设置一个断点,以便在代码执行时进行调试。
javascript
// 假设我们找到以下生成 w 参数的代码
let w = generateW(params);
// 我们需要找到 generateW 函数的实现
4. 观察 w 参数的生成过程
通过断点调试,我们发现 w 参数由两个部分组成,每个部分有独特的构造逻辑。我们将不变的逻辑单独拿出来,变动的部分进行破解。
4.1 破解 u 参数
javascript
更多内容联系1436423940
// 生成随机文本的辅助函数
function getRandomTextHelper() {
const helper = () => ((65536 * (1 + Math.random())) | 0).toString(16).substring(1);
return helper() + helper() + helper() + helper();
}
// 随机值的缓存
let oldRandomText = getRandomTextHelper();
// 生成随机文本
function getRandomText(needRefresh) {
if (needRefresh) {
oldRandomText = getRandomTextHelper();
}
return oldRandomText;
}
// 获取 u 参数
function getU() {
const U = new UClass(); // UClass 是我们从代码中提取出来的加密类
let e = U.encrypt(getRandomText());
while (!e || e.length !== 256) {
e = U.encrypt(getRandomText(true));
}
return e;
}
4.2 破解 h 参数
javascript
// 生成 h 参数
function getH(l) {
return GGC(l); // GGC 是我们从代码中提取出来的函数
}
// 生成 l 参数
function getL(params) {
const V = new VClass(); // VClass 是我们从代码中提取出来的加密类
const o = {
lang: 'zh-cn',
userresponse: H(params.t, params.challenge),
passtime: params.n,
imgload: Math.floor(Math.random() * 50 + 30),
aa: getAA(params.e, params.c, params.s),
ep: {
v: '7.8.8',
$_BIQ: false,
me: true,
tm: -1,
td: -1
}
};
return V.encrypt(stringify(o), getRandomText());
}
4.3 生成轨迹数据
javascript
function generateSlideTrace(distance) {
const trace = [
[random(-50, -10), random(-50, -10), 0],
[0, 0, 0]
];
const count = 30 + Math.floor(distance / 2);
let t = random(50, 100);
let lastX = 0;
let lastY = 0;
let lastYCount = 0;
for (let i = 0; i < count; i++) {
const x = Math.round(i === count ? 1 : (1 - Math.pow(2, (-10 * i) / count)) * distance);
t += random(10, 20);
if (x === lastX) continue;
lastYCount += 1;
if (lastYCount > random(5, 10)) {
lastYCount = 0;
lastY = random(-2, 2);
}
lastX = x;
trace.push([x, lastY, t]);
}
return trace;
}
5. 合并 u 和 h
javascript
// 计算 w 参数
function getSlideW(props) {
return getSlideLeft(props) + getRight();
}
function getSlideLeft(props) {
return encodeLeft(getL(props));
}
function getRight() {
let e = new UClass().encrypt(getRandomText());
while (!e || e.length !== 256) {
e = new UClass().encrypt(getRandomText(true));
}
return e;
}
// 假设我们已经提取出 encodeLeft, UClass, VClass, H, getAA, stringify 等函数
6. 构造请求
最后,我们按照上述步骤构造请求,使用合适的参数发出对应的请求即可。大致的顺序为:ajax.php -> get.php -> 计算参数 -> ajax.php -> 验证成功!
javascript
async function verifyCaptcha() {
const response = await fetch('https://example.com/get.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
gt: 'YOUR_GT_VALUE',
challenge: 'YOUR_CHALLENGE_VALUE',
w: getSlideW({
c: 'YOUR_C_VALUE',
s: 'YOUR_S_VALUE',
trace: generateSlideTrace(YOUR_SLIDE_DISTANCE),
challenge: 'YOUR_CHALLENGE_VALUE'
})
})
});
const result = await response.json();
if (result.success) {
console.log('Verification successful!');
} else {
console.log('Verification failed.');
}
}
verifyCaptcha();