教你如何利用机器学习破解网站验证码

相信每个人都对验证码没有好感——你必须输入图像里的文本,然后才能访问网站。验证码的设计是为了防止计算机自动填写表格,以此验证你是一个真实的人。但随着深度学习和计算机视觉的兴起,它们现在已经变得脆弱不堪。

我一直在读一本由Adrian Rosebrock写的《Deep Learning for Computer Vision with Python》(用Python实现机器视觉的深度学习)。在这本书中,Adrian通过机器学习,在E-ZPass纽约网站上绕过了验证码阶段:

Adrian没有访问生成验证码图像的应用程序的源代码。为了打破这个系统,他不得不下载数百个示例图像,并手动输入每个图像对应的验证码来训练他的系统。

但是,如果我们想要破坏一个开源的验证码系统,在哪里我们可以访问源代码呢?

我在WordPress.org网站(一个插件下载网站)上搜索了“captcha”。网页置顶的搜索结果为“Really Simple CAPTCHA”(“真正简单的验证码”,一个验证码生成插件),其活跃安装次数超过100万:

最棒的是,我们可以利用它获得生成验证码的源代码,所以这应该很容易被打破。为了使任务更有挑战性,我决定给自己一个时间限制。15分钟内,能否彻底破解这个验证码系统?擦亮眼睛看吧!

重要提示:这绝不是对该插件或其作者的挑衅或某种程度上的鄙视。插件作者自己也说它已经不安全了,建议你使用其他东西。这只是一个有趣和快速的技术挑战,但如果你是其100万用户之一,或许你应该换一个插件了:)

挑战开始

为方便定制攻击计划,我们首先看一下该插件会生成什么样的图像。在演示网站上,我们看到:

验证码图像展示

从图像看来,验证码明显是四个字母,不过我们要在PHP源代码中验证这一点:

是的,它使用4种不同字体的随机组合生成4个字母的验证码。我们可以看到,在代码中它从不使用“O”或“I”,以避免用户混淆。这就给我们留下了32个可能的字母和数字。

目前记时:2分钟

我们的工具集

在我们进一步讨论之前,先来罗列一下解决这个问题的工具:

Python 3

Python是一种很有趣的编程语言,有很好的机器学习和计算机视觉库。

OpenCV

OpenCV是一个流行的计算机视觉和图像处理框架。我们将使用OpenCV来处理验证码图像。它有一个Python API,所以我们可以直接从Python中使用它。

Keras

Keras是一个用Python编写的深度学习框架。它能够以最少的代码定义、训练和使用深度神经网络。(这个评价可能不够客观。)

TensorFlow

TensorFlow是谷歌的机器学习库。我们会在Keras中编码,但是Keras并没有真正实现神经网络逻辑本身。因此,它使用谷歌的TensorFlow库来完成繁重的任务。

好的,回到挑战!

创建数据集

训练任何机器学习系统,我们都需要训练数据。要破解验证码系统,我们需要这样的训练数据:

因为我们有了该插件的源代码,所以我们可以通过修改它来保存10000个验证图像,以及每个图像的预期答案。

在对代码进行了几分钟的黑客攻击并添加了一个简单的for循环之后,我有了一个包含训练数据的文件夹—10,000个PNG文件,每个文件都有正确的答案作为文件名:

目前记时:5分钟

简化这个问题

现在我们有了训练数据,我们可以直接用它来训练神经网络:

如果有足够的训练数据,这种方法甚至可能直接产生效果——但我们要使问题变得更简单。问题越简单,训练数据越少,我们解决它所需的计算能力就越小。毕竟只有15分钟!

幸运的是,验证码图像通常只由四个字母组成。如果我们能把图像分割开来,这样每个字母都是一个单独的图像,那么我们只需训练神经网络一次识别单个字母:

我没有时间去挨个查看10000个训练图像,然后用Photoshop将它们手工分割成不同的图像。这需要几天的时间,我只剩下10分钟了。我们不能将图像分割成4个等分大小的块因为验证码随机将字母放置在不同的水平位置,以防止出现这样的情况:

每个图像中的字母都是随机放置的,使图像分割变得更加困难。

幸运的是,我们仍然可以实现自动化。在图像处理中,我们经常需要检测具有相同颜色的像素的“blob”。这些连续像素点的边界称为轮廓。OpenCV有一个内置的findContours()函数,我们可以用来检测这些连续区域。

我们将从一个原始的验证码图像开始:

然后我们将图像转换成纯黑和白(这称为阈值化),这样就很容易找到连续区域:

接下来,我们将使用OpenCV的findContours()函数来检测图像中包含相同颜色连续的像素点的图像的不同部分:

然后这就变成了一个简单的问题,可以把每个区域作为一个单独的图像文件保存。因为我们知道每个图像应该包含四个从左到右的字母,所以我们可以用这些知识来标记我们保存的字母。只要我们按这个顺序把它们存起来,应该就可以用正确的字母名称来保存每一个图像字母。

但是等一下——我发现问题了!有时验证码有这样重叠的字母:

这意味着我们最终会将两个字母组合成一个区域。

如果我们不处理这个问题,我们就会产生“很脏”(dirty)的训练数据。我们需要解决这个问题,防止机器接受训练后仍然靠运气识别这两个重叠在一起的字母。

这里有一个简单的窍门:如果一个等高线区域比它的高度宽得多,那就意味着可能有两个字母在一起被压扁了。在这种情况下,我们可以把这两个字母放在中间,把它分成两个独立的字母:

