2021年2月4日

小小滑块可笑可笑-安卓滑块验证码通杀方案研究(2)

作者 huruwo

前言

之前讲到关于普通滑动无法通过的事实,后面我经过大量的额资料查验

搜索关键字包括

appium 验证码

selenium 验证码

有趣的是 有很多的验证码接入之后依然使用的是h5的方式,也就是网页端的那一套方案来校验。这就涉及到手机上操作h5页面这个东西了。

selenium与appium以及其他自动化对比分析

再说回来 关于自动化 有趣的是

python+selenium 和 python+appium 的对比方案

python+selenium

python+selenium的组合是可以再网页端应对网页的校验,关键在于selenium可以粒度化化的定制滑动路径。

高阶爬虫实战:破解极验滑动验证码

selenium + Chrome 滑动验证码破解三之京东 实现某东登录

def get_move_track(self, gap):
        track = []  # 移动轨迹
        current = 0  # 当前位移
        # 减速阈值
        mid = gap * 4 / 5  # 前4/5段加速 后1/5段减速
        t = 0.2  # 计算间隔
        v = 0  # 初速度
        while current < gap:
            if current < mid:
                a = random.uniform(2, 5)  # 加速度随机
            else:
                a = -(random.uniform(12.5, 13.5))  # 加速度随机,负数
            v0 = v  # 初速度v0
            v = v0 + a * t  # 当前速度
            move = v0 * t + 1 / 2 * a * t * t  # 移动距离
            current += move  # 当前位移
            track.append(round(move))  # 加入轨迹
        return track

    def move_slider(self, track):
        slider = self.driver.find_elements_by_xpath(r'//div[@class="JDJRV-slide-inner JDJRV-slide-btn"]')[0]
        ActionChains(self.driver).click_and_hold(slider).perform()
        for x in track:  # 只有水平方向有运动 按轨迹移动
            ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
        sleep(1)
        ActionChains(self.driver).release().perform()  # 松开鼠标

核心在于selenium在网页端确实可以做到模拟手各种速度变化的曲线抖动,这也是能过校验的核心所在。

重点在于预先的生成了一段 轨迹数组
然后在后面按照数组轨迹移动 且有意的sleep 1ms

这就形成了一个加速到减速的轨迹过程

python+appium

现在问题回到了手机端,作为类似的自动化框架appium。我们到底可以不可以做到这种粒度化在手机上呢。

又是一番搜索Appium 滑动验证码 终于找到了突破思路

如果我们也将整个滑动过程分成一段一段的小过程,且有意的控制滑动的持续时间为10ms

x方向上的位移越多也就是速度越快,且前面是个加速运动再到匀速再到减速。

找到了

def swipe(self, start_x, start_y, end_x, end_y, duration=None):
     # 从一个点滑动到另一个点,持续时间可选
        """Swipe from one point to another point, for an optional duration.

        :Args:
         - start_x - x-coordinate at which to start   开始的X轴
         - start_y - y-coordinate at which to start  开始的Y轴
         - end_x - x-coordinate at which to stop    结束的X轴
         - end_y - y-coordinate at which to stop    结束的Y轴
         - duration - (optional) time to take the swipe, in ms.   持续的时间,单位毫秒

        :Usage:
            driver.swipe(100, 100, 100, 400)
        """

两个关键的因素都是可控的:位移距离和持续时间

同理无障碍和adb滑动都存在两个控制参数

  • adb的swipe:
input swipe startX startY endX endY timeToSwipe
  • 无障碍的GestureDescription:
GestureDescription.StrokeDescription(path1, startTime, duration)

通用方案的核心--轨迹生成

既然可以控制速度了,现在的核心需求就是如何生成有效的一段轨迹。

你以为我会绞尽脑汁的想函数 模拟轨迹吗?

NONONO!!!

直接手写一个轨迹录制工具软件即可用生成的轨迹数组去模拟操作,我称之为回放路径。

总结

本章节通过对比两种不同的端对于滑块验证码的对抗策略,确定了核心在于轨迹的录制和回放。下面就是关于录制轨迹的部分。