怼就完事了,总结几种验证码的解决方案

简介: 怼就完事了,总结几种验证码的解决方案

截止到今天咸鱼已经写了很多期关于 Js 逆向的文章,不过这么多的文章都有一个共同点,都是关于加密参数或者密码加密的解析,很多读者在后台私信希望能够出一些关于滑动验证或者人机验证的分析教程。

于是咸鱼总结了目前遇到过的的验证码类型以及总结出来的相关处理方式和大家聊一聊。

现在市面上的验证码的类型大致有下面几种类型。

图形验证码

比较常见的英文数字组合成的图形验证码,常常辅以各类干扰线扭曲图片中的内容达到提高混淆难度的目的,并且通过加长图片中的文字长度提升识别成本。

7位英数-难度高4位英数-难度中等4位英数-难度低

像这类验证码的处理方案有很多种,简单给大家概括一下。

难度中低的两类验证码,安装 tesserocr,通过 OCR 技术结合 Python 的 tesserocr 库可以就可以完成识别。如果验证码中带有简单干扰线可以使用灰度和二值化的方法提高代码的识别率。

常用示例代码:

import tesserocr
from PIL import Image
image = Image.open('code2.jpg')
image = image.convert('L')
threshold = 127
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)
image = image.point(table, '1')
result = tesserocr.image_to_text(image)
print(result)

难度较高的多位英数+扭曲的图形验证码包括上面总结的中低难度的图形验证码,可以通过 TensorFlow 训练的方式达到识别验证码的目的。

之前我有一个系列文章介绍了整个训练部署的流程,大家可以点击参考。

大佬说 | 写给程序员的TensorFlow教程-准备篇

大佬说 | 写给程序员的TensorFlow教程-编码篇

大佬说 | 写给程序员的TensorFlow教程-上线篇

使用这个方式的朋友记得要先准备好足够的验证码的样本,只要你的模型不是太差,通过足量的样本,不断调优是可以达到一个较为可观的识别率。

目前体验过最好的程序是冷月的四位英数,识别成功率高达 99.99% ,不过据知情人透露整个训练的样本达到了 6000 W ,耗费的时间精力可想而知。

旋转验证码

这类验证码是将验证码的图片旋转并且需要用户拖动下方滑块完成将图片摆正的操作才可以完成验证。

旋转验证码

不过某家的这个验证码有一些小小的 bug,依靠劳苦大众的智慧,我在 GitHub 上发现了一个很 Nice 的项目。

项目地址:https://github.com/scupte/xuanzhaunyanz

因为图库的容量问题,没有超大的图库作为后盾,将全部的原图抓取下来对比完全可以得到旋转的角度了。

不过鉴于该家的验证码并没有普及所以了解一波即可。

部分对比代码:

# -*- coding: utf-8 -*-
import cv2
import numpy as np
imagepath = '9_1.png'
img = cv2.imread(imagepath)
gray = cv2.cvtColor ( img , cv2.COLOR_BGR2GRAY )
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)  
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)  
#cv2.drawContours(img,contours,-1,(0,0,255),1)  
for cnt in contours:
    # 最小外界矩形的宽度和高度
    width, height = cv2.minAreaRect(cnt)[1]
    if width* height > 100:
        # 最小的外接矩形
        rect = cv2.minAreaRect(cnt)
        box = cv2.boxPoints(rect)  # 获取最小外接矩形的4个顶点
        box = np.int0(box)
        print box
        if 0 not in box.ravel():
            #绘制最小外界矩形
            for i in range(4):
                cv2.line(img, tuple(box[i]), tuple(box[(i+1)%4]), 0)  # 5
            theta = cv2.minAreaRect(cnt)[2]
            if abs(theta) <= 45:
                print('图片的旋转角度为%s.'%theta)
            #     angle = theta
print theta            
cv2.imshow("img", img)  
cv2.waitKey(0)  
滑动验证码

滑动验证码

说到滑动验证码,一定一定要提某验,虽然说市面上关于滑动验证码的产品有很多,但是某验的地位就像 10 年前脑白金在保健品市场的地位一样,业界标杆啊。

它越牛逼,市场上用它做防护的网站也越多,像国家企业信用信息公示系统、B 站、狗东等等。

像某验的解决方案也有很多,不过原理大同小异。

selenium 模拟滑动

使用 selenium 这个大家都听过,步骤大致是将缺口图和原图进行对比获取缺口的横坐标,并使用计算完成拖动轨迹模拟,之后使用 selenium 按照轨迹滑动完成缺口的拼接。

