MyException - 我的异常网
当前位置:我的异常网» JavaScript » 《转》利用JavaScript破译验证码

《转》利用JavaScript破译验证码

www.MyException.Cn  网友分享于:2013-10-10  浏览:23次
《转》利用JavaScript破解验证码

 如今,基于web的应用越来越普及,随之而来的安全威胁也越来越大,近日网上惊现可以破解验证码的JavaScript脚本,可以轻松搞定流行的验证机制CAPTCHA。

<!-- Error -->

  近日,网上惊现可以破解验证码的JavaScript脚本——GreaseMonkey!由“Shaun Friedle”开发的这段脚本可以轻松搞定Megaupload站点的CAPTCHA。如果您不相信的话,可以到http://herecomethelizards.co.uk/mu_captcha/亲自尝试一下!

  现在,Megaupload站点提供的CAPTCHA在上述代码面前已经败下阵来,说实话,这里的验证码设计的不不太好。但更有趣的是:

  1.HTML 5中的Canvas应用程序接口getImageData可以用来从验证码图像中取得像素数据。利用Canvas,我们不仅可以将一个图像嵌入一个画布中,而且之后还可以再从中重新提取出来。

  2.上述的脚本中包含一个完全使用JavaScript实现的神经网络。

  3.使用Canvas从图像中提取出像素数据后,将其送入神经网络,通过一种简单的光学字符识别技术来推测验证码中到底使用了哪些字符。

  通过阅读源代码,我们不仅可以更好地理解其工作原理,也可以领会这个验证码究竟是如何实现的。就像前面看到的那样,这里使用的验证码不是很复杂——每个验证码有三个字符组成,每个字符使用一种不同的颜色,并且只使用26个字母中的字符,而所有字符都使用同一种字体。

  第一步的用意很明显,那就是把验证码拷贝到画布上,并且把它转化为灰度图。

 

      function convert_grey(image_data){
  for (var x = 0; x < image_data.width; x++){
  for (var y = 0; y < image_data.height; y++){
  var i = x*4+y*4*image_data.width;
  var luma = Math.floor(image_data.data[i] * 299/1000 +
  image_data.data[i+1] * 587/1000 +
  image_data.data[i+2] * 114/1000);
  image_data.data[i] = luma;
  image_data.data[i+1] = luma;
  image_data.data[i+2] = luma;
  image_data.data[i+3] = 255;
  }
  }
  }

 

  然后,将画布分成三个单独的像素矩阵,每个矩阵包含一个字符。这一步实现起来非常容易,因为每个字符都使用一种单独的颜色,所以通过颜色就可以将其区分开来。

 

      filter(image_data[0], 105);
  filter(image_data[1], 120);
  filter(image_data[2], 135);
  function filter(image_data, colour){
  for (var x = 0; x < image_data.width; x++){
  for (var y = 0; y < image_data.height; y++){
  var i = x*4+y*4*image_data.width;
  // Turn all the pixels of the certain colour to white
  if (image_data.data[i] == colour) {
  image_data.data[i] = 255;
  image_data.data[i+1] = 255;
  image_data.data[i+2] = 255;
  // Everything else to black
  } else {
  image_data.data[i] = 0;
  image_data.data[i+1] = 0;
  image_data.data[i+2] = 0;
  }
  }
  }
  }

 

  最终,所有无关的干扰像素都被剔除出去。为此,可以先查找那些前面或者后面被黑色(未匹配的)像素围绕的白色(匹配过的)像素,然后将匹配过的像素删除即可。

 

      var i = x*4+y*4*image_data.width;
  var above = x*4+(y-1)*4*image_data.width;
  var below = x*4+(y+1)*4*image_data.width;
  if (image_data.data[i] == 255 &&
  image_data.data[above] == 0 &&
  image_data.data[below] == 0) {
  image_data.data[i] = 0;
  image_data.data[i+1] = 0;
  image_data.data[i+2] = 0;
  }

 

  现在我们已经得到了字符的大约图形,但在将其载入神经网络之前,脚本还会进一步对它进行必要的边缘检测。脚本会寻找图形最左、右、上、下方的像素,并将其转化为一个矩形,接着把矩形重新转换为一个20*25像素的矩阵。

 

      cropped_canvas.getContext("2d").fillRect(0, 0, 20, 25);
  var edges = find_edges(image_data[i]);
  cropped_canvas.getContext("2d").drawImage(canvas, edges[0], edges[1],
  edges[2]-edges[0], edges[3]-edges[1], 0, 0,
  edges[2]-edges[0], edges[3]-edges[1]);
  image_data[i] = cropped_canvas.getContext("2d").getImageData(0, 0,
  cropped_canvas.width, cropped_canvas.height);

 

  经过上面的处理,我们得到了什么呢? 一个20*25的矩阵,其中包含单个矩形,其中填由黑白色。真是太好了!

  然后,会对这个矩形做进一步的简化。我们策略性地从矩阵中提取一些点,作为“光感受器”,这些光感受器将输送到神经网络。举例而言,某个光感受器具体对应的可能是位于9*6位置像素,有像素或者没有像素。脚本会提取一系列这样的状态(远少于对 20*25矩阵整个计算的次数——只提取64种状态),并将这些状态送入神经网络。

  您可能要问,为什么不直接对像素进行比较?有必要使用神经网络吗?问题的关键在于,我们要去掉那些模棱两可的情况。如果您试过前面的演示就会发现,直接进行像素比较比通过神经网络比较,更容易出错,尽管出错的时候不多。但我们必须承认,对于大部分用户来说,直接的像素比较应该已经够用了。

  下一步就是尝试猜字母了。神经网络中导入了64个布尔值(由其中的一个字符图像获取而来),同时包含一系列预先计算好的数据。神经网络的理念之一,就是我们希望得的结果事先就是知道的,所以我们可以针对结果对神经网络进行相关的训练。脚本作者可以多次运行脚本,并收集了一系列最佳评分,这些评分能帮助倒推出产生它们的那些值,从而帮神经网络猜出答案,除此之外,这些评分没有任何特殊意义。

  当神经网络对验证码中一个字母对应的64个布尔值进行计算以后,和一个预先计算好的字母表相比较,然后为和每个字母的匹配都给出一个分数。(最后的结果可能类似:98%的可能是字母A,36%的可能是字母B等。)

  当对验证码中的三个字母都经过处理以后,最终的结果也就出来了。需要注意的是,该脚本无法达到100%正确性(不知道如果在开始的时候不将字母转换成矩形,是不是可以提高评分的精度),但这已经相当好了,至少对于当前的用途来说是这样。而且所有的操作都是在基于标准的客户端技术实现的浏览器中完成的!

  补充说明一下,这个脚本应该算是一个特例吧,这项技术可能会很好的工作在在其它简陋的验证码上,但对于复杂的验证码来说,就有点鞭长莫及了(尤其是这种基于客户端的分析)。但愿有更多人能从这个项目中受到启发而开发出更奇妙的东西来,因为它的潜力实在是太大了。

文章评论

科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
中美印日四国程序员比较
中美印日四国程序员比较
程序员的鄙视链
程序员的鄙视链
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
老程序员的下场
老程序员的下场
那些争议最大的编程观点
那些争议最大的编程观点
代码女神横空出世
代码女神横空出世
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
每天工作4小时的程序员
每天工作4小时的程序员
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
为什么程序员都是夜猫子
为什么程序员都是夜猫子
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
一个程序员的时间管理
一个程序员的时间管理
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
漫画:程序员的工作
漫画:程序员的工作
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
旅行,写作,编程
旅行,写作,编程
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
编程语言是女人
编程语言是女人
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
我是如何打败拖延症的
我是如何打败拖延症的
如何成为一名黑客
如何成为一名黑客
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
10个调试和排错的小建议
10个调试和排错的小建议
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
 程序员的样子
程序员的样子
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序员和编码员之间的区别
程序员和编码员之间的区别
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
程序员都该阅读的书
程序员都该阅读的书
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序员必看的十大电影
程序员必看的十大电影
总结2014中国互联网十大段子
总结2014中国互联网十大段子
Java程序员必看电影
Java程序员必看电影
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有