极验验证码,通用破解

首先,我们来理一下思路:

极验是专业提供第三方服务的,既然是第三方服务,就表明 验证滑动是否成功的服务端是在极验的后台。

那么用户的流程就应该是:

1、访问目标网页,获得表明商户的参数  

                                ↓

2、带着这个参数请求极验,获得滑动图片

                                ↓

3、用户拖动图片,返回轨迹等数据给极验

                                ↓

4、极验返回验证结果,如果成功则附带一个验证成功的参数

                                ↓

5、携带这个参数即可请求目标网页后续内容

那其实我们就可以利用这个三方交互的流程,尽量让我们的代码可复用。

所以思路很清晰,我们的流程就应该是:

1、访问目标网页,获得表明商户的参数  

                                ↓

2、调用我们的服务,获得一个验证成功的参数

                                ↓

3、携带这个参数即可请求目标网页后续内容

也就是说,我们的代码是只与极验交互,传入一个参数,返回一个参数即可。

我们先来看一下极验的请求参数:

很明显,两个参数,gt 和 challenge 。

极验的官方使用文档里面有说明:

果然,就跟我们的推测一样,我们只需要请求目标网页即可拿到这两个参数。

而最终的验证成功返回值:

这个validate就是我们需要的参数。

也就是:

gt, challenge = get_gt()  #和目标网站交互
validate = get_validate(gt, challenge)  #和极验交互
result = get_result(validate)  #和目标网站交互

很明显,我们可以复用的就是 get_validate,这也是破解的重点:

那首先我们需要一个滑动验证码的模板:

极验文档中直接有使用样例:https://www.geetest.com/demo/slide-custom.html

但是他的传入参数已经写死,所以我们需要对这个html进行加工一下:

可以看到他取参数是直接调用ajax,参数放在data中:

而我们的需求是参数可以变化的,所以我们只需要稍作修改:

请求时只需用get请求传入参数即可。

接下来就是常规的selenium模拟滑动的内容了,网上样例很多,我就不多说了。

只需要注意一点就是url需要使用我们自己的html:

url = './jiyan.html?success=1&new_captcha=true&gt={}&challenge={}'.format(gt, challenge)

补充一点:

极验的图片是使用convas直接生成的,拼接比较繁琐,我们使用selenium直接截图比较方便:

其中image1, image2分别为滑块在最左端和最右端时的截图,主要是用来确定y的位置,裁剪图片,提高准确率。

二值化阈值通过y的位置范围内的平均阈值来确定。

# 通过比较两张图片确定y位置
def get_y(image1, image2):
    y_s = []
    for i in range(image1.size[0] - 60, image1.size[0]):
        for j in range(image1.size[1]):

            rgb1 = image1.load()[i, j]
            rgb2 = image2.load()[i, j]
            if rgb1[1] == rgb2[1] and rgb1[2] == rgb2[2] and rgb1[3] == rgb2[3]:
                continue
            y_s.append(j)

    y_s_s = []
    for y in range(min(y_s), max(y_s)):
        if y_s.count(y) > 40:
            y_s_s.append(y)
    return max(y_s_s), min(y_s_s)


# 获取图片的平均灰度值
def get_ave_rgb(image1):
    rgb = []
    for i in range(image1.size[0]):
        for j in range(image1.size[1]):
            rgb.append(image1.load()[i, j])
    return np.mean(rgb)


def get_x(img_11, img_22):
    y1, y2 = get_y(img_11, img_22)
    cropImg = img_11.crop((0, y2, img_11.size[0], y1))
    image1 = cropImg.convert('L')

    threshold = int(get_ave_rgb(image1)) - 30  # 阈值通过平均灰度值确定

    # 二值化
    table = []
    for i in range(256):
        if i < threshold:
            table.append(0)
        else:
            table.append(1)
    img = image1.point(table, '1')
    img.save('tu3.png')

    node_list = []
    for x in range(40, img.size[0] - 80, 2):
        # (x0,y0,x1,y1)
        box1 = (x, 0, x + 43, img.size[1])

        image1 = img.crop(box1)
        # image1.show()
        matrix = np.asarray(image1)
        node_num = np.sum(matrix)
        node_list.append((x, node_num))

    return min(node_list, key=lambda x: x[1])

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章