验证码破解:极验3.0滑动验证码破解最新俩种方法

您所在的位置:网站首页 破解网站验证码违法吗 验证码破解:极验3.0滑动验证码破解最新俩种方法

验证码破解:极验3.0滑动验证码破解最新俩种方法

2023-08-05 19:59| 来源: 网络整理| 查看: 265

特点: 对于极验验证码3.0版本,我们首先点击按钮进行智能验证。如果验证不通过,则会弹出滑动的验证的窗口,拖动滑块拼合图像进行验证。之后三个加密参数会生成,通过表单提交到后台,后台还会进行一次验证。

极滑2.0的破解思路:

模拟点击验证按钮 直接用Selenium模拟点击按钮识别滑动缺口的位置 利用原图和缺口图对比检测方式来识别缺口的位置,通过遍历俩张图片,找出相同位置像素RGB差距超过此阀值的像素点,那么此像素点的位置就是缺口的位置。模拟拖动滑块 模拟人的移动轨迹通过验证,一般是先加速后减速。

破解的重要点就是:识别滑动缺口的位置。 但是极滑3.0进行了更新,我们点击按钮进行智能验证,然后截图,但是获取到的不再是完整的原图,而是带有缺口的原图,这样子,我们就不能使用极滑2.0的办法来获取到滑动缺口的位置,需要另想获取滑动缺口的位置,下面有分别俩个办法来获取极滑3.0的缺口位置:

方法一、通过超级鹰平台(本博客将以该方法为测试案例) 通过超级鹰验证码破解平台,我们先截图获取带有缺口的验证码图片,然后再在图片上加上”请点击凹槽左上交“ 这几个打字,然后通过接口发送超级鹰验证平台,他们就会返回给我们凹槽的左上角位置 获取得到的验证码: 在这里插入图片描述 需要添加上”请点击凹槽左上角“,超级鹰才能知道是识别滑动缺口图片的凹槽位置 在这里插入图片描述 超级鹰返回的结果为字典类型,其中键"pic_str"的值为结果坐标(60, 52): 在这里插入图片描述 图片凹槽的左上角的真实位置为(58,53): 在这里插入图片描述 方法二、不断截图

通过滑动小块按钮,从左边到右边,然后不断保存滑动过的轨迹和截图到的照片到字典中,通过照片分析,找到其中没有凹槽的图片,也就是将滑块移动到符合位置的轨迹,至于怎么在那么多截图中找到最合适的那种找完美的图片,这个就需要图片处理的算法,这个下次再弄,这次尝试了方法一。

方法一代码:chaojiying.py 、geetest_spider.py

chaojiying.py: 需要使用到超级鹰平台,读者可以看我上一篇博客,有讲到如何注册使用,在geetest_spider.py中需要用到超级鹰的账号、密码、软件ID,这个模块就无要更改

import requests from hashlib import md5 class Chaojiying_Client(object): def __init__(self, username, password, soft_id): self.username = username self.password = md5(password.encode("utf-8")).hexdigest() self.soft_id = soft_id self.base_params = { 'user': self.username, 'pass2': self.password, 'softid': self.soft_id, } self.headers = { 'Connection': 'Keep-Alive', 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', } def PostPic(self, im, codetype): """ im: 图片字节 codetype: 题目类型 参考 http://www.chaojiying.com/price.html """ params = { 'codetype': codetype, } params.update(self.base_params) files = {'userfile': ('ccc.jpg', im)} r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers) return r.json() def ReportError(self, im_id): """ im_id:报错题目的图片ID """ params = { 'id': im_id, } params.update(self.base_params) r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers) return r.json() if __name__ == '__main__': # todo:用户中心>>软件ID 生成一个替换 96001 chaojiying = Chaojiying_Client('超级鹰账号', '密码', '软件ID') # todo: 本地图片文件路径 来替换 a.jpg 有时WIN系统须要// im = open('target.png', 'rb').read() # todo: 9101 验证码类型, 滑动验证码就不需要更改 result = chaojiying.PostPic(im, 9101) print(result)

geetest_spider.py:需要修改CrackGeetest类中的get_gap()方法中的超级鹰账号、密码以及软件ID

import time from io import BytesIO from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from chaogjiying import Chaojiying_Client from PIL import ImageFont from PIL import Image from PIL import ImageDraw EMAIL = '[email protected]' PASSWORD = '123456' BORDER_1 = 8 BORDER_2 = 15 BORDER_3 = 28 class CrackGeetest(object): def __init__(self): self.url = 'https://account.geetest.com/login' self.browser = webdriver.Chrome() self.browser.maximize_window() self.wait = WebDriverWait(self.browser, 5) self.email = EMAIL self.password = PASSWORD self.success = False self.try_num = 3 self.now_num = 3 self.flesh_num = 1 def __del__(self): self.browser.close() def get_geetest_button(self): """ 获取初始验证按钮 :return: 初始化验证按钮 """ button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip'))) return button def get_position(self): """ 获取验证码位置 :return: 验证码位置元组 """ img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img'))) time.sleep(0.5) location = img.location size = img.size top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[ 'width'] return top, bottom, left, right def get_screenshot(self): """ 获取网页截图 :return: 截图对象 """ screenshot = self.browser.get_screenshot_as_png() screenshot = Image.open(BytesIO(screenshot)) return screenshot def get_slider(self): """ 获取滑块 :return: 滑块对象 """ try: slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button'))) except Exception: self.crack() return return slider def get_geetest_image(self, name='captcha.png'): """ 获取验证码图片 :return: 图片对象 """ top, bottom, left, right = self.get_position() screenshot = self.get_screenshot() captcha = screenshot.crop((left, top, right, bottom)) captcha.save(name) return captcha def open(self): """ 打开网页输入用户名密码 :return: None """ self.browser.get(self.url) time.sleep(0.5) email = self.browser.find_elements_by_xpath("//i[@class='icon-email']/../../input")[0] password = self.browser.find_element_by_xpath("//i[@class='icon-password']/../../input") email.send_keys(self.email) password.send_keys(self.password) @staticmethod def get_track(distance): """ 根据偏移量获取移动轨迹 :param distance: 偏移量 :return: 移动轨迹 """ # 移动轨迹 track = [] # 当前位移 current = 0 # 减速阈值 mid = distance * 4 / 5 # 计算间隔 t = 0.2 # 初速度 v = 0 while current 软件ID 生成一个替换 96001 chaojiying = Chaojiying_Client('超级鹰账号', '密码', '软件ID') # todo: 本地图片文件路径 来替换 a.jpg 有时WIN系统须要// im = open('target.png', 'rb').read() # todo: 9101 验证码类型, 滑动验证码就不需要更改 result = chaojiying.PostPic(im, 9101) gap = int(result.get("pic_str").split(",")[0]) return gap # 超级赢验证失败,反馈回去,将不扣钱 @staticmethod def fail_to_chaojiying(): """ 超级赢验证失败,反馈回去,将不扣钱 :return: None """ # todo:用户中心>>软件ID 生成一个替换 96001 chaojiying = Chaojiying_Client('超级鹰账号', '密码', '软件ID') # todo: 本地图片文件路径 来替换 a.jpg 有时WIN系统须要// im = open('target.png', 'rb').read() result = chaojiying.ReportError(im) @staticmethod def add_text_to_image(): """ 给截取的带缺口的图片添加“请点击凹槽左上角" :return: None """ # 设置字体样式 font = ImageFont.truetype("/usr/share/fonts/蓝杰ios加粗.ttf", 32) # 打开底版图片 imageFile = "captcha.png" im1 = Image.open(imageFile) # 在图片上添加文字 "请点击凹槽左上角" add_text = "请点击凹槽左上角" draw = ImageDraw.Draw(im1) draw.text((2, 120), add_text, "#FF0000", font=font) # 保存 im1.save("target.png") def crack(self): # 输入用户名密码 self.open() # 点击验证按钮 time.sleep(1) button = self.get_geetest_button() button.click() # BOREDER有俩种情况,一种是8,一种是15, 还有一种是28 def slider_try(gap, BORDER): if self.now_num: # 减去缺口位置 gap -= BORDER # 计算滑动距离 track = self.get_track(int(gap)) # 拖动滑块 slider = self.get_slider() self.move_to_gap(slider, track) try: self.success = self.wait.until( EC.text_to_be_present_in_element((By.CLASS_NAME, 'geetest_success_radar_tip_content'), '验证成功')) except Exception as e: self.now_num -= 1 test_num = self.try_num - self.now_num if self.now_num == 0: print("第%d次尝试失败, 验证失败" % test_num) else: print("验证失败,正在进行第%d次尝试" % test_num) while not self.success and self.now_num > 0: # 获取验证码图片 try: self.get_geetest_image() except Exception as e: # todo: 其他验证,或者是自动识别通过 self.success = True print("自动识别通过或者验证非滑动验证码,无需滑动%s" % e) time.sleep(5) return # 给验证码加文字 self.add_text_to_image() # 获取缺口位置 gap = self.get_gap() print("缺口位置gap为",gap) # 第一中请求,gap减少7 slider_try(gap, BORDER_1) # 成功后退出 if not self.success: # 尝试gap减少14 slider_try(gap, BORDER_2) if not self.success: slider_try(gap, BORDER_3) self.fail_to_chaojiying() if self.success: test_num = self.try_num - self.now_num + 1 print("第{}次刷新,第{}次尝试,验证通过".format(self.flesh_num, test_num)) time.sleep(5) self.success = True if not self.success: print("重新刷新页面,这是第%d次刷新" % self.flesh_num) self.flesh_num += 1 self.now_num = 3 self.try_num = 3 self.crack() if __name__ == '__main__': crack = CrackGeetest() crack.crack() del crack 测试数据: 次数验证何时通过(每次刷新尝试最多3次机会)1第1次刷新,第1次尝试,验证通过2第2次刷新,第3次尝试,验证通过3第1次刷新,第2次尝试,验证通过4第1次刷新,第1次尝试,验证通过5第8次刷新,第1次尝试,验证通过过6第1次刷新,第3次尝试,验证通过

该验证的通过率,取决于超级鹰平台的返回的坐标,不过从结果可以看出来,基本都是要识别好几次,才可以成功,这个算法有点不行,可以通过celery异步让他处理,结果会更好,如果有机会,还不如自己写个识别图片凹槽的算法,感觉不会特别难



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3