极验三代验证码逆向实战:从抓包到破解w参数的全过程
如果你曾经在某个网站注册或登录时,被要求拖动滑块、点击文字或完成拼图,那么你很可能已经与极验验证码打过交道。作为目前国内应用最广泛的行为验证方案之一,极验三代验证码以其复杂的数据收集和加密机制,成为了许多自动化工具开发者需要跨越的一道门槛。今天,我将带你深入极验三代验证码的内部机制,从最基础的网络请求抓包开始,一步步拆解其核心加密参数w的生成逻辑,最终实现完整的逆向破解。
这篇文章面向的是有一定JavaScript基础和安全研究兴趣的开发者。我不会提供可以直接复制粘贴的完整代码——那样既不利于理解,也容易被滥用。相反,我会详细讲解每个步骤的原理、关键代码片段的分析方法,以及在实际逆向过程中可能遇到的坑。通过这篇文章,你将学会如何像安全研究员一样思考,如何从混乱的混淆代码中找到关键逻辑,如何构造出能够通过验证的合法参数。
1. 环境准备与初步分析
在开始逆向之前,我们需要搭建一个合适的分析环境。与许多教程推荐使用Selenium或Puppeteer不同,我更倾向于使用纯粹的JavaScript调试环境,因为这样可以更清晰地观察代码执行流程,避免浏览器自动化工具带来的额外干扰。
1.1 必要的工具链
首先,确保你的开发环境中安装了以下工具:
- Node.js (v14或更高版本):用于运行JavaScript代码和调试
- Chrome DevTools 或 Firefox Developer Tools:用于网络抓包和JavaScript调试
- Charles 或 Fiddler:可选,用于更详细的HTTP/HTTPS流量分析
- VS Code 或 WebStorm:代码编辑和调试
- Postman 或 curl:用于手动测试API请求
对于代码反混淆,我推荐使用以下工具组合:
# 安装常用的Node.js分析工具
npm install -g js-beautify
npm install -g acorn
npm install -g escodegen
1.2 建立本地代理环境
为了能够拦截和修改极验的JavaScript文件,我们需要设置一个本地代理。这里以Charles为例,但任何支持SSL代理的工具都可以:
- 安装Charles证书:在Charles中,选择Help → SSL Proxying → Install Charles Root Certificate
- 启用SSL代理:Proxy → SSL Proxying Settings,添加
*.geetest.com到列表 - 设置浏览器代理:将浏览器代理设置为Charles的监听端口(默认8888)
注意:某些网站可能会检测代理环境,在实际操作中可能需要更隐蔽的代理设置方式。
1.3 目标网站选择
为了遵守法律法规和道德准则,我们选择极验官方的演示页面作为分析目标:
https://www.geetest.com/demo/
这个页面包含了极验的各种验证模式,我们可以在这里安全地进行技术研究。打开页面后,选择“滑动验证”模式,准备开始我们的分析工作。
2. 网络请求流程深度解析
极验验证码的完整流程涉及多个HTTP请求,每个请求都有特定的目的和参数。理解这个流程是逆向成功的第一步。
2.1 初始请求链分析
打开浏览器开发者工具的网络面板,清空记录,然后点击验证码触发验证流程。你会看到类似以下的请求序列:
| 请求顺序 | 接口路径 | 关键参数 | 返回数据 | 作用 |
|---|---|---|---|---|
| 1 | /gettype.php |
gt, callback |
验证类型和JS文件路径 | 确定验证模式 |
| 2 | /get.php (第一次) |
gt, challenge, w |
配置参数和s、c值 |
环境检测和初始化 |
| 3 | /ajax.php (第一次) |
gt, challenge, w |
验证结果或下一步指示 | 无感验证判断 |
| 4 | /get.php (第二次) |
gt, challenge |
图片URL、c、s等 |
获取验证素材 |
| 5 | /ajax.php (第二次) |
gt, challenge, w |
validate值 |
最终验证 |
让我们详细看看每个请求的具体内容。
2.1.1 gettype.php - 确定验证模式
第一个关键请求是gettype.php,它返回当前验证码的类型和需要加载的JavaScript文件:
// 请求示例
GET https://api.geetest.com/gettype.php?gt=25ba81caec944f8d74c98befd841a667&callback=geetest_1627891234567
// 响应示例
geetest_1627891234567({
"status": "success",
"data": {
"type": "slide",
"fullpage": "/static/js/fullpage.9.0.9.js",
"slide": "/static/js/slide.7.8.6.js",
"static_servers": ["static.geetest.com", "dn-staticdown.qbox.me"]
}
})
这里的gt参数是网站的唯一标识,由极验分配给每个客户。callback参数是一个JSONP回调函数名,用于跨域请求。
2.1.2 第一次get.php - 环境检测
这个请求携带了第一个w参数,这是环境检测的关键:
// 请求参数
{
"gt": "25ba81caec944f8d74c98befd841a667",
"challenge": "61f4492c9e8ea1e136e98b38107d561e",
"lang": "zh-cn",
"pt": 0,
"client_type": "web",
"w": "Wt(lNJWNy9DeW5Z6nJck3NZCQaoyQdi3TTcxtdnFpU65OTMLZvjnrK9bgDx94DdhAlV0bvg61eh)qX0m(bWYmvFzG84QiCW7S5tLICB4QMC(zoR0YLHui9VVj6iJwWEK9lFIqklAGbsFUYHM3GEGr6mrnflcVvbIyyo8SJGIF4j70VqCLwmmcChYl4TX9GZQb0pN0)dJHSIJucHlyrrxhSpqk4b(ox65Ur4IX)De0of3r6WB78QI7)XNqxKheWL(L7peMT)f(bIl6ut5S1gO7d9dRSSZac9SjtQGUfXPNHtbm1tOts(zRdjihk8z)Zfsh)JFqM4QQgrhnd6wBOQ8pyv60bjgpONQeJdKnNBIb(SXgo)flKztgLn1cehGDcCTTQcNlnWi5E7R)(5X01pqSyc16(8YSj)CXk2T6JHUXCXXFAXrSFWs7noM4IR7KUawc1KLmu4lDLA913wOOGoCv5C06D4D48IkVeDIalagtcLwMVd(S7TAVVwWtxXXzsnxLipWbB9HjYSiYPeg3YzjvnJpbV)oDukpEkYkl2kjs53ucZ8jo33(QE09ubUvMLgQuHwIWOoqaO5VJ4ESffY)87yPJrLJprSRUTYHmuTAo6yyI0OeQGk5CHxx67iHrgzHnNxAAPZY5yrv)CJ3xcBhZgu0tk8lCYgiH1wbigIChhPgd5QTP0nJiOJPgQs76yVkvX7bLEMWJfWjLqIzZ1hd9XQmt)2yGvVLC0iiApcqGuKSvRhxvVrW01WPp6pzFOywFXULhI7vsqUOTvqoNnwJtnSv1b40F)F2y6lC8LRsj1AKBcxREtAtqKvpXOcCFPxT2qMdLKgISgYJ33RVknFDS4JfOhTk9AgXBFtSJ2zM7tpPROoRoBsPVMOrbO)mdip4Z62PxxSDS8cA0PW980wi6ZhaDamumAlxx8RQKLPW587)9Xehn5s6cIMdMFRIAubg0VXlnW5Us2IvKeI6cjEfHNMyCJz4Fmv3)IYsXh3iigq87dCjtkGlGiVTrjjo2q44e(qr0GAo5CrxuKO)EgbdLDAyqf)5WFlSx)VXn5UoZF(AunphgVIn4(vMeFVWN(fWYj(MKztePyzCi2Cdd3pLrrL2IrD7NvNo87wvdX6ro5Q6GVVHP14IvrQsArUDdnIZjz5kMJ0IG0rsd2oQL2XFndtTcuJNlRewL5KYai(K2uPNjCQmXLfEfH2LMIjerHM126aAv5EhwLuFhvxKhIjoEGoQqMGg3FZorOHWIJEt6jSDtKNwLeeUXomknlRtaVwVCJJkrR9MfM8vldLCZ..e581bf73fb48171a223c9fac8fc74f151438380e515f1775cb26d78086253beef82f250f02349285fd86ed2d52d0acb6f45fa1733340ea282c3524c432d93df20d22b28c2c382e1ad52d72b20fcc2104188b7e99d11ca440325cb4391e34d78f2122162d3e3fb3efa810139c6d1f933b1dacfdc1e044686369271275d2ac258a"
}
这个w参数看起来像是一堆乱码,但实际上它包含了浏览器指纹信息、环境数据等。如果这个w参数构造得足够"真实",极验可能会直接返回无感验证通过,跳过滑块验证。
2.1.3 关键响应参数解析
从第一次get.php的响应中,我们需要关注几个重要参数:
{
"status": "success",
"data": {
"c": [12, 58, 98, 36, 43, 95, 62, 15, 12],
"s": "73304840",
"bg": "pictures/gt/7d068eca5/bg/b5afeb19a.jpg",
"fullbg": "pictures/gt/7d068eca5/7d068eca5.jpg",
// ... 其他配置
}
}
c数组:用于图片还原的密钥,后面计算滑块位置时会用到s值:与c配合使用的另一个密钥bg和fullbg:滑块验证的背景图和完整图URL
2.2 图片处理与缺口识别
当进入滑块验证模式时,我们需要处理两张图片:被切割打乱的背景图(bg)和完整的原图(fullbg)。极验使用c数组来控制图片的切割和还原方式。
2.2.1 图片下载与还原
首先,我们需要下载这两张图片:
import requests
from PIL import Image
import io
def download_image(url):
"""下载图片并转换为PIL Image对象"""
response = requests.get(url)
return Image.open(io.BytesIO(response.content))
# 下载图片
bg_image = download_image("https://static.geetest.com/pictures/gt/7d068eca5/bg/b5afeb19a.jpg")
fullbg_image = download_image("https://static.geetest.com/pictures/gt/7d068eca5/7d068eca5.jpg")
2.2.2 使用c数组还原图片
c数组定义了图片的切割和重组方式。下面是一个简化的还原函数:
def restore_image(cut_image, full_image, c_array):
"""
根据c数组还原被切割的图片
参数:
cut_image: 被切割的图片(PIL Image)
full_image: 完整原图(PIL Image)
c_array: 还原数组,如[12, 58, 98, 36, 43, 95, 62, 15, 12]


1万+

被折叠的 条评论
为什么被折叠?



