深入解析数美滑块验证码破解:从抓包到实现(C#版)

数美滑块验证码是一种常见的安全验证方式,用于防止自动化脚本和机器人进行恶意操作。本文将详细介绍如何通过抓包获取滑块图片信息、分析加密参数、生成滑动轨迹等步骤,成功破解数美滑块验证码。以下是我们要实现的主要步骤:

抓取滑块图片信息并计算滑动距离
分析加密参数
生成滑动轨迹并进行DES加密
验证破解结果
1. 抓取滑块图片信息并计算滑动距离
首先,进入数美滑块验证码的演示页面,进行抓包操作以获取滑块验证码的前景和背景图片。我们通过HttpClient从网站获取图片:

csharp

using System;
using System.Net.Http;
using System.Threading.Tasks;
using OpenCvSharp;
using Newtonsoft.Json.Linq;

public class CaptchaBreaker
{
    private static readonly HttpClient client = new HttpClient();

    public static async Task Main(string[] args)
    {
        string registerUrl = "https://www.ishumei.com/trial/captcha.html";
        var images = await GetImagesAsync(registerUrl);
        Mat fg = images.Item1;
        Mat bg = images.Item2;
        int distance = GetDistance(fg, bg);

        Console.WriteLine("Calculated distance: " + distance);
    }

    public static async Task<Tuple<Mat, Mat>> GetImagesAsync(string registerUrl)
    {
        var response = await client.PostAsync(registerUrl, new StringContent("{}"));
        string responseBody = await response.Content.ReadAsStringAsync();

        // 假设返回的JSON包含前景和背景图片URL
        string fgUrl = ParseImageUrl(responseBody, "fg");
        string bgUrl = ParseImageUrl(responseBody, "bg");

        Mat fgImage = await DownloadImageAsync(fgUrl);
        Mat bgImage = await DownloadImageAsync(bgUrl);

        return Tuple.Create(fgImage, bgImage);
    }

    public static string ParseImageUrl(string json, string key)
    {
        var jsonObj = JObject.Parse(json);
        return jsonObj[key].ToString();
    }

    public static async Task<Mat> DownloadImageAsync(string imageUrl)
    {
        var response = await client.GetAsync(imageUrl);
        byte[] imageBytes = await response.Content.ReadAsByteArrayAsync();
        return Cv2.ImDecode(imageBytes, ImreadModes.Color);
    }

    public static int GetDistance(Mat fg, Mat bg)
    {
        Mat result = new Mat();
        Cv2.MatchTemplate(fg, bg, result, TemplateMatchModes.CCoeffNormed);
        Cv2.MinMaxLoc(result, out _, out _, out _, out Point maxLoc);
        return (int)maxLoc.X;
    }
}
2. 分析加密参数
在滑动滑块的过程中,我们需要分析加密参数。抓包查看请求信息,可以看到有一个fverify的验证信息。如果正确的话,riskLevel返回值为PASS,失败为REJECT。

通过在浏览器中设置断点,我们可以找到参数aw等的生成函数,并确定这些参数的加密方式。使用断点调试后,发现是通过DES加密。

以下是通过System.Security.Cryptography库实现DES加密的示例代码:

csharp

using System;
using System.Security.Cryptography;
using System.Text;

public class DESEncryption
{
    public static void Main(string[] args)
    {
        string message = "Hello, World!";
        string key = "your_key_here";
        bool flag = true;

        string encryptedMessage = EncryptContent(message, key, flag);
        Console.WriteLine("Encrypted message: " + encryptedMessage);
    }

    public static string Pad(string data)
    {
        int blockSize = 8;
        int paddingSize = blockSize - (data.Length % blockSize);
        return data + new string('\0', paddingSize);
    }

    public static string EncryptContent(string message, string key, bool flag)
    {
        using (var des = DES.Create())
        {
            des.Mode = CipherMode.ECB;
            des.Padding = PaddingMode.None;
            des.Key = Encoding.UTF8.GetBytes(key);

            var transform = flag ? des.CreateEncryptor() : des.CreateDecryptor();
            byte[] paddedMessage = Encoding.UTF8.GetBytes(Pad(message.Replace(" ", "")));
            byte[] result = transform.TransformFinalBlock(paddedMessage, 0, paddedMessage.Length);
            return Convert.ToBase64String(result);
        }
    }
}
3. 生成滑动轨迹并进行DES加密
滑动轨迹可以通过模拟人的滑动行为来生成,包括一些随机的抖动和速度变化。以下是生成滑动轨迹的示例代码:

csharp

using System;
using System.Collections.Generic;

public class SlideTrackGenerator
{
    public static void Main(string[] args)
    {
        int distance = 100; // 假设滑动距离为100
        var track = GetRandom(distance);

        foreach (var step in track)
        {
            Console.WriteLine($"x: {step[0]}, y: {step[1]}, t: {step[2]}");
        }
    }

    public static List<int[]> GetRandom(int distance)
    {
        var track = new List<int[]>();
        track.Add(new int[] { 0, 0, 0 });
        var random = new Random();

        for (int i = 0; i < 10; i++)
        {
            int x = 0;
            int y = random.Next(3) - 1;
            int t = 100 * (i + 1) + random.Next(3);
            track.Add(new int[] { x, y, t });
        }

        for (int i = 1; i < track.Count - 5; i++)
        {
            track[i][0] = distance / 2;
        }

        for (int i = track.Count - 5; i < track.Count - 1; i++)
        {
            track[i][0] = distance + random.Next(4);
        }

        track[track.Count - 1][0] = distance;
        return track;
    }
}
4. 验证破解结果
最后,结合前面的步骤,实现滑块破解。以下是完整的示例代码:

csharp

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using OpenCvSharp;
using System.Security.Cryptography;

public class CaptchaBreaker
{
    private static readonly HttpClient client = new HttpClient();

    static CaptchaBreaker()
    {
        Cv2.SetUseOptimized(true);
    }

    public static async Task Main(string[] args)
    {
        string registerUrl = "https://www.ishumei.com/trial/captcha.html";
        var images = await GetImagesAsync(registerUrl);
        Mat fg = images.Item1;
        Mat bg = images.Item2;
        int distance = GetDistance(fg, bg);
        var track = GetRandom(distance);

        string nm = JsonConvert.SerializeObject(track);
        string dy = track[track.Count - 1][2].ToString();

        string key = "your_key_here";
        bool flag = true;

        string encryptedNm = EncryptContent(nm, key, flag);
        string encryptedDy = EncryptContent(dy, key, flag);

        var verifyData = new Dictionary<string, string>
        {
            { "nm", encryptedNm },
            { "dy", encryptedDy },
            { "rid", "register_id_here" },
            { "dl", distance.ToString() }
        };

        string json = JsonConvert.SerializeObject(verifyData);

        var request = new HttpRequestMessage(HttpMethod.Post, "https://www.ishumei.com/trial/fverify")
        {
            Content = new StringContent(json, Encoding.UTF8, "application/json")
        };

        var response = await client.SendAsync(request);
        string responseBody = await response.Content.ReadAsStringAsync();
        var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseBody);

        if (result["riskLevel"] == "PASS")
        {
            Console.WriteLine("验证成功");
        }
        else
        {
            Console.WriteLine("验证失败");
        }
    }

    public static async Task<Tuple<Mat, Mat>> GetImagesAsync(string registerUrl)
    {
        var response = await client.PostAsync(registerUrl, new StringContent("{}"));
        string responseBody = await response.Content.ReadAsStringAsync();

        string fgUrl = ParseImageUrl(responseBody, "fg");
        string bgUrl = ParseImageUrl(responseBody, "bg");

        Mat fgImage = await DownloadImageAsync(fgUrl);
        Mat bgImage = await DownloadImageAsync(bgUrl);

        return Tuple.Create(fgImage, bgImage);
    }

    public static string ParseImageUrl(string json, string key)
    {
        var jsonObj = JObject.Parse(json);
        return jsonObj[key].ToString();
    }

    public static async Task<Mat> DownloadImageAsync(string imageUrl)
    {
        var response = await client.GetAsync(imageUrl);
        byte[] imageBytes = await response.Content.ReadAsByteArrayAsync();
        return Cv2.ImDecode(imageBytes, ImreadModes.Color);
    }

    public static int GetDistance(Mat fg, Mat bg)
    {
        Mat result = new Mat();
        Cv2.MatchTemplate(fg, bg, TemplateMatchModes.CCoeffNormed);
        Cv2.MinMaxLoc(result, out _, out _, out _, out Point maxLoc);
        return (int)maxLoc.X;
    }

    public static List<int[]> GetRandom(int distance)
    {
        var track = new List<int[]>();
        track.Add(new int[] { 0, 0, 0 });
        var random = new Random();

        for (int i = 0; i < 10; i++)
        {
            int x = 0;
            int y = random.Next(3) - 1;
            int t = 100 * (i + 1) + random.Next(3);
            track.Add(new int[] { x, y, t });
        }

        for (int i = 1; i < track.Count - 5; i++)
        {
            track[i][0] = distance / 2;
        }

        for (int i = track.Count - 5; i < track.Count - 1; i++)
        {
            track[i][0] = distance + random.Next(4);
        }

        track[track.Count - 1][0] = distance;
        return track;
    }

    public static string Pad(string data)
    {
        int blockSize = 8;
        int paddingSize = blockSize - (data.Length % blockSize);
        return data + new string('\0', paddingSize);
    }

    public static string EncryptContent(string message, string key, bool flag)
    {
        using (var des = DES.Create())
        {
            des.Mode = CipherMode.ECB;
            des.Padding = PaddingMode.None;
            des.Key = Encoding.UTF8.GetBytes(key);

            var transform = flag ? des.CreateEncryptor() : des.CreateDecryptor();
            byte[] paddedMessage = Encoding.UTF8.GetBytes(Pad(message.Replace(" ", "")));
            byte[] result = transform.TransformFinalBlock(paddedMessage, 0, paddedMessage.Length);
            return Convert.ToBase64String(result);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值