最后,谈谈滑动验证码。
目前,工商网站已经全面改版,全部采用了滑动验证码,上面绝大多数思路都失效了。对于滑动验证码,网上能搜到的解决方案基本都是下载图片,还原图片,算出滑动距离,然后模拟js来进行拖动解决,我们来看下能否不模拟拖动来解决这个问题。
以云南工商网站为例,首先抓包看过程。
1. http://yn.gsxt.gov.cn/notice/pc-geetest/register?t=147991678609,response:
2. 下载验证码图片
3. http://yn.gsxt.gov.cn/notice/pc-geetest/validate, post如下数据:
4. http://yn.gsxt.gov.cn/notice/search/ent_info_list,post如下数据:
仔细分析,我们发现两处疑点:
1. 第一步并没有返回需要下载的图片地址,那么前端怎么知道要下载哪些图片?
2. 第三步验证时,并没有告知后端下载了那些图片,后端是怎么验证post过去的数据是有效性的?
仔细阅读前端混淆的js代码,我们发现前端数据处理过程是这样的:
1. 从0到6(不含)中取随机整数,赋值给d, d=5;
2. 从0到300(不含)中取随机整数,赋值给e, e=293;
3. 将d转化为字符串并作MD5加密,加密字符串取前9位赋值给f, f=’e4da3b7fb’;
4. 将e转化为字符串并作MD5加密,加密字符串从第11位开始取9位赋值给g, g=’43be4f209’;
5. 取f的偶数位和g的奇数位组成新的9位字符串给h, h=’e3de3f70b’;
6. 取h的后4位与200做MOD运算,其结果小于40,则取40,否则取其本身赋值给x,x=51;
7. 取[x-3, x+3]以内随机数赋值给c,c=51;
8. 分别取c,d,e跟challenge做t加密(t(c,challenge), t(d, challenge), t(e,challenge))并用(_)拼接即为geetest_validate, ‘9ccccc997288_999c9ccaa83_999cc9c9999990d’
这里f, g参数决定了下载图片地址:
而x为滑块拖动的横向偏移量,至此解答了疑问1中图片下载地址怎么来的问题。
前边提到的t加密过程是这样的:
t(a,b),此处以a=51演示
1. challenge为34位16进制字符串,取前32位赋值给prefix,后2位赋值给suffix,prefix=’34173cb38f07f89ddbebc2ac9128303f’, suffix=’a8′
2. prefix去重并保持原顺序,得到列表 [‘3’, ‘4’, ‘1’, ‘7’, ‘c’, ‘b’, ‘8’, ‘f’, ‘0’, ‘9’, ‘d’, ‘e’, ‘2’, ‘a’]
3. 将2中列表循环顺序放入包含5个子列表的列表中,得到random_key_list: [[‘3’, ‘b’, ‘d’], [‘4’, ‘8’, ‘e’], [‘1’, ‘f’, ‘2’], [‘7’, ‘0’, ‘a’], [‘c’, ‘9’]]
4. 将suffix字符串(16进制)逐位转化为10进制,得到[10, 8]
6. 将4中列表逐位与[36,0]做乘法和运算并与a的四舍五入结果相加, n= 51 + 36*10 + 0*8=419
7. q=[1,2,5,10,50], 用q对n做分解(n=50*13+10*0+5*1+2*1+1*1),将其因数倒序赋值给p,p=[0,2,1,1,8]
8. 从random_key_list右侧开始随机取值,次数为p中数值,拼成字符串sub_key,sub_key=’9ccccc997288′
至此,我们完成了整个分析过程,我们又有了新发现:
1. 按照前边的抓包过程,其实不需要真的下载图片,只需执行1、3、4步就可以得到目标数据了。步骤1也可以不要,只需3、4即可,但是少了步骤1, 我们还需要额外请求一次cookie,所以还是保留1, 这样也伪装的像一点嘛。
2. 相同的challenge,每次运算都可以得出不同的validate和seccode,那么问题来了:到底服务端是怎么根据challenge验证其他数据是否有效呢?
总结一下,对于验证码,本文只是提供了一种新的思路,利用了网站开发过程中的一点小疏漏,而最后的滑动验证码也只是分析了offline模式的验证方法。不要指望所有验证码都可以能绕过,没有阿登高地,二战德国就不打法国了么?只要觉得有价值,即使正面面对验证码,作为爬虫工程师建议也就一句话:不要怂,就是干!