声明:本文内容仅供学习交流,严禁用于商业用途,否则由此产生的一切后果均与作者无关。
目录
前言
我过的第一个验证码就是极验,当时是极验三代,不仅请求流程多,还有暗坑,当时为了过极验头发都掉了不少,去年就听说极验要出四代了,我以为会变得更难,没想到简单了不少,很快就逆向成功了。
环境:
window10
抓包工具:
Fiddler
浏览器:
谷歌浏览器最新版本
IDE:
pycharm专业版
一、请求流程
逆向第一步一般都是流程分析,打开抓包工具,分析请求流程。
二、算法扣取
1.challenge
直接全局搜索
2.w
像w这种全局搜索肯定是很多的,因为极验三代中w的值在一个对象中,并以ASCII编码的形式表示
打上断点,移动滑块,成功断住,进入加密函数中分析逻辑
从上图可以分析出:
1. 函数执行 得到变量n
2.new 一个构造函数得到一个对象,取对象中一个函数,执行函数,实参为e和n,得到结果赋值给o
3.执行函数实参为o,得到的结果与a相加,最后的结果便为w的值
其中e为变量r生成传入的对象
明确目标:
1.扣取生成n的函数 (0, c[$_CEABJ(181)])()
2.扣取构造函数 _[($_CEAAg(91))]()
3.扣取加密e和n生成o得函数 i[$_CEAAg(91)][$_CEAAg(757)]
4.扣取加密o的函数 (0,c[$_CEAAg(139)])
扣取这些函数非常麻烦,这个js文件有13000多行代码,我们可以将整个js文件复制到本地,将要扣取的这几个函数直接调用执行。这样就简单很多了。
window = global
window.document = {
body:{},
head:{},
}
window.location = {
protocol:'https:',
}
window.navigator = {
userAgent:'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.1885.120 Safari/537.36'
}
分析扣取下来的js代码:
我们所需要的函数都在自执行函数中,自执行函数的的作用域为函数作用域,所以直接调用加密函数行不通,所以我们需要将加密函数暴露在全局作用域中,在全局作用域中调用加密函数。
这样就将需要扣取加密函数暴露给全局了,直接在全局调用
识别滑块缺口得到set_Left的值,首先获取滑块的背景图和滑块图的url地址(在第一次请求返回值中),请求图片的url本地保存然后识别
识别代码:
import os
import cv2
from PIL import Image
def identify_gap(bg, tp):
'''
bg: 背景图片
tp: 缺口图片
'''
# 读取背景图片和缺口图片
bg_img = cv2.imread(bg) # 背景图片
tp_img = cv2.imread(tp) # 缺口图片
# 识别图片边缘
bg_edge = cv2.Canny(bg_img, 100, 200)
tp_edge = cv2.Canny(tp_img, 100, 200)
# 转换图片格式
bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
# 缺口匹配
res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
# 寻找最优匹配
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# 左上角点的坐标
tl = max_loc
# 返回缺口的X坐标
return tl[0]
if __name__ == "__main__":
# 接收两个参数
# 第一个为背景图片地址
# 第二个为缺口图片地址
identify_gap('bg_image.png','slide_image.png')
滑动轨迹(track值)生成:
# -*- coding: utf-8 -*-
import random
def __ease_out_expo(x):
if x == 1:
return 1
else:
return 1 - pow(2, -10 * x)
def __ease_out_quart(x):
return 1 - pow(1 - x, 4)
def get_slide_track(distance):
"""
根据滑动距离生成滑动轨迹
:param distance: 需要滑动的距离
:return: 滑动轨迹<type 'list'>: [[x,y,t], ...]
x: 已滑动的横向距离
y: 已滑动的纵向距离, 除起点外, 均为0
t: 滑动过程消耗的时间, 单位: 毫秒
"""
if not isinstance(distance, int) or distance < 0:
raise ValueError(f"distance类型必须是大于等于0的整数: distance: {distance}, type: {type(distance)}")
# 初始化轨迹列表
slide_track = [
[random.randint(20, 60), random.randint(10, 40), 0]
]
# 共记录count次滑块位置信息
count = 30 + int(distance / 2)
# 初始化滑动时间
t = random.randint(50, 100)
# 记录上一次滑动的距离
_x = 0
_y = 0
for i in range(count):
# 已滑动的横向距离
x = round(__ease_out_expo(i / count) * distance)
# 滑动过程消耗的时间
t = random.randint(10, 20)
if x == _x:
continue
slide_track.append([x - _x, _y, t])
_x = x
slide_track.append([0, 0, random.randint(200, 300)])
return slide_track
if __name__ == '__main__':
s = []
for _ in get_slide_track(105):
s.append(_)
print(s)
这份轨迹也是在csdn找到的,博主叫做带泪的鱼
验证一下是否能通过,成功通过
总结
极验四代相对来说还是比较简单的,主要是思路和方法,如果有哪里写的不对,欢迎大佬指点交流。