用Rust破解极验验证码

极验验证码是一种广泛应用的滑动验证码系统,通过分析其加密和验证机制,我们可以模拟滑动操作并破解验证码。本文将详细介绍如何在Rust语言环境下实现这一过程。

一、观察verify请求
首先,我们需要观察verify请求的来源。在浏览器开发者工具中查看verify请求的发起者,可以发现它来自于gcaptcha4.js文件。由于该文件经过混淆处理,我们需要对其进行还原和分析。

二、AST还原混淆代码
为了便于调试和分析,我们使用AST(抽象语法树)还原混淆的JS文件。通过Chrome的reres插件替换混淆后的JS文件,我们可以在浏览器中加载还原后的代码进行调试。

三、定位w参数加密位置
通过对代码的分析和调试,可以确定w参数的加密位置。通过搜索关键字"w",可以找到相关代码并在适当位置打上断点,观察w参数的生成过程。

四、分析w参数加密算法
通过分析w参数的生成代码,可以简化为以下内容:

rust

let r = d.default(l.default.stringify(e), a);
其中,e是一个包含多个固定值和从请求响应中获取的数据的对象。通过进一步分析,可以确定e的组成如下:

rust

let e = json!({
    "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": lot_number,
    "passtime": passtime,
    "pow_msg": generate_pow_msg(&lot_number, passtime),
    "pow_sign": generate_pow_sign(&generate_pow_msg(&lot_number, passtime)),
    "setLeft": set_left,
    "track": track,
    "userresponse": user_response
});
五、Rust代码实现
下面是一个完整的Rust程序示例,它演示了如何生成滑动验证码所需的参数,并发送验证请求。

rust

use md5;
use rand::Rng;
use serde_json::json;
use std::time::{SystemTime, UNIX_EPOCH};

// 生成UUID
fn generate_challenge() -> String {
    let start = SystemTime::now();
    let since_the_epoch = start
        .duration_since(UNIX_EPOCH)
        .
rust

use md5;
use rand::Rng;
use serde_json::json;
use std::time::{SystemTime, UNIX_EPOCH};

// 生成UUID
fn generate_challenge() -> String {
    let start = SystemTime::now();
    let since_the_epoch = start
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards");
    let timestamp = since_the_epoch.as_millis().to_string();
    format!("{:x}", md5::compute(timestamp))
}

// 生成滑动轨迹
fn generate_track(distance: i32) -> Vec<(i32, i32, i32)> {
    let mut track = Vec::new();
    let mut current = 0;
    let mut rng = rand::thread_rng();

    while current < distance {
        let step = rng.gen_range(1..=5);
        current += step;
        track.push((step, rng.gen_range(0..=2), rng.gen_range(10..=20)));
    }
    track
}

// 计算滑动距离
fn get_set_left(track: &[(i32, i32, i32)]) -> i32 {
    track.iter().map(|(x, _, _)| *x).sum()
}

// 生成pow_msg
fn generate_pow_msg(lot_number: &str, passtime: i32) -> String {
    format!(
        "1|0|md5|2022-03-25T14:23:36.364152+08:00|24f56dc13c40dc4a02fd0318567caef5|{}||29f07cebf938aa4e",
        lot_number
    )
}

// 生成pow_sign
fn generate_pow_sign(pow_msg: &str) -> String {
    format!("{:x}", md5::compute(pow_msg))
}

fn main() {
    let captcha_id = "24f56dc13c40dc4a02fd0318567caef5";
    let challenge = generate_challenge();
    let client_type = "web";
    let risk_type = "slide";
    let lang = "zh";
    let callback = format!("geetest_{}", SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_millis());

    // 模拟加载请求
    let load_response = load_request(captcha_id, &challenge, client_type, risk_type, lang, &callback);
    let lot_number = load_response.get("lot_number").unwrap().as_str().unwrap();
    let bg_image = load_response.get("bg").unwrap().as_str().unwrap();
    let full_image = load_response.get("fullbg").unwrap().as_str().unwrap();

    // 分析背景图与完整图以确定滑块位置
    let set_left = analyze_image(bg_image, full_image);

    // 生成滑动轨迹
    let track = generate_track(set_left);
    let passtime = track.iter().map(|(_, _, t)| *t).sum();

    // 计算userresponse
    let user_response = set_left as f64 / (0.8876 * 340.0 / 300.0);

    // 构造w参数
    let w_param = json!({
        "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": lot_number,
        "passtime": passtime,
        "pow_msg": generate_pow_msg(lot_number, passtime),
        "pow_sign": generate_pow_sign(&generate_pow_msg(lot_number, passtime)),
        "setLeft": set_left,
        "track": track,
        "userresponse": user_response
    });

    // 发送验证请求
    let verify_response = verify_request(&w_param);
    println!("Verify Response: {}", verify_response);
}

// 示例函数:加载请求
fn load_request(
    _captcha_id: &str,
    _challenge: &str,
    _client_type: &str,
    _risk_type: &str,
    _lang: &str,
    _callback: &str,
) -> serde_json::Value {
    // 模拟发送请求并获取响应
    json!({
        "lot_number": "7e22264d4f3e4dd8a6ffbf6e82e1122d",
        "bg": "bg_image_data",
        "fullbg": "full_image_data",
    })
}

// 示例函数:分析图像
fn analyze_image(_bg_image: &str, _full_image: &str) -> i32 {
    // 简化的图像分析函数,返回假定的滑块位置
    88
}

// 示例函数:验证请求
fn verify_request(w_param: &serde_json::Value) -> String {
    // 模拟发送验证请求并获取响应
    println!("Sending Verify Request with wParam: {}", w_param.to_string());
    // 模拟响应
    "Success".to_string()
}

你可能感兴趣的:(rust,开发语言,后端)