Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4450513
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: 网络与安全

2016-10-08 18:28:59

原文地址:
作者:Jonathan LEI
链接:
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

(请原谅我的配图,毕竟是用MSPaint画的)

总算要开始讲解图片还原了。我们首先看看GeeTest自己是如何实现网页上的图片还原的:

打开DOM Explorer,点击Ctrl+B开始选择元素,把指针放到滑块上,待图像出现后点击:

然后在DOM里,我们可以看到如下的结构:

是的,GeeTest并没有在网页上还原这个图片,而是通过放置2行26列的52个10px*58px的div元素,将这些元素的背景统统设为被打乱的图片,并设置相应的背景偏移,以达到看上去图像被还原的效果。

于是,问题的关键落在了这些偏移值是如何计算的上面。只要能找到偏移值的计算方法,我们就可以模拟出这个算法,真正地还原这张图片。

留意到每个div的class都是gt_cut_fullbg_slice,在Debugger中搜索,出来的结果却全是CSS。

我们要找的可是JavaScript啊,看来gt_cut_fullbg_slice并没有完整地在JS中出现,说明它是由几个部分相连而成的。而这里面最需要被替换的估计是fullbg,于是搜索_slice,在几个结果中,我们能发现下面这个才是我们真正需要的:

从这里我们可以整理出这样的代码:

for (o.className = "gt_cut_" + b + "_slice", i = 0, j = n.length; j > i; i++) k = "-" + (n[i] % 26 * 12 + 1) + "px " + (n[i] > 25 ? -f.config.height / 2 : 0) + "px", m = o.cloneNode(), m.style.backgroundImage = "url(" + c + ")", l.push(m), e.appendChild(m), m.style.backgroundPosition = k 

JavaScript的语法真是相当随意啊????,这也是我不喜欢它的原因之一。这里面其它的代码都自己理解一下吧,我们关注的重点在k上,因为k显然是一个代表了位移的字符串:

k = "-" + (n[i] % 26 * 12 + 1) + "px " + (n[i] > 25 ? -f.config.height / 2 : 0) + "px" 

这里总共有两个值,第一个值是x方向偏移,第二个是y方向偏移。其余的部分和C#一样都很好理解,问题只有两个:

  • n是什么?
  • f.config.height是什么?

为了解决这两个问题,我们在这里下个breakpoint。记住要通过右键添加breakpoint,而不是直接在左侧点击。原因是这里的代码经过了混淆,整个文件只有一行,直接在左边点击出来的断点不一定出现在你想要的位置。

重新进入页面,我们首先看看什么是f.config吧:

这东西...似曾相识啊...这不就是我们上次3号包的返回结果吗!

好了第二个问题解决了,我们来看第一个,看看n是什么:

这样一来,这个数组就成了问题的关键,我们需要继续追查这个数组的来源,实际上它就在for的前一句里:

var m,n=a(),o=document.createElement("div"); 

看来n是由一个名为a的函数产生的,我们来看看a是什么。转到Console标签页,输入a然后回车:

function (){for(var a,b="6_11_7_10_4_12_3_1_0_5_2_9_8".split("_"),c=[],d=0,e=52;e>d;d++)a=2*parseInt(b[parseInt(d%26/2)])+d%2,parseInt(d/2)%2||(a+=d%2?-1:1),a+=26>d?26:0,c.push(a);return c} 

这便是a的定义。可以看到,a里面再也没有引用外部变量,也就是说我们的追查到底了。将这个函数翻译为C#并不难,但是懒惰的我选择直接在C#中运行JS解决问题????。

然而还有一个问题,就是这个还原函数是固定的吗,还是每次都不一样?如果搜索那串带下划线的字符串,可以发现这个函数实际上被定义在这里:

而这段代码位于geetest.5.5.9.js文件中,是一个静态JavaScript文件。这下便可以放心了。

如此看来,所有下载的图片都是经过同一个次序打乱的,我们只需要写一次这个还原函数,就能还原所有图片。

至此,对于第二个问题:

  • fullbg和bg通过什么算法还原完整图象?

我们也有了答案,接下来我们就要开始写C#代码实现还原算法,将这些被打乱的图像还原。但是要还原图像我们首先要模拟1、2、3号包并下载图片。对于有网络编程基础的人来说这是小儿科,但为了照顾没有基础的读者,同时也为了有基础读者的使用方便,我会在该系列下一篇文章之前插入我的一个小项目:NetworkHandler。

NetworkHandler一个非常简单的类,但是它能让使用者一句代码完成一个HttpRequest,而不需要设置这个设置那个。而且还有重要的一点,便是原生的CookieContainer中有一个严重的问题。某些网站的Set-Cookie没有按照Standard来设置,它便无法识别。这其实不是CookieContainer的bug,只是网站没有按规矩办事。我的NetworkHandler中通过使用一个List对象解决这个问题。这个项目将在我的GitHub上开源并不断更新,欢迎大家使用和Contribute。

谢谢阅读本文,喜欢的还请关注点赞,谢谢!

阅读(1418) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~