专栏首页python前行者极验验证码破解分析

极验验证码破解分析

极验验证码相关文档:http://www.wzdr.cn/article-725.html 极验验证码登录注册地址:http://jiyan.c2567.com/index.php/login/index.html(不能用中文帐号注册) 利用极验接口破解验证码:https://blog.csdn.net/zhangmengran/article/details/82901891


首先介绍一下 极验验证:

1. 抓取极验参数

任何一个网站,如果在登录时网站接入的极验的接口,那么该网站就可以使用极验验证码进行登录,此时极验验证码API就会返回两个极验参数,gt和challenge,这两个参数只跟极验验证码API相关,跟这个网站没有任何关系。

注意: 有的网站是直接调用极验官方提供的验证码接口: 比如:极验的官方后台,https://auth.geetest.com/api/init_captcha?time=1538185553190 有的网站又对极验验证码接口封装了一个API接口: 比如: 魅族登录:https://login.flyme.cn/sec/geetest3?t=1538185653356 工商信息网:http://www.gsxt.gov.cn/SearchItemCaptcha

2. 将获取的极验参数,提交给极验破解网站(http://jiyan.c2567.com)的识别接口,会得到新的返回值:

这里的返回值就相当于你在网站页面中将滑块滑到正确的位置得到的加密结果。

{ 
status: "ok", # 就相当于你的滑块是否滑动到正确位置,正确的话就是OK,错误就是Error 
challenge: "3d033f099597f5ae63e2e2c902301d183z", 
validate: "8f6ebd56291ed6569ac40c1d74780985" 
} 

3. 将上述参数challenge和validate,混合着网站自己提交的参数向网站自己的url发送POST/GET请求即可。

下面写一个小实例:

利用极验破解接口(http://jiyan.c2567.com),模拟极验官方网站后台登录(https://auth.geetest.com/login)

第一个函数要请求的网址以及返回的响应

第二个函数要请求的网址以及返回的响应

第三个函数要请求的网址以及返回的响应

创建一个名字为geetest.py文件,具体代码如下:

import requests, json
from http.cookiejar import LWPCookieJar
 
class JiYanLoginSpider(object):
    def __init__(self):
        # 极验官方登录用户
        self.jiyan_user = ''
        # 极验破解网站登录用户
        self.pojie_user = ''
        self.password = ''
 
        # 初始化session对象,用于保存登录成功后的cookie信息。
        self.session = requests.Session()
        self.session.cookies = LWPCookieJar(filename='jy_cookie.txt')
 
        # 配置session的全局请求头
        self.session.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
        }
 
    def get_jiyan_params(self):
        """
        分析要爬取网站中调用极验验证API的url地址,访问这个url地址,获取gt和challenge参数
        :return:
        """
        try:
            response = self.session.get('https://auth.geetest.com/api/init_captcha')
            return json.loads(response.text).get('data')
        except Exception as e:
            print('极验参数获取失败:',e)
            return None
 
    def jiyan_shibie(self, jiyan_params):
        """
        根据get_jiyan_params()函数返回的值,调用极验破解网站的识别接口,开始识别验证码,验证码识别成功,会返回两个加密数据,challenge和validate。
        :param jiyan_params: 获取的极验参数
        :return:
        """
        pojie_url = 'http://jiyanapi.c2567.com/shibie?gt={}&challenge={}&referer=https://auth.geetest.com&user={}&pass={}&return=json&model=3&format=utf8'.format(jiyan_params.get('gt'), jiyan_params.get('challenge'), self.pojie_user, self.password)
        # 发送请求,开始破解验证码
        try:
            response = self.session.get(pojie_url).text
            result_status = json.loads(response).get('status')
            if result_status == "ok":
                # 破解成功
                return json.loads(response)
            else:
                # 破解失败
                print('破解失败,需要重新获取极验参数,再重新破解。')
                return None
        except Exception as e:
            print('识别请求解析失败,',e)
            return None
 
    def login(self, result_dict):
        """
        根据验证码识别结果,进行模拟登录
        :param result_dict:
        :return:
        """
        loging_url = "https://auth.geetest.com/api/login"
        login_params = {
            # 网站参数
            'email': self.jiyan_user,
            'password': self.password,
            # 验证码识别后的结果参数
            'geetest_challenge': result_dict.get('challenge'),
            'geetest_validate': result_dict.get('validate'),
            'geetest_seccode': result_dict.get('validate') + '|jordan'
        }
        response = self.session.post(loging_url, data=json.dumps(login_params))
        if response.status_code == 200:
            print('登录成功:', response.cookies)
            self.session.cookies.save(ignore_discard=True, ignore_expires=True)
        else:
            print('登录失败:', response.status_code, response.text)
 
 
if __name__ == "__main__":
    jy = JiYanLoginSpider()
    jy_params = jy.get_jiyan_params()
    if jy_params:
        result = jy.jiyan_shibie(jy_params)
        if result:
            jy.login(result)

整个过程的流程如下图:

识别接口网址所要携带的参数如下图:

项目环境

大致需要用到以下模块各位看观请提前准备好: python3.6、selenium、numpy、PIL、chromedriver

分析步骤以及代码编写

  1. 首先分析目标网站(本次主要以geetest官网滑块demo为参考)

网站大致长这个样子,首先f12打开 开发者工具选择Elements查看节点,发现最新版本的滑块图片是使用画布来进行呈现的,期间查阅大量文档,使用如下代码获得画布中的图片数据,获取到的图片是base64进行编码的

document.getElementsByClassName("geetest_canvas_bg geetest_absolute")[0].toDataURL("image/png")

2.通过分析发现这两个画布放的是所需要的背景图和缺口图(其实一眼就看出来的)

  1. 接下来就是代码的编写了 3.1 首先是获得背景图和缺口图的数据
    def get_images(self):
        """
        获取验证码图片
        :return: 图片的location信息
        """
        time.sleep(1)
        self.browser.web_driver_wait_ruishu(10, "class", 'geetest_canvas_slice')
        fullgb = self.browser.execute_js('document.getElementsByClassName("geetest_canvas_bg geetest_'
                                             'absolute")[0].toDataURL("image/png")')["value"]
        bg = self.browser.execute_js('document.getElementsByClassName("geetest_canvas_fullbg geetest_fade'
                                         ' geetest_absolute")[0].toDataURL("image/png")')["value"]
        return bg, fullgb

3.2 对数据进行解码操作并保存图片

    def get_decode_image(self, filename, location_list):
        """
        解码base64数据
        """
        _, img = location_list.split(",")
        img = base64.decodebytes(img.encode())
        new_im: image.Image = image.open(BytesIO(img))
        return new_im

3.3 接下来就是计算缺口位置了(这里使用的PIL中计算两张图片的差值获得缺口位置)

    def compute_gap(self, img1, img2):
        """计算缺口偏移 这种方式成功率很高"""
        # 将图片修改为RGB模式
        img1 = img1.convert("RGB")
        img2 = img2.convert("RGB")
        # 计算差值
        diff = ImageChops.difference(img1, img2)
        # 灰度图
        diff = diff.convert("L")
        # 二值化
        diff = diff.point(self.table, '1')
        left = 43
        # 这里做了优化为减少误差 纵坐标的像素点大于5时才认为是找到
        # 防止缺口有凸起时有误差
        for w in range(left, diff.size[0]):
            lis = []
            for h in range(diff.size[1]):
                if diff.load()[w, h] == 1:
                    lis.append(w)
                if len(lis) > 5:
                    return w

3.4 当滑块的缺口位置找到以后就需要生成滑动轨迹(其中加20是保证在滑动时先超过缺口位置然后在慢慢还原到正确位置)

    def ease_out_quart(self, x):
        return 1 - pow(1 - x, 4)
    def get_tracks_2(self, distance, seconds, ease_func):
        """
        根据轨迹离散分布生成的数学 生成  # 参考文档  https://www.jianshu.com/p/3f968958af5a
        成功率很高 90% 往上
        :param distance: 缺口位置
        :param seconds:  时间
        :param ease_func: 生成函数
        :return: 轨迹数组
        """
        distance += 20
        tracks = [0]
        offsets = [0]
        for t in np.arange(0.0, seconds, 0.1):
            ease = ease_func
            offset = round(ease(t / seconds) * distance)
            tracks.append(offset - offsets[-1])
            offsets.append(offset)
        tracks.extend([-3, -2, -3, -2, -2, -2, -2, -1, -0, -1, -1, -1])
        return tracks

以上来源:https://www.lizenghai.com/archives/4731.html


Python有一个神奇的库叫pyautogui, 可以操作键盘和鼠标。 pip install pyautogui

python selenium2 中的显示等待WebDriverWait与条件判断expected_conditions举例 :https://www.cnblogs.com/yuuwee/p/6635652.html 知乎 极验验证可以被破解吗?:https://www.zhihu.com/question/28833985 Python&按键精灵自动化:https://blog.csdn.net/whiterbear/article/details/50402096 Python调用(运行)外部程序:https://blog.csdn.net/fanhuajames/article/details/8781977

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 静态html提取正文的API和开源算法

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    周小董
  • [709]python之pywifi

    这一步需要使用tkinter模块,这是python自带的图形界面库,通过import tkinter调用使用就可以了,代码中set_init_window函数就...

    周小董
  • session会话管理

    session会话和cookie一起被称为会话跟踪技术,主要通过保存在服务器端的session数据和客户端浏览器的cookie数据共同完成用户访问服务器的足迹记...

    周小董
  • 剑指offer【50~59】

    排序数组,很明显二分查找,找到第一个 >= k 的元素索引以及第一个 > k 的元素索引,两者相减即为答案,即 lowerBound - upperBound。...

    echobingo
  • Python模拟登录和登录跳转

    py3study
  • 回归

    看一下损失函数的导函数tanh(x),当x偏离0时,tanh(x)趋向+1或者-1

    用户1733462
  • 自定义UITableViewCell实现左滑动多菜单功能LeftSwipe

    1、使用自定义UITableViewCell + UISwipeGestureRecognizer + 代理 实现;

    tandaxia
  • Python Web Flask源码解读(二)——路由原理

    在 Flask中是使用 @app.route这个装饰器来实现 url和方法之间的映射的。

    阳仔
  • 两个imageView实现图片轮播

    Scott_Mr
  • harbor仓库镜像的删除

    docker镜像仓库中镜像的清理,一直是个比较麻烦的事情。尤其是在测试环境当中,每天都会有大量的构建。由此会产生大量的历史镜像,而这些镜像,大多数都没有用。

    yaohong

扫码关注云+社区

领取腾讯云代金券