使用JavaScript破解gcaptcha4.js中的w参数加密算法

在这篇文章中,我们将介绍如何使用JavaScript来逆向工程gcaptcha4.js文件,找到并破解w参数的加密算法。这个过程包括观察verify请求,定位加密位置,分析加密算法,最终还原w参数的明文。

一. 观察verify请求
首先,我们需要观察verify请求的发起者。在网络请求中,我们可以看到所有verify请求都来自于gcaptcha4.js文件。因此,这个文件成为我们分析的重点。

我们使用JavaScript的fetch API来捕获和分析这些请求。

javascript

fetch('https://example.com/verify')
    .then(response => response.text())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
通过分析响应内容,可以发现所有的verify请求都指向了gcaptcha4.js文件。

二. 定位w参数加密位置
为了找到w参数的加密位置,我们需要解析gcaptcha4.js文件。我们可以下载并格式化这个文件,然后使用正则表达式搜索关键词:w、.w、'w'或"w"。

javascript
const fs = require('fs');

fs.readFile('gcaptcha4.js', 'utf8', (err, data) => {
    if (err) {
        console.error(err);
        return;
    }
    const matches = data.match(/[\.\'\"]w[\.\'\"]/g);
    console.log(matches);
});
通过搜索"w",我们找到了相关代码。在第2527行,我们发现了w的值r在第2525行被定义。

三. 分析w参数加密算法
接下来,我们需要简化代码中w的定义。假设我们已经提取了相关的JavaScript代码,我们可以使用JavaScript来模拟这个过程。

javascript

const crypto = require('crypto');

function stringify(data) {
    return JSON.stringify(data);
}

function defaultEncrypt(data, key) {
    const hash = crypto.createHash('md5');
    hash.update(data + key);
    return hash.digest('hex');
}

// 示例数据
const e = { /* your data */ };
const a = 'your_key';

const r = defaultEncrypt(stringify(e), a);
console.log(r);
首先,stringify(e)相当于对e进行JSON序列化操作。然后,我们分析defaultEncrypt(stringify(e), a)的含义。

javascript

function encrypt(e, t) {
    const n = generateGuid();
    let a = encryptor.encrypt(n);
    while (!a || a.length !== 256) {
        n = generateGuid();
        a = encryptor.encrypt(n);
    }
    const o = encryptor.encrypt(e, n);
    return arrayToHex(o) + a;
}

function generateGuid() {
    return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        const r = Math.random() * 16 | 0,
            v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function arrayToHex(input) {
    return input.reduce((acc, val) => acc + val.toString(16), '');
}

// 示例数据
const e = 'example_data';
const t = 'example_key';

const result = encrypt(e, t);
console.log(result);
从这里可以确定参数t未被使用,参数e就是w的明文。接着我们分析e的组成部分:

javascript

const e = {
    'device_id': 'A8A0',  // 固定值
    'em': { 
        'cp': 0,
        'ek': '11',
        'nt': 0,
        'ph': 0,
        'sc': 0,
        'si': 0,
        'wd': 1,
    },  // 固定值
    'ep': '123',  // 固定值
    'geetest': 'captcha',  // 固定值
    'fq6a': '1925502591',  // 固定值
    'lang': 'zh',  // 固定值
    'lot_number': '7e22264d4f3e4dd8a6ffbf6e82e1122d',  // load请求返回值
    'passtime': 166,  // 通过时间
    'pow_msg': '1|0|md5|2022-03-25T14:23:36.364152+08:00|24f56dc13c40dc4a02fd0318567caef5|7e22264d4f3e4dd8a6ffbf6e82e1122d||29f07cebf938aa4e',  // load请求返回加上某算法返回值
    'pow_sign': '2b47a3a9425dd19dd5abf902c8bb0763',  // pow_msg的md5值
    'setLeft': 88,  // 滑动距离
    'track': [[38, 18, 0], [1, 0, 33]......],  // 轨迹
    'userresponse': 87.47978686742837  // 某算法返回值
};
4.1 分析pow_msg和pow_sign
通过搜索pow_msg,我们找到相关代码并解析如下:

javascript

function generateGuid() {
    return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        const r = Math.random() * 16 | 0,
            v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function md5(input) {
    return crypto.createHash('md5').update(input).digest('hex');
}

const n = 'example_n';
const a = 'example_a';
const s = 'example_s';
const o = 'example_o';
const t = 'example_t';
const e = 'example_e';
const r = 'example_r';

const u = `${n}|${a}|${s}|${o}|${t}|${e}|${r}|`;
const p = generateGuid();
const g = u + p;
const pow_msg = u + p;
const pow_sign = md5(g);

console.log('pow_msg:', pow_msg);
console.log('pow_sign:', pow_sign);
4.2 分析set_left、track、passtime、userresponse
set_left:滑块移动距离的整数值
track:移动轨迹,从第二步开始,是相对上一步的相对移动距离(x, y, t)
passtime:总移动时间
userresponse:计算公式为set_left / (0.8876 * 340 / 300)
javascript

const set_left = 88;
const track = [[38, 18, 0], [1, 0, 33]......];
const passtime = 166;
const userresponse = set_left / (0.8876 * 340 / 300);

console.log('set_left:', set_left);
console.log('track:', track);
console.log('passtime:', passtime);
console.log('userresponse:', userresponse);
至此,我们已经完成了w参数的明文解析。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值