我们将把比它们高得多的区域分割成两半,把它看成两个字母。这里有黑客行事风格的嫌疑,但是对于验证码来说,它是可行的。

现在我们有了一种提取单个字母的方法,接下来在所有的验证码图像中运行这个方法。目的是收集每个字母的不同变体。我们可以把每个字母都保存在自己的文件夹里,井井有条。

这是我摘取所有字母后的“W”文件夹的图像:

从我们的10,000个验证码图像中提取的一些“W”字母。我最终得到了1,147个不同的“W”图像。

目前记时:10分钟

建立和训练神经网络

因为我们只需要识别单个字母和数字的图像,我们就不需要一个非常复杂的神经网络结构。识别字母比识别像猫和狗这样的复杂图像要容易得多。

我们将使用一个简单的卷积神经网络结构,它有两个卷积层和两个完全连通的层:

如果你想知道更多关于卷积神经网络的工作原理以及为什么它们是图像识别的理想方法,请查阅Adrian的书。

定义这个神经网络体系结构只需要使用Keras的几行代码:

  1. # Build the neural network! 
  2. model = Sequential() 
  3. First convolutional layer with max pooling 
  4. model.add(Conv2D(20, (5, 5), padding="same", input_shape=(20, 20, 1), activation="relu")) 
  5. model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2))) 
  6. Second convolutional layer with max pooling 
  7. model.add(Conv2D(50, (5, 5), padding="same", activation="relu")) 
  8. model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2))) 
  9. # Hidden layer with 500 nodes 
  10. model.add(Flatten()) 
  11. model.add(Dense(500, activation="relu")) 
  12. Output layer with 32 nodes (one for each possible letter/number we predict) 
  13. model.add(Dense(32, activation="softmax")) 
  14. # Ask Keras to build the TensorFlow model behind the scenes 
  15. model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"]) 

现在我们可以训练它了!

  1. # TrAIn the neural networkmodel.fit(X_train, Y_train, validation_data=(X_test, Y_test), batch_size=32, epochs=10, verbose=1) 

经过训练数据集10次之后,我们达到了接近100%的准确度。在这一点上,我们应该能够在我们想要的时候自动绕过这个验证码!我们做到了!

计时结束:15分钟。

使用训练的模型来求解验证码

现在我们有了一个训练有素的神经网络,用它来破坏一个真正的验证码是很简单的:

从一个使用该插件的网站上获取一个真正的验证码图像。

用我们用来创建训练数据集的方法将该图像分割成四个不同的字母图像。

让我们的神经网络对每个字母图像做一个单独的预测。

用四个预测字母作为验证码的答案。

狂欢接踵而来!

下面是我们的模型如何解码真实的验证码:

或从命令行来看:

试一下!

如果你想亲自尝试,可以在原文中获取代码。文件中包括10,000个示例图像和本文中每个步骤的所有代码。查看README.md文件,可阅读运行说明。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI研习社

Github 项目推荐 | 用 Numpy 实现简单的 GAN

本库能够让开发者用 Numpy 一步步实现简单的 GAN。不使用 GPU 的话,生成所有的数字会花费大量的时间,如果你只想用 CPU 来训练的话,建议只训练一个...

762
来自专栏小鹏的专栏

tf12: 判断男声女声

本帖训练一个简单的神经网络模型,用来判断声音是男是女。 本帖数据集取自voice-gender项目,这个项目使用了n种分类模型,并比较了准确率,但是它没有使...

2049
来自专栏灯塔大数据

塔趣 | 用深度学习来评判颜值,基于TensorFlow的开源项目FaceRank

导读:用深度学习来评判颜值,已开源。好友 @小灰灰 大大的「颜值评分 FaceRank」,这是基于 TensorFlow 的 CNN 模型,美不美机器说了算。...

39411
来自专栏河湾欢儿的专栏

05-图片优化合并

遵循的原则: 把同属于一个模块的图片进行合并 把大小相近的图片进行合并 把色彩相近的图片进行合并 综合以上凡是合并

882
来自专栏AI研习社

野外动物监测图像挑战赛:预测捕捉到的野外图像是否包含动物

野外相机能够自动收集大量的图像信息,不过不幸的是,收集到的大量图片都是误报,这些错误大多是由非动物引起的,比如草木的晃动。 本次比赛旨在预测白天和晚上从各个地点...

3189
来自专栏CreateAMind

运动信息向量的神经网络学习 code、ppt、视频

官方代码还未开放, http://visualdynamics.csail.mit.edu/

983
来自专栏北京马哥教育

Python破解验证码,只要15分钟就够了!

让我们一起攻破世界上最流行的WordPress的验证码插件 每个人都讨厌验证码——在你被允许访问一个网站之前,你总被要求输入那些烦人的图像中所包含的文本。 验...

3516
来自专栏计算机视觉与深度学习基础

【深度学习】使用tensorflow实现VGG19网络

接上一篇AlexNet,本文讲述使用tensorflow实现VGG19网络。 VGG网络与AlexNet类似,也是一种CNN,VGG在2014年的 ILSV...

4114
来自专栏IT派

python代码实现图片噪声去除

今天来给大家分享下怎么做图片的噪声去除。平时其实大家上网都能遇到这样的场景,就是输入讨厌验证码,怎么都输不对。验证码现在可以说是千奇百怪、分外妖娆,为啥要做成这...

833
来自专栏CreateAMind

代码解读Top-down Neural Attention by Excitation Backprop及模型架构图

1023

扫码关注云+社区