JS逆向 - 数美滑块验证码逆向分析

文章旨在学习和记录,若有侵权,请联系删除

文章目录

  • 前言
  • 一、请求分析
  • 二、参数逆向
  • 三、模拟轨迹
  • 四、请求验证
  • 总结


前言

数美验证码的应用非常广泛,像某书、某街就是使用了数美滑块来进行风控的,当爬虫没有使用代理ip、ip质量比较差或者单个代理ip使用次数过多的时候,就会出现滑块验证码,严重的时候还会出现无限滑块的情况。

那么我们通过官网的示例,来分析下数美滑块的流程,并使用协议来通过数美滑块的验证。

目标网址:https://www.ishumei.com/trial/captcha.html
目标特点:ob混淆、环境检测、轨迹模拟


一、请求分析

  1. 抓包分析
    拖动滑块,主要的请求流程如下:
    JS逆向 - 数美滑块验证码逆向分析_第1张图片

  2. 验证码注册
    该接口主要用于验证码注册,请求参数基本上都是固定的,然后在响应中有三个需要重点关注的地方,分别是背景图片、滑块图片、验证图片绑定的rid,先将他们保存下来。JS逆向 - 数美滑块验证码逆向分析_第2张图片

  3. 请求验证

    在请求验证接口中,有三个重要的加密参数,这三个参数是分别对 滑动距离比例、滑动耗时、鼠标轨迹 进行加密的结果,使用协议请求时需要对这三个参数进行逆向,并构造出来。
    JS逆向 - 数美滑块验证码逆向分析_第3张图片


    验证通过,响应返回 PASS,表示滑动通过了验证码。
    JS逆向 - 数美滑块验证码逆向分析_第4张图片


    验证失败,响应返回 REJECT,表明参数有误,或者轨迹没通过验证。
    JS逆向 - 数美滑块验证码逆向分析_第5张图片

    那么,我们下面来分析加密参数 lm、fg、fm 生成的位置,以及如何构造。

二、参数逆向

  1. 参数定位
    通过initiator定位js文件,由于网站使用了定时函数,断点断在发请求出的话堆栈不好跟踪,所以可以选择在setTimeout函数前的每个堆栈都下一个断点,观察下加密参数最早在哪边出现的。
    JS逆向 - 数美滑块验证码逆向分析_第6张图片

    可以发现,在倒数第二个断点处发现了所有参数都已经生成了,可以推断就是在这个函数断点前面某个地方生成的加密参数。

    那么全局搜索一下这个变量,看下是在哪里进行赋值的。接着搜索定位到了变量赋值的地方,是通过调用this[_0x416bd9(0x937)]()函数来生成的加密对象,继续追进函数里面,看下这个函数是如何进行加密的。
    JS逆向 - 数美滑块验证码逆向分析_第7张图片

    由下图可知,加密参数的生成位置出来了,同时加密函数 _0x84c366 的声明也是在下面,很棒。
    仔细分析下代码,加密函数主要就是使用了对称加密算法des来进行加密,同时也能清晰的观察到传入的参数和密钥,简化出来的目标参数生成逻辑伪代码如下:

    lm = des(横向滑动距离/300, 密钥)
    fm = des(轨迹数组, 密钥)
    fg = des(开始时间-结束时间, 密钥)
    
  2. 算法还原
    用python代码来实现des加密:

    import base64
    from Crypto.Cipher import DES
    
    def des_encrypt(key, text):
    	"""des加密计算"""
        cipher = DES.new(key.encode('utf-8'), DES.MODE_ECB)
        text = text.replace(' ', '').encode()
        block_size = 8
        while len(text) % block_size:
            text += b'\0'
        encrypted_text = cipher.encrypt(text)
        return base64.b64encode(encrypted_text).decode('utf-8')
        
    

三、模拟轨迹

  1. 识别图片、计算距离
    这边使用OpenCV来识别图片,计算滑动距离。(也可以使用深度学习的方式,采集大量数美的背景图和滑块图作为训练材料,使用pytorch进行回归模型训练,将图像数据映射到用户滑动的距离上,这种方式的识别准确率相对来说会高一些)
    import cv2
    import numpy as np
    from io import BytesIO
    
    def get_distance(fg_resp, bg_resp):
        """计算滑动距离"""
        # 1. 将背景图、滑块图的二进制响应体转为BytesIO对象
        bg = BytesIO(bg_resp.content)
        fg = BytesIO(fg_resp.content)
        # 2. 使用imdecode进行图像解码,转成OpenCV中的Mat对象
        target = cv2.imdecode(np.asarray(bytearray(fg.read()), dtype=np.uint8), 0)
        template = cv2.imdecode(np.asarray(bytearray(bg.read()), dtype=np.uint8), 0)
        # 3. 使用matchTemplate方法进行模板匹配,返回背景图中与滑块的位置匹配值数组
        result = cv2.matchTemplate(target, template, cv2.TM_CCORR_NORMED)
        # 4. 使用numpy中的unravel_index函数获取result中位置匹配值最大的索引位置,既是滑动的距离
        _, distance = np.unravel_index(result.argmax(), result.shape)
        return distance
        
    
  2. 轨迹模拟
    生成轨迹的方法很多,此处分享一个通过加速度来模拟生成轨迹的方法
    def get_random_tracks(distance):
        """生成轨迹"""
        tracks = []
    
        y = 0
        v = 0
        t = 1
        current = 0
        mid = distance * 3 / 4
        exceed = 20
        z = t
    
        tracks.append([0, 0, 1])
    
        while current < (distance + exceed):
            if current < mid / 2:
                a = 15
            elif current < mid:
                a = 20
            else:
                a = -30
            a /= 2
            v0 = v
            s = v0 * t + 0.5 * a * (t * t)
            current += int(s)
            v = v0 + a * t
    
            y += random.randint(-5, 5)
            z += 100 + random.randint(0, 10)
    
            tracks.append([min(current, (distance + exceed)), y, z])
    
        while exceed > 0:
            exceed -= random.randint(0, 5)
            y += random.randint(-5, 5)
            z += 100 + random.randint(0, 10)
            tracks.append([min(current, (distance + exceed)), y, z])
    
        return tracks
    
    

四、请求验证

JS逆向 - 数美滑块验证码逆向分析_第8张图片
如图,滑动成功率还是ok的。

总结

  1. 数美验证码的数据包请求流程还是挺清晰的,比较好分析。
  2. 数美的版本迭代会比较频繁,每次迭代一般都会改变加密参数des的密钥,可以尝试通过正则来匹配最新的密钥参数。
  3. 如果想要追求更高的通过率的话,可以进一步优化下图像识别和轨迹模拟这两方面。完。

你可能感兴趣的:(python,爬虫,网络安全)