极验滑块验证码破解与研究(三):滑块缺口识别

声明

原创文章,请勿转载!

本文内容仅限于安全研究,不公开具体源码。维护网络安全,人人有责。

本文关联文章超链接:

  1. 极验滑块验证码破解与研究(一):AST还原混淆JS
  2. 极验滑块验证码破解与研究(二):缺口图片还原
  3. 极验滑块验证码破解与研究(三):滑块缺口识别
  4. 极验滑块验证码破解与研究(四):滑块轨迹构造
  5. 极验滑块验证码破解与研究(五):请求分析及加密参数破解

一、环境安装

1. 第三方库安装

pip install Pillow
pip install numpy
pip install opencv-python

二、滑块缺口识别

滑块缺口识别功能的实现还是比较简单的,小编冗余一些工具函数,方便不同的场景使用。

1. 准备工作

首先我们需要准备两张图片:1. 带缺口的背景图;2. 与之对应的接口图。
缺口图片还原方式请看 极验滑块验证码破解与研究(二):缺口图片还原
在这里插入图片描述在这里插入图片描述

2. 工具函数说明

这些工具函数主要是图片格式的相互转换功能。大家知道PIL是以RGB格式打开的图片<type ‘PIL.JpegImagePlugin.JpegImageFile’>,cv2是以BGR格式打开的图片<type ‘np.ndarray’>。我们从网页下载图片通常是bytes格式。因此,我们需要准备一些图片格式相互转换的工具函数,方便测试和上线。

# -*- coding: utf-8 -*-
from pathlib import Path

import PIL
import cv2
import numpy as np


def imshow(img, winname='test', delay=0):
    """cv2展示图片"""
    cv2.imshow(winname, img)
    cv2.waitKey(delay)
    cv2.destroyAllWindows()


def pil_to_cv2(img):
    """
    pil转cv2图片
    :param img: pil图像, <type 'PIL.JpegImagePlugin.JpegImageFile'>
    :return: cv2图像, <type 'numpy.ndarray'>
    """
    img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
    return img


def bytes_to_cv2(img):
    """
    二进制图片转cv2
    :param img: 二进制图片数据, <type 'bytes'>
    :return: cv2图像, <type 'numpy.ndarray'>
    """
    # 将图片字节码bytes, 转换成一维的numpy数组到缓存中
    img_buffer_np = np.frombuffer(img, dtype=np.uint8)
    # 从指定的内存缓存中读取一维numpy数据, 并把数据转换(解码)成图像矩阵格式
    img_np = cv2.imdecode(img_buffer_np, 1)
    return img_np


def cv2_open(img, flag=None):
    """
    统一输出图片格式为cv2图像, <type 'numpy.ndarray'>
    :param img: <type 'bytes'/'numpy.ndarray'/'str'/'Path'/'PIL.JpegImagePlugin.JpegImageFile'>
    :param flag: 颜色空间转换类型, default: None
        eg: cv2.COLOR_BGR2GRAY(灰度图)
    :return: cv2图像, <numpy.ndarray>
    """
    if isinstance(img, bytes):
        img = bytes_to_cv2(img)
    elif isinstance(img, (str, Path)):
        img = cv2.imread(str(img))
    elif isinstance(img, np.ndarray):
        img = img
    elif isinstance(img, PIL.Image):
        img = pil_to_cv2(img)
    else:
        raise ValueError(f'输入的图片类型无法解析: {type(img)}')
    if flag is not None:
        img = cv2.cvtColor(img, flag)
    return img

3. 接口识别原理讲解

首先使用上面介绍的工具函数,以灰度图方式读取背景图和缺口图

bg_gray = cv2_open(bg, flag=cv2.COLOR_BGR2GRAY)
tp_gray = cv2_open(tp, flag=cv2.COLOR_BGR2GRAY)

在这里插入图片描述

接下来,使用cv2的边缘检测功能,检测背景图和缺口图的边缘,阀值大小可以自己调整哦。

tp_gray = cv2.Canny(tp_gray, 255, 255)
bg_gray = cv2.Canny(bg_gray, 255, 255)

在这里插入图片描述在这里插入图片描述

使用cv2的目标检测函数,得到相似度最高的坐标,坐标的x值就是滑动验证码需要滑动的距离

# 目标匹配
result = cv2.matchTemplate(bg_gray, tp_gray, cv2.TM_CCOEFF_NORMED)
# 解析匹配结果
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
distance = max_loc[0]

在这里插入图片描述

4. 缺口识别完整代码

# -*- coding: utf-8 -*-
from pathlib import Path

import PIL
import cv2
import numpy as np


def imshow(img, winname='test', delay=0):
    """cv2展示图片"""
    cv2.imshow(winname, img)
    cv2.waitKey(delay)
    cv2.destroyAllWindows()


def pil_to_cv2(img):
    """
    pil转cv2图片
    :param img: pil图像, <type 'PIL.JpegImagePlugin.JpegImageFile'>
    :return: cv2图像, <type 'numpy.ndarray'>
    """
    img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
    return img


def bytes_to_cv2(img):
    """
    二进制图片转cv2
    :param img: 二进制图片数据, <type 'bytes'>
    :return: cv2图像, <type 'numpy.ndarray'>
    """
    # 将图片字节码bytes, 转换成一维的numpy数组到缓存中
    img_buffer_np = np.frombuffer(img, dtype=np.uint8)
    # 从指定的内存缓存中读取一维numpy数据, 并把数据转换(解码)成图像矩阵格式
    img_np = cv2.imdecode(img_buffer_np, 1)
    return img_np


def cv2_open(img, flag=None):
    """
    统一输出图片格式为cv2图像, <type 'numpy.ndarray'>
    :param img: <type 'bytes'/'numpy.ndarray'/'str'/'Path'/'PIL.JpegImagePlugin.JpegImageFile'>
    :param flag: 颜色空间转换类型, default: None
        eg: cv2.COLOR_BGR2GRAY(灰度图)
    :return: cv2图像, <numpy.ndarray>
    """
    if isinstance(img, bytes):
        img = bytes_to_cv2(img)
    elif isinstance(img, (str, Path)):
        img = cv2.imread(str(img))
    elif isinstance(img, np.ndarray):
        img = img
    elif isinstance(img, PIL.Image):
        img = pil_to_cv2(img)
    else:
        raise ValueError(f'输入的图片类型无法解析: {type(img)}')
    if flag is not None:
        img = cv2.cvtColor(img, flag)
    return img


def get_distance(bg, tp, im_show=False, save_path=None):
    """
    :param bg: 背景图路径或Path对象或图片二进制
        eg: 'assets/bg.jpg'
            Path('assets/bg.jpg')
    :param tp: 缺口图路径或Path对象或图片二进制
        eg: 'assets/tp.jpg'
            Path('assets/tp.jpg')
    :param im_show: 是否显示结果, <type 'bool'>; default: False
    :param save_path: 保存路径, <type 'str'/'Path'>; default: None
    :return: 缺口位置
    """
    # 读取图片
    bg_gray = cv2_open(bg, flag=cv2.COLOR_BGR2GRAY)
    tp_gray = cv2_open(tp, flag=cv2.COLOR_BGR2GRAY)
    # 边缘检测
    tp_gray = cv2.Canny(tp_gray, 255, 255)
    bg_gray = cv2.Canny(bg_gray, 255, 255)
    # 目标匹配
    result = cv2.matchTemplate(bg_gray, tp_gray, cv2.TM_CCOEFF_NORMED)
    # 解析匹配结果
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

    distance = max_loc[0]
    if save_path or im_show:
        # 需要绘制的方框高度和宽度
        tp_height, tp_width = tp_gray.shape[:2]
        # 矩形左上角点位置
        x, y = max_loc
        # 矩形右下角点位置
        _x, _y = x + tp_width, y + tp_height
        # 绘制矩形
        bg_img = cv2_open(bg)
        cv2.rectangle(bg_img, (x, y), (_x, _y), (0, 0, 255), 2)
        # 保存缺口识别结果到背景图
        if save_path:
            save_path = Path(save_path).resolve()
            save_path = save_path.parent / f"{save_path.stem}.{distance}{save_path.suffix}"
            save_path = save_path.__str__()
            cv2.imwrite(save_path, bg_img)
        # 显示缺口识别结果
        if im_show:
            imshow(bg_img)
    return distance


if __name__ == '__main__':
    d = get_distance(
        bg='assets/bg.jpg',
        tp='assets/tp.png',
        im_show=True,
        save_path='assets/bg.jpg'
    )
    print(d)

三、结语

友情链接:极验滑块验证码破解与研究(四):滑块轨迹构造

本期文章结束啦,如果对您有帮助,记得收藏加关注哦,后期文章会持续更新 ~~~

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值