极验验证码逆向(一)

记录一次处理极验验证码的心路历程。(主要是看到现有的方法都是通过selenium去模拟拖动😈)

demo网站:滑动模式

里面有很多不同的极验现有的模式,大家可以参考一下。

本文主要是以最为常用的滑动验证为基础来讲解。

首先分析一下抓包的请求,手动拖动一下滑动验证码,可以看到这个包在提交。

根据返回的内容来看,这个包显然就是我们需要针对的报文。

通过观察参数来看,主要分析的就是参数w,模拟其生成过程。

到这一步,我们可以把整个流程的处理方案分为三步骤,一 针对验证码的图片处理,二得到缺口位置,三生成滑动轨迹,四计算w的参数生成过程。

下面我们来按照这个步骤执行:

1.还原验证码图片

寻找图片的url

这分别为background和full的整个图片,但是我们发现其生成的过程是乱序的图片,这该如何处理呢?我们不妨逆向思维一下,我们看到的图层是正常的样子,那么极验肯定是根据一定的规则,将这些图片排列好生成给我们,那么我们只需要找到这个生成的算法即可。 

通过设置断点,我们不难发现,这个即就是图层的生成算法, 

Ge这个函数即为这个图片的生成顺序,所以我们只需要按照这个顺序将图片取出,就可以生成该图片的正常情况。 

 注意,上图将图片处理的时候还进行了缩放,所以我们生成图片的时候也需要进行缩放处理。

import requests
import PIL.Image as Image
import cv2

class DealImage():
    def __init__(self, url, image_save_path):
        self.jiyan_sequence = [39, 38, 48, 49, 41, 40, 46, 47, 35, 34, 50, 51, 33, 32, 28, 29, 27, 26, 36, 37, 31, 30, 44, 45,
                          43, 42, 12, 13, 23, 22, 14, 15, 21, 20, 8, 9, 25, 24, 6, 7, 3, 2, 0, 1, 11, 10, 4, 5, 19, 18, 16, 17]
        self.url = url
        self.tmp_image_path = './cut/tmp_image.png'
        self.image_save_path = image_save_path


    def get_image(self):
        res = requests.get(self.url).content
        with open(self.tmp_image_path, 'wb')as f:
            f.write(res)

    def cut_image(self):
        img = cv2.imread(self.tmp_image_path, cv2.IMREAD_COLOR)
        h = img.shape[0]
        w = img.shape[1]
        # cv2.imshow('test', img)
        # cv2.waitKey()
        # cv2.destroyAllWindows()
        h_size = 80
        w_size = 12
        h_step = img.shape[0] // h_size
        w_step = img.shape[1] // w_size
        image_list = []
        count = 0
        for h in range(h_step):
            for w in range(w_step):
                img_cut = img[h * h_size:(h + 1) * h_size, w * w_size:(w + 1) * w_size, :]
                image_list.append(img_cut[:, :, 1])
                cv2.imwrite(('./cut/{}.png'.format(count)), img_cut)
                count += 1

    def merge_img(self):
        image_path = './cut/'
        h_size = 80
        w_size = 12
        # print(file_list)
        def image_compose():
            to_image = Image.new('RGB', (312, 160))
            for i, num in enumerate(self.jiyan_sequence):
                height = (i // 26) * h_size
                width = ((i - 26) * 12 if i > 25 else i * 12)
                # print(width, height, file_list[i])
                from_image = Image.open(image_path + '{}.png'.format(num)).resize((w_size, h_size), Image.ANTIALIAS)
                to_image.paste(from_image, (width, height))
            to_image.resize((260, 160), Image.ANTIALIAS).save(self.image_save_path)
        image_compose()

    def main(self):
        self.get_image()
        self.cut_image()
        self.merge_img()
        print("图片保存完成,保存的路径为:{}".format(self.image_save_path))


if __name__ == '__main__':
    # full_img
    base_url = 'https://static.geetest.com/'
    url = 'pictures/gt/cd0bbb6fe/cd0bbb6fe.jpg'
    # bg_img
    # url = 'https://static.geetest.com/pictures/gt/7bfaaa72b/bg/5b7598fd8.jpg'
    full_image_path = './full.png'
    deal_image = DealImage(base_url+url, full_image_path)
    deal_image.main()
    deal_image = DealImage(base_url+'pictures/gt/cd0bbb6fe/bg/d90272870.jpg', './bg.png')
    deal_image.main()

2.获取缺口的位置

缺口的获取方式其实很简单,将两张图片的像素点值进行色域比较即可,缺口位置的色差肯定大于其他正常位置的缺口,取该值即可。

from PIL import Image


class GetDistance():
    def __init__(self, capture1, capture2):
        self.capture1 = capture1
        self.capture2 = capture2

    def get_img(self):
        capture1 = Image.open(self.capture1)
        capture2 = Image.open(self.capture2)
        return capture1, capture2


    # 缩放图片
    def reszie_img(self, img):
        (x, y) = img.size
        x_resize = int(x / 2) + 1
        y_resize = int(y / 2)
        img = img.resize((x_resize, y_resize), Image.ANTIALIAS)
        return img



    def get_gap_offset(self, img1, img2):
        # 起始对比x点
        distance = 0
        for i in range(distance, img1.size[0]):
            for j in range(img1.size[1]):
                # 两张图片对比,(i,j)像素点的RGB差距,过大则该x为偏移值
                if not self.is_pixel_equal(img1, img2, i, j):
                    distance = i
                    return distance
        return distance

    def is_pixel_equal(self, img1, img2, x, y):
        pixel1, pixel2 = img1.load()[x, y], img2.load()[x, y]
        sub_index = 100
        # 比较RGB各分量的值
        if abs(pixel1[0] - pixel2[0]) < sub_index and abs(pixel1[1] - pixel2[1]) < sub_index and abs(
                pixel1[2] - pixel2[2]) < sub_index:
            return True
        else:
            return False

    def main(self):
        capture1, capture2 = self.get_img()
        distance = self.get_gap_offset(capture1, capture2)
        print(distance)


if __name__ == '__main__':
    full_img = './full.png'
    bk_img = './bg.png'
    get_distance = GetDistance(full_img, bk_img)
    get_distance.main()

3.生成轨迹方程

计算出了距离之后,最主要的就是生成这个滑动轨迹,通过抓包发现其轨迹的逻辑。

但是到目前为止,我也没有找到好的方法可以生成这条轨迹,仍然按照的是远古的方法,根据匀加速和匀减速去生成这个轨迹,目前测试效果并不是很理想,正确率较低。

如果各位看官有什么好的方法 可以高通过率,可以一起探讨。

如涉及版权问题,请联系qq:986361369.(可以商务合作,白嫖党勿扰)

关于w的生成方式,将在下一节中详细介绍。

极验验证码生成(二)_china-mogul-CSDN博客其实关于w的生成方式,我们可以完全可以通过扣代码的方式去实现,不过首先找到w参数的生成js是很重要的。废话不多说,直接上干货。目前我掌握两种方式可以找到w这个参数。1.通过内存漫游的方式(这个后期会进行详细介绍)。2.通过经典的跟栈方式,查找这个函数的生成位置。(主要介绍)滑动一次,我们可以根据chrome寻找到这个ajax的调用栈关系,如下图所示:那么我们可以在这这个js的任意地方下断点,然后重新拖动验证码,让其在你需要的位置段住。这个过程需要很多的耐心,其实我们很https://blog.csdn.net/qq_41733098/article/details/120956006

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spider boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值