这一类方法的优点是门槛低,原理简单,缺点是完成滑动耗时较长,成功率无法估计(同一轨迹计算规则使用多次后成功率迅速下降)

常见的轨迹生成代码:

import numpy as np
import math
def ease_out_expo(x):
    """
    曲线函数
    :param x:
    :return:
    """
    if x == 1:
        return 1
    else:
        return 1 - pow(2, -10 * x)
def get_tracks(distance, seconds):
    """
    轨迹生成函数
    :param distance: 滑动总距离
    :param seconds: 滑动总时间
    :return:
    """
    tracks = [0]  # 存放轨迹的数组
    offsets = [0]  # 存放滑动总距离的记录数组
    for t in np.arange(0.0, seconds, 0.1):  # 产生一个数列如[0.0, 0.1, 0.2, 0.3]
        offset = round(ease_out_expo(t/seconds) * distance)  # 根据时间t计算在曲线上的滑动距离
        tracks.append(offset - offsets[-1])  # 本次计算的距离减去上一次移动的距离,得到本次的轨迹
        offsets.append(offset)  # 至本次滑动了的总距离
    return offsets, tracks
a, b = get_tracks(138, 3)
print(a, b)
def get_tracksb(distance):
    """
    根据物理的先加速再减速规律计算
    :param distance:
    :return:
    """
    distance += 20  # 加上20是为了滑动超过缺口再回滑
    v = 0  # 初速度
    t = 0.2  # 以0.2秒为一个计算周期
    forward_tracks = []  # 轨迹记录数组
    current = 0  # 初始移动距离
    mid = distance * 3 / 5  # 减速阀值即五分之三的距离加速剩下距离减速
    while current < distance:  # 总移动距离等于输入距离时结束
        if current < mid:  # 加速状态
            a = 2  # 加速度为+2
        else:  # 减速状态
            a = -3  # 加速度-3
        s = v * t + 0.5 * a * (t ** 2)  # 计算0.2秒周期内的位移
        v = v + a * t  # 计算本次周期后的速度
        current += s  # 将之前移动的总距离,加上本次0.2秒周期内移动的距离
        forward_tracks.append(round(s))  # 记录本次0.2秒周期内的移动距离为轨迹
    back_tracks = [-3, -3, -2, -2, -2, -2, -2, -1, -1, -1]  # 手动将开头加上的20,生成减去轨迹,即回滑轨迹
    return {'forward_tracks': forward_tracks, 'back_tracks': back_tracks}

Js 破解关键的参数

这类方法的门槛就比较高了,通过断点调试 Js,逆向分析滑动后提交参数的生成逻辑完成参数的生成,之后构造请求完成提交,当然这中间也是需要分析图片的缺口位置与模拟轨迹,不过没有使用到模拟所以速度快成功率高。

缺点是风险高,代码维护成本高,更新一个新版本就要重新分析而且逆向相关产品的代码是有一定的法律风险的,免费吃住也不是开玩笑的,所以很多能够商业化的大佬们都闷声发大财不会到处张扬。

使用现有的服务

上面两种方法各有各的优缺,很多人就想把这一块的工作量与风险分出去,这就要使用到第三方的服务商了。

不过目前国内市场上的服务商并没有这类服务,目前咸鱼在使用的是一家俄罗斯的服务商 - 2Captcha

这个服务商提供的验证码服务有很多种,其中包含了我们比较关心的 GeeTest 。

每1000次的价格

下面咸鱼给大家简单介绍下如何使用服务。(不要问为啥收费,人家服务商也要吃饭,况且这个价格实在便宜了)

首先,注册一个账号,官网是 http://2captcha.com/zh

首页

完成注册之后会跳转到控制台界面,这里最重要的是获取到属于你的 API Key 。

API KEY

好,拿到这个 API Key 之后就可以上手使用服务完成滑动的破解了。

通过参考官方的 API 文档,我们只需要构建两个 Get 请求就可以了。

第一个 Get 请求的组成是这样的:

https://2captcha.com/in.php
?key= 上面获取的API KEY 
&method=geetest
&gt= 某验参数
&challenge= 某验参数
&api_server=api-na.geetest.com(可选)
&pageurl= 滑动验证码所在的网页地址

参数列表:

参数名 参数介绍
key API KEY
method 表示验证码类型
gt 某验参数1
challenge 某验参数2
api_server api-na.geetest.com(选填)
pageurl 滑动验证码所在的网页地址

这里解释下关于 gtchallenge 这两个参数的获取。

第一个请求中这两个参数其中 gt这个参数是固定的,找一个使用某验的网站就可以获取。例如:

challenge这个参数是由请求返回,你找到这个请求之后按照请求重新获取一次,如果是 XHR 的话也可以直接 replay XHR 。

完成参数构建,提交完第一个请求之后,成功会返回类似下面的结果。


OK|2122988149 or as JSON {"status":1,"request":"2122988149"}

这里面的一串数字就是会话 ID。

有了这个会话 ID 之后我们就可以构建下一个请求,记住两个请求中间需要等待一些时间哦。

https://2captcha.com/res.php
?key=API KEY
&action=get
&id=2122988149

参数列表:

参数名 参数介绍
key API KEY
action Get
id 上一个请求返回的会话ID

这个请求返回的结果就是我们需要的加密参数。

{
      "challenge":"1a2b3456cd67890e12345fab678901c2de",
      "validate":"09fe8d7c6ba54f32e1dcb0a9fedc8765",
      "seccode":"12fe3d4c56789ba01f2e345d6789c012|jordan"
}

以上常见的几类验证码,已经全部介绍完了。

肯定有人问像 google 家的 ReCaptcha 以及和他相似的 hCaptcha 的解决方案没有提到啊?

像以上两类验证码,刚刚提到的服务商也同样有提供接口打码。

至于其他不依靠服务商的解决方案,目前咸鱼还没有接触过,毕竟这两类验证码,咸鱼手动点击都没办法做到一次通过,目前也只能依赖服务商了。


相关文章
|
9月前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
1775 5
|
PHP
PHP实现图片登录验证码的解决方案
PHP实现图片登录验证码的解决方案
241 0
|
数据安全/隐私保护
一个页面多个图形验证码冲突的解决方案
实际开发中,经常会遇到一个页面需要两个或多个验证码,使用同一个验证码调用两次会导致前一个失效。那么我们需要使用两个不同的验证码.
一个页面多个图形验证码冲突的解决方案
|
Web App开发 文字识别 测试技术
教你python自动识别图文验证码的解决方案!
对于web应用程序来讲,处于安全性考虑,在登录的时候,都会设置验证码,验证码的类型种类繁多,有图片中辨别数字字母的,有点击图片中指定的文字的,也有算术计算结果的,再复杂一点就是滑动验证的。诸如此类的验证码,对我们的系统增加了安全性的保障,但是对于我们测试人员来讲,在自动化测试的过程中,无疑是一个棘手的问题。
1937 0
|
数据可视化 JavaScript 前端开发
VisualCaptcha – 灵活的可视化验证码解决方案
  visualCaptcha 是一个可配置的验证码解决方案,专注于可访问性和简单性,同时保持安全性。它也支持移动,视网膜设备,并有一个创新的可访问性的解决方案。 visualCaptcha 现在可以跨多个后端语言,不管你是使用 JavaScript ,Ruby 或 PHP,都可以使用 visualCaptcha。
915 0
dedecms 验证码老提示不正确的解决方案
1.三个字:权限不够,修改服务器上的IUSER的访问权限即可 类似的在phpcms中出现error_log.php错误的话只要修改权限即可!
713 0
|
Apache
phpcms(v9)验证码无法显示解决方案
1.首先直接启动下服务器(本人经历过,管用) 2.找到php.ini文件 搜索extension=php_gd2.dll这段代码 然后把前面的;符号去掉即可。 3.关键一点是获取验证码的图片与全局变量SITE_URL相关,也就是网站的目录,所以只要修改cache/configs/system.php文件中的网站路径变量‘web_path’ 即可。
1319 0
|
JavaScript 前端开发
大型网站中的验证码解决方案
先看这个demo的解决方案图 Entity是实体,里面有验证码的实体 private string contentType = "image/pjpeg"; private ImageFormat imageFormat = ImageFormat.
878 0
|
存储 NoSQL 数据库
认证服务---整合短信验证码,用户注册和登录 ,密码采用MD5加密存储 【二】
这篇文章讲述了在分布式微服务系统中添加用户注册和登录功能的过程,重点介绍了用户注册时通过远程服务调用第三方服务获取短信验证码、使用Redis进行验证码校验、对密码进行MD5加密后存储到数据库,以及用户登录时的远程服务调用和密码匹配校验的实现细节。
认证服务---整合短信验证码,用户注册和登录 ,密码采用MD5加密存储 【二】