1- ## GeeTest滑块验证码offline模式的破解
1+ # GeeTest滑块验证码offline模式的分析
2+
23GeeTest滑块验证码通过机器学习检查鼠标行为轨迹,识别人工或机器行为。
34online在线验证的流程,目前最全面的分析文档详见 [ https://zhuanlan.zhihu.com/windev ] ( https://zhuanlan.zhihu.com/windev ) 。
45online模式的验证流程,网站后台与GeeTest后台 [ http://api.geetest.com ] ( http://api.geetest.com ) 进行通讯验证。浏览器前端仅做数据采集和简单加密传输。
56offline模式的离线验证,网站后台自行验证,GeeTest后台 [ http://static.geetest.com ] ( http://static.geetest.com ) 仅提供滑块验证码图片下载功能。浏览器前端做数据采集和本地验证。
67在安全性上,online模式相对非常可靠,offline模式仅仅是障眼法。
78
8- ### 1. 测试网站
9- 以[ 国家企业信用信息公示系统] ( http://www.gsxt.gov.cn ) 为例:
10- 主站使用geetest 5.10.10 online 在线验证模式。各省市站点使用的版本和模块略有差异。
11- ** geetest offline 5.9.0**
9+ ### 1. 测试网站
10+
11+ 以[ 国家企业信用信息公示系统] ( http://www.gsxt.gov.cn ) 为例:主站使用 geetest 5.10.10 online 在线验证模式。各省市站点使用的版本和模块略有差异。
12+
13+ ** geetest offline 5.9.0**
14+
1215+ 上海
1316+ 河北
1417+ 内蒙古
@@ -25,76 +28,108 @@ offline模式的离线验证,网站后台自行验证,GeeTest后台 [http://
2528+ 青海
2629+ 宁夏
2730
28- ** geetest offline 5.10.10**
31+ ** geetest offline 5.10.10**
32+
2933+ 贵州
3034+ 陕西
3135
3236### 2. offline模式验证流程
33- 以上海站点为例 [ http://sh.gsxt.gov.cn ] ( http://sh.gsxt.gov.cn )
34- #### 2.1 GET 首页 http://sh.gsxt.gov.cn/notice/
35- 返回HTML页面,解析得到session.token。
36- #### 2.2 GET register http://sh.gsxt.gov.cn/notice/pc-geetest/register
37+
38+ 以[ 上海站点] ( http://sh.gsxt.gov.cn ) 为例。
39+
40+ #### 2.1 GET 首页 http://sh.gsxt.gov.cn/notice/
41+
42+ 返回HTML页面,解析得到session.token。
43+
44+ #### 2.2 GET register http://sh.gsxt.gov.cn/notice/pc-geetest/register
45+
3746返回JSON数据
38- ```
47+
48+ ``` json
3949{
40- "success":0,
41- "gt":"39134c54afef1e0b19228627406614e9",
42- "challenge":"d2ddea18f00665ce8623e36bd4e3c7c543"
50+ "success" :0 ,
51+ "gt" :" 39134c54afef1e0b19228627406614e9" ,
52+ "challenge" :" d2ddea18f00665ce8623e36bd4e3c7c543"
4353}
4454```
55+
4556success = 0 表示启用 offline 验证模式。
46- #### 2.3 POST http://sh.gsxt.gov.cn/notice/security/verify_ip
47- 返回200 True,表示成功。
48- #### 2.4 POST http://sh.gsxt.gov.cn/notice/security/verify_keyword
49- 返回200 True,表示成功。
50- #### 2.5 POST http://sh.gsxt.gov.cn/notice/pc-geetest/validate
57+
58+ #### 2.3 POST http://sh.gsxt.gov.cn/notice/security/verify_ip
59+
60+ 返回200 True,表示成功。
61+
62+ #### 2.4 POST http://sh.gsxt.gov.cn/notice/security/verify_keyword
63+
64+ 返回200 True,表示成功。
65+
66+ #### 2.5 POST http://sh.gsxt.gov.cn/notice/pc-geetest/validate
67+
5168上传滑块验证码的本地验证结果数据,简称validate。返回JSON数据
52- ```
69+
70+ ``` json
5371{
54- "status":"success",
55- "version":"3.3.0"
72+ "status" :" success" ,
73+ "version" :" 3.3.0"
5674}
57- ```
58- offline模式,后台根本不知道浏览器使用哪张滑块验证码图片,只知道浏览器上传了验证结果的数据。所以完全可以省略下载验证码图片,进行图像识别,计算滑块移动位置,模拟鼠标滑动轨迹这些步骤。
59- ** 验证数据的格式**
60- 例如:1517aab3f_51aa460f_75555a6a38,其中以_分隔的3段数据是由geetest.5.x.x.js中的distance, rand0, rand1加密混淆得到。
61- 具体加密过程分析详见 [ 寻找阿登高地——爬虫工程师如何绕过验证码] ( http://www.jianshu.com/p/5b6fb04ea686 ) 。
62- 其实不用关心加密算法的实现细节,只需找到JavaScript调用入口,传入参数执行即可:
6375```
76+
77+ offline模式,后台根本不知道浏览器使用哪张滑块验证码图片,只知道浏览器上传了验证结果的数据。所以完全可以省略下载验证码图片,进行图像识别,计算滑块移动位置,模拟鼠标滑动轨迹这些步骤。
78+
79+ ** 验证数据格式**
80+
81+ 例如:` 1517aab3f_51aa460f_75555a6a38 ` ,其中以 ` _ ` 分隔的3段数据是由 ` geetest.5.x.x.js ` 中的 distance, rand0, rand1 加密混淆得到。
82+ 具体加密过程分析详见 [ 寻找阿登高地——爬虫工程师如何绕过验证码] ( http://www.jianshu.com/p/5b6fb04ea686 ) 。
83+ 其实不用关心加密算法的实现细节,只需找到JavaScript调用入口,传入参数执行即可:
84+
85+ ``` javascript
6486function userresponse (a , b ) {
65- for (var c = b.slice(32), d = [], e = 0; e < c.length; e++) {
66- var f = c.charCodeAt(e);
67- d[e] = f > 57 ? f - 87 : f - 48
68- }
69- c = 36 * d[0] + d[1];
70- var g = Math.round(a) + c; b = b.slice(0, 32);
71- var h, i = [ [], [], [], [], [] ], j = {}, k = 0; e = 0;
72- for (var l = b.length; e < l; e++)
73- h = b.charAt(e), j[h] || (j[h] = 1, i[k].push(h), k++, k = 5 == k ? 0 : k);
74- for (var m, n = g, o = 4, p = "", q = [1, 2, 5, 10, 50]; n > 0;)
75- n - q[o] >= 0 ? (m = parseInt(Math.random() * i[o].length, 10), p += i[o][m], n -= q[o]) : (i.splice(o, 1), q.splice(o, 1), o -= 1);
76- return p
87+ for (var c = b .slice (32 ), d = [], e = 0 ; e < c .length ; e++ ) {
88+ var f = c .charCodeAt (e);
89+ d[e] = f > 57 ? f - 87 : f - 48
7790 }
91+ c = 36 * d[0 ] + d[1 ];
92+ var g = Math .round (a) + c; b = b .slice (0 , 32 );
93+ var h, i = [ [], [], [], [], [] ], j = {}, k = 0 ; e = 0 ;
94+ for (var l = b .length ; e < l; e++ )
95+ h = b .charAt (e), j[h] || (j[h] = 1 , i[k].push (h), k++ , k = 5 == k ? 0 : k);
96+ for (var m, n = g, o = 4 , p = " " , q = [1 , 2 , 5 , 10 , 50 ]; n > 0 ;)
97+ n - q[o] >= 0 ? (m = parseInt (Math .random () * i[o].length , 10 ), p += i[o][m], n -= q[o]) : (i .splice (o, 1 ), q .splice (o, 1 ), o -= 1 );
98+ return p
99+ }
78100```
79- ** 3个参数的正确生成**
101+
102+ ** 3个参数的正确生成**
103+
80104distance,rand0,rand1,这3个参数都是随机生成,但是如果写代码直接随机生成,会发现验证成功率不高,那么这3个参数之间存在什么隐藏关联关系?后台是如何校验这3个随机数的正确性?
81105其实它们之间存在什么关系不重要,重要的是能够成功通过验证。
82106只需人工采样N次,构造足够的样本数组,每次随机选取1个,调用JavaScript加密方法,得到验证数据即可。
83- #### 2.6 POST http://sh.gsxt.gov.cn/notice/search/ent_info_list
107+
108+ #### 2.6 POST http://sh.gsxt.gov.cn/notice/search/ent_info_list
109+
84110上传session.token(步骤1获得),challenge(步骤2获得),validate(步骤5计算),keyword(查询关键字),返回HTML页面,解析DOM结构,即可获得查询结果和session.token的更新(用于下一次查询)。
85- ### 3. 源码见GitHub
86- https://github.com/9468305/python-script/tree/master/geetest_offline , Python 3.6
87- Install:
88- ```
111+
112+ ### 3. 源码
113+
114+ Python 3.6
115+
116+ Install:
117+
118+ ``` bash
89119pip install requests # HTTP Request库
90120pip install PyExecJS # Python调用JavaScript, 配合node.js更佳
91121pip install beautifulsoup4 # 解析HTML页面
92122```
123+
93124Demo:
94- ```
125+
126+ ``` bash
95127python ./geetest_offline.py
96128python ./geetest_offline_nm.py
97129```
98- Entry Code:
99- [ geetest_offline.py] ( /geetest_offline/geetest_offline.py ) for 上海,河北。
100- [ geetest_offline_nm.py] ( /geetest_offline/geetest_offline_nm.py ) for 内蒙古,HTTP Request&Response 略有不同。
130+
131+ #### Entry Code
132+
133+ [ geetest_offline.py] ( /geetest_offline/geetest_offline.py ) for 上海,河北。
134+
135+ [ geetest_offline_nm.py] ( /geetest_offline/geetest_offline_nm.py ) for 内蒙古,HTTP Request&Response 略有不同。
0 commit comments