少女祈禱中...
Loading...

ccloli

cc是个loli,你也可以叫她傲娇

使用 canvas 破解简单验证码

首先,其实这玩意并不算是完全的破解,因为它还需要人工录入的过程,而不是机器自动识别。如果是机器自动识别的话,那该是神经网络了吧——后文会给出一个别人写的例子……话说 CoffeeScript 是什么……

其次,这玩意只能破解非常简单的验证码,也就是那些出现位置固定、没有任何变形和干扰线,甚至颜色差别都不大的验证码,所以像下面这样的验证码还是洗洗睡吧,虽然还是可以识别出验证码的部分,但是识别的话……(canvas 阈值化 by 8q,咳咳,当然 example 也是我们参与的某个玩意的验证码,传说中的自黑

D2YUWF`3L(81`SZ{92TRV4U7O[W~8}V`YA3{]HTN1Z4A_K

再次,每个网站的验证码风格是不一样的,所以基本很难做到一个程序通杀所有验证码。如果真的有这么想过的话,真的可以洗洗睡了……中文验证码祝你好运……

最后,由于源码是手机码的,所以缩进不统一什么的 _(:3」∠)_……

其实陷入这个坑完全是由于自己的自大 _:3」∠)_ 嘛,具体发生了什么看过之前的文章的同学应该知道,如果不知道的还是最好不要知道了,过去了就过去吧……

首先,让我们看看这个简单的验证码……

可以发现这些验证码组成比较单一,干扰点与验证码颜色区分明显,位置也没有多大变化。

然后我们百度一下,发现用 canvas 破解验证码的还不少,例如 紫云飞大神的这篇文章 与上图基本符合,而国外也有类似的破解某网盘的验证码的脚本,解析原理的文章 思路也是类似的。

接下来,我们先来简单了解一下这里用到的 canvas 的几个用法……其实我了解这玩意是看 阮一峰的 JavaScript 标准参考教程里的 canvas 一节 才知道的,感兴趣可以看看,看完大概十分钟的样子。

首先我们需要将图片插入页面或者 new Image() 并绑定 onload 事件,然后我们需要一个画布,创建一个 canvas 并获取 context,然后进行初始化。

这样在页面内你就会看见一张绘制了图片的 canvas 了。

接下来是尝试阈值化,首先我们需要获取 canvas 内的图像数据,可以用 getImageData 方法载入这些数据,返回的是一个伪数组,每四个值对应 canvas 对应像素点的 rgba 值。所以我们可以根据此,用合适的计算方法将其转换为一张只有黑色和白色的图片,这便是阈值化。关于阈值的定义请百度一下,这里由于没有百度所以简单粗暴地判断了一下 rgb 之和。

这样我们便得到了一张黑白图片,演示效果如下:
Screenshot_2014-10-28-16-14-19

嗯,接下来实战演示,通过绘制矩形一步步确定验证码的位置。这是获取图片位置的效果,为了确定验证码位置,我们使用了 fillRect 方法绘制矩形:

p5

然后用上面的代码取得每个字符对应的区域的 image data,并转换为一组只有 0 和 1 的字符串,手动录入文字并保存。当时测试的源码如下:

最后得到了这样一堆玩意……

接下来把代码改改,就可以用这些数据识别验证码了,这样只要字符串对应的文本相同就可以匹配到对应的字符。可是,准确率不高啊,有些字识别不出来……

20141125121744

(于是写到两点半才写到这还没写完 _(:3」∠)_ 本子已经强制关机了……)

刚开始估计有可能是字符有些许移位,所以尝试统计每个字对应的字符串中 1 的个数,不过看来我想太多了,因为 1 相同的字符数略多,例如 1 出现了 55 次的就有 4 个字符对应……

所以这个方法得到的文本并不准确,于是有想将选区进行适当移位,直至字符串匹配……

咳咳,当然还是惨不忍睹……看来这算法还是不科学啊……再尝试字符串一个一个文字匹配……呵呵了 orz……

仔细思考后,考虑到有可能是生成图片的噪点覆盖了部分字符,导致无法完全匹配。所以我们尝试将生成的字符串分割成好几段,对每一段字符串进行匹配,取匹配次数最多的字符,最后终于做到了几乎 100% 匹配。

咳咳,由于完成之后没几分钟验证码机制就改了,所以没法做更多的测试了,不过在测试的验证码中都完全识别了出来。

最后附识别源码,只是前面的源码改了一下而已。

附录:

1. 使用神经网络破解验证码的脚本 http://userscripts-mirror.org/scripts/show/183059

2. 另一个类似的例子 http://www.cnblogs.com/gdut-link/archive/2013/01/25/2876697.html

3. 刚刚 Google 一下似乎还看到了破解拖动图片验证码的玩意,感兴趣可以看看 http://my.oschina.net/u/237940/blog/337194

  1. 文科说道:

    哇 ,好厉害。

    Unknown Unknown Unknown Unknown
  2. JerryLocke说道:

    _(:зゝ∠)_手机代码菊苣

    Google Chrome 39.0.2171.65 Google Chrome 39.0.2171.65 Windows 8.1 x64 Edition Windows 8.1 x64 Edition
  3. 8q说道:

    rgb不算标准差直接加和真的没问题吗……

    Google Chrome 26.0.1399.0 Google Chrome 26.0.1399.0 Windows XP Windows XP
    1. 864907600cc说道:

      当时是不知道什么是阈值所以简单粗暴的 rgb 相加 _(:3」∠)_ 实现功能就好,算法什么的……

      Google Chrome 39.0.2171.65 Google Chrome 39.0.2171.65 Windows 8.1 x64 Edition Windows 8.1 x64 Edition
  4. 千与琥珀说道:

    原来用的是二值化的处理方法,噪点处理的不错

    Google Chrome 39.0.2171.71 Google Chrome 39.0.2171.71 Windows 7 Windows 7
    1. 864907600cc说道:

      前三张图不是我做的 _(:3」∠)_

      Google Chrome 39.0.2171.71 Google Chrome 39.0.2171.71 Windows 8.1 x64 Edition Windows 8.1 x64 Edition
  5. 说道:

    ヾ(:3ノシヾ)ノシ不愧是cc菊苣QAAQ

    Google Chrome 39.0.2171.71 Google Chrome 39.0.2171.71 GNU/Linux x64 GNU/Linux x64
  6. 不错,收藏以后学习学习~

    Firefox 33.0 Firefox 33.0 GNU/Linux x64 GNU/Linux x64
  7. Taobeier说道:

    CoffeeScript 是我大Ruby党开发时候的利器. 用近乎Ruby/Python的语法而不用写原生的js , 简直爽!

    Google Chrome 38.0.2125.104 Google Chrome 38.0.2125.104 GNU/Linux x64 GNU/Linux x64
  8. 说道:

    菊苣!

    Google Chrome 38.0.2125.111 Google Chrome 38.0.2125.111 Windows 8.1 x64 Edition Windows 8.1 x64 Edition
  9. koi说道:

    juju!

    Google Chrome 39.0.2171.95 Google Chrome 39.0.2171.95 Mac OS X  10.10.1 Mac OS X 10.10.1
  10. Archeb说道:

    赞一个
    其实我也有挺完整的思路不过不打算做这样的东西。。

    Google Chrome 37.0.2062.120 Google Chrome 37.0.2062.120 Mac OS X  10.10.2 Mac OS X 10.10.2
  11. Kunr说道:

    不愧是CC菊苣

    Google Chrome 40.0.2214.111 Google Chrome 40.0.2214.111 GNU/Linux x64 GNU/Linux x64
  12. Indeed说道:

    我想到众复旦魔们破解选课验证码的故事了

    Google Chrome 41.0.2272.101 Google Chrome 41.0.2272.101 Mac OS X  10.10.2 Mac OS X 10.10.2