如何破解滑动验证码 我不知道验证码

Python 爬虫入门(四)—— 验证码上篇(主要讲述验证码验证流程,不含破解验证码) - 不剃头的一休哥 - 博客园
posts - 14, comments - 140, trackbacks - 0, articles - 0
  本篇主要讲述验证码的验证流程,包括如何验证码的实现、如何获取验证码、识别验证码(这篇是人来识别,机器识别放在下篇)、发送验证码。同样以一个例子来说明。目标网址 /index.php(查询域名备案信息)
  1.验证码的实现:
  简单的说,验证码就是一张图片,图片上有字符串。网站是如何实现的呢?有WEB基础的人可能会知道,每个浏览器基本都有cookie,作为这次回话的唯一标示。每次访问网站,浏览器都会把这个cookie发送给服务器。验证码就是和这个cookie绑定到一起的。如何理解呢?举个例子,现在有网站W,有A和B两个人,同时访问W,W给A返回的验证码是X,给B返回的验证码是Y,这两个验证码都是正确的,但是如果A输入了B的验证码,肯定验证不通过。那服务器是怎么区分A和B呢,就是用到的cookie。再举个例子,有些网站你登录一次之后,下次继续访问可能就自动登陆了,也是用cookie来标示唯一身份的,如果清除了cookie也就无法自动登陆了。cookie具体是什么生成的,我们不必关心,只需要知道是一长串字符串就行了,你的和别人的都不一样。(例子中的目标网址并不是用cookie,而是用的其他方式,所以可能会存在一些BUG)
  服务器后台生成验证码的流程就很容易理解了:首先,生成一个随机字符串,然后和cookie绑定,然后写到图片上返回给你。那么,如何生成一个图片验证码呢?下面是一个简单的生成验证码源码:
from PIL import Image
import ImageFilter,ImageDraw,ImageFont
import random
width = 80
height = 40
font = ImageFont.truetype('C:\\Windows\\Fonts\\AdobeFangsongStd-Regular.otf', 28)
image = Image.new("RGB",(width,height),(0,0,0))
draw = ImageDraw.Draw(image)
for t in range(4):
draw.text((20*t,10),`random.randint(0,9)`,font=font,fill=(255,255,255))
image.show()
  代码说明:
    a).PIL是python的图片库模块,需要自己安装
    b).ImageFont.truetype()是选择字体
    c).Image.new("RGB",(width,height),(0,0,0))新建一个Image,背景色是白色((0,0,0)就代表的颜色),如果需要别的颜色,可自己查询颜色代码。window自带的画板就可以看到:
    d).random.randint(0,9)随机数 范围大于等于0,小于等于9
    e).draw.text((20*t,10),`random.randint(0,9)`,font=font,fill=(255,255,255),anchor=False) 第一个参数代表位置,带二个代表内容,第三个代表字体,第四个代表字体颜色
    f).image.show()显示图片,第一词会提示选择默认图片查看器。
   运行结果如下图:
  2).验证码的获取
    a).分析目标网站,可以看到当鼠标点击验证码那个输入框时会显示验证码,如图:
  那么获取验证码的请求是什么?以及请求发送的时间?(验证码显示的时间不一定是验证码获取的时间,虽然这个例子中是,以为验证码可能是页面刚开始的时候一起加载的,只是一直被隐藏)。火狐浏览器F12打开控制台,找到网络标签,刷新页面,可以看到如下图所示:
  并没有发现获取验证码的请求,那么我们点击验证码的那个输入框,发现多了一个请求,没错,这就是获取验证码的请求。
  b).下面我们开始分析这个请求,首先点击这个请求,可以看到如下图所示:
  完整URL:/captcha.php?.cn&sid=82&icp_host=sxcainfo。可以看到三个参数:
  .cn:查询的域名
  sid=82:这个ID暂时不知道是什么,后面查看JS源代码会看到
  icp_host:这个暂时也不知道。
  这三个参数,那些是必须的呢?可以一个一个测试。测试方法就是删掉某个元素,然后再发请求。测试发现,三个参数缺省都可以获取到验证码,获取到验证码,不代表验证码可用,因为,没有与某些类似cookie的值绑定到一起,它就和图片没有任何区别,不具备验证的功能。经我测试,(测试很简单,不过要用到后面的东西,看完这篇,就知道怎么测了),这三个参数都需要。在测试的过程中,我发现了sid就是一个随机数,没有什么特殊含义,基本可以确定可以随便输入:js代码如下:
  icp_host的取值有很多:sccainfo、ahcainfo、jscainfo......有没有发现什么规律?首先八个字母,最后六个都是cainfo,那么前面两个代表什么?sc=四川、ah=安徽、js=j江苏。所以,我们可以猜测这个是省份的简写。那这个值有什么用呢?作用一,如果不按这个规则输入字符串(比如,aaaaaaaa),就获取不到验证码;作用二,验证码就是和这个绑定的。也就是说,你获取验证码的时候用sccainfo,那么验证的时候也要用sccainfo。
  分析完参数,然后再分析请求头,方法和参数的分析方法一样,一个个删除,看能不能获取正确的结果。这个时候,可以自己写python代码测试,具体代码如下:
#encoding=utf8
import urllib2
from PIL import Image
import cStringIO
getCode_url = "/captcha.php?&sid=0&icp_host=hncainfo"
header={"Referer":"/captcha.php?&sid=0&icp_host=hncainfo"}
# header['Host']=""
# header['User-Agent']="Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/ Firefox/43.0"
header['Cache-Control']="max-age=0"
request = urllib2.Request(getCode_url,headers=header)
res = urllib2.urlopen(request).read()
image = Image.open(cStringIO.StringIO(res))
image.show()
  代码说明:
    a).cStringIO python的流模块,无论是图片、文本、音频、视频都是流文件,可以相互转化。这里的作用是将图片流还原成图片
    b).header中添加参数可直接用header['']="",这样就可以测试了。具体哪些参数必须,自己测试。
  运行结果:
  3).检验验证码
   a).分析目标网站,寻找检验验证码的请求。我们在输入框输入正确的验证码,点击备案查询,如图所示:
    可以看到控制台中多了一个请求
    点击请求,查看请求详情:/index.php?&code=65a89c&icp_host=lncainfo
    三个参数:
     :查询的域名,必不可少
     code=65a89c:验证码,必不可少
     icp_host=lncainfo:和获取验证码相对应
    然后再分析header,与上面的方法一样。这两次检验不同的是:检验获取验证码时,是自己写代码获取验证码,然后放到网站上检验,验证码的正确性(必须保证icp_host一致);检验检查验证码时,是用网站获取验证码,填到代码里面,看看参数对不对。
    验证代码如下:
#encoding=utf8
import urllib2
checkcode_url = "/index.php?&code=N3PE37&icp_host=hncainfo"
# header['Pragma']="Pragma"
# header['Referer']="/index.php?&code=CUXWDV&icp_host=sccainfo"
header['User-Agent']="Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/ Firefox/43.0"
request = urllib2.Request(checkcode_url,headers=header)
res = urllib2.urlopen(request).read()
    代码说明:icp_host=hncainfo这个参数必须和你获取验证码时候的参数一致
    运行结果:
    如果验证码不正确或者别的地方不一致,会返回:
  到此,我们就分析完了,不过现在是把获取和验证放在两个代码中运行,怎么放在一起呢?代码如下:
#encoding=utf8
import urllib2
from PIL import Image
import cStringIO
import BeautifulSoup
def getCode(domain):
print "获取验证码...."
getcode_url="/captcha.php?q="+domain+"&sid=0&icp_host=hncainfo"
getcode_headers = {}
getcode_headers['Referer']="/captcha.php?&sid=0&icp_host=hncainfo"
getcode_headers['Cache-Control']="max-age=0"
getcode_request = urllib2.Request(getcode_url,headers=getcode_headers)
getcode_res = urllib2.urlopen(getcode_request).read()
image = Image.open(cStringIO.StringIO( getcode_res))
print "获取验证码成功"
image.show()
def checkcode(domain,code):
# print "您输入的验证码为:"+`code`
print "开始检查验证码..."
checkcode_url = "/index.php?q="+domain+"&code="+code+"&icp_host=hncainfo"
checkcode_headers={}
checkcode_headers['User-Agent']="Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/ Firefox/43.0"
checkcode_request = urllib2.Request(checkcode_url,headers=checkcode_headers)
checkcode_res = urllib2.urlopen(checkcode_request).read()
if(checkcode_res.count("主办单位名称")&0):
print "验证成功"
checkcode_soup = BeautifulSoup.BeautifulSoup(checkcode_res)
print "所属单位名称:"+checkcode_soup.findAll("table")[0].findAll("tr")[0].findAll("td")[1].text.encode("utf8")
print "验证失败"
domain = raw_input("请输入域名:")
getCode(domain)
code = raw_input("请输入验证码:")
checkcode(domain,code)
    代码说明:
      a).def getCode(domain) 声明一个函数,getCode是函数名,domain是参数
      b).raw_input() 获取用户输入
      c).在获取和验证的时候,我把icp_host都写成了hncainfo,这样就可以保证一致。
      d).encode("utf8") 对变量以utf8格式编码
      e).验证码要人工识别输入
    运行结果:
  到此,整个验证码的获取,验证都讲述完了,验证码的识别放在下一节。
  说明:
  a).代码仅供学习交流
  b).如有错误,多多指教
  c).转载请注明出处利用机器学习破解网站验证码 只需15分钟
 作者: 谢涛编译 编辑:
  【IT168 编译】网站登录验证码的存在一直让人感到不爽,因为输错一个字往往就意味着账号密码什么的就得重新再输一遍。更有甚者(如12306网站),仅仅验证码一道工序就把人整到怀疑人生。不过看了国外一位大神的分享,小编我算是知道为什么12306网站要把验证码设置的这么变态了!  愿世间少一些套路,多一些真诚。  以下是原文:  相信每个人都对验证码没有好感——你必须输入图像里的文本,然后才能访问网站。验证码的设计是为了防止计算机自动填写表格,以此验证你是一个真实的人。但随着深度学习和计算机视觉的兴起,它们现在已经变得脆弱不堪。  我一直在读一本由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的几行代码:  # Build the neural network!  model = Sequential()  # First convolutional layer with max pooling  model.add(Conv2D(20, (5, 5), padding=&same&, input_shape=(20, 20, 1), activation=&relu&))  model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))  # Second convolutional layer with max pooling  model.add(Conv2D(50, (5, 5), padding=&same&, activation=&relu&))  model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))  # Hidden layer with 500 nodes  model.add(Flatten())  model.add(Dense(500, activation=&relu&))  # Output layer with 32 nodes (one for each possible letter/number we predict)  model.add(Dense(32, activation=&softmax&))  # Ask Keras to build the TensorFlow model behind the scenes  pile(loss=&categorical_crossentropy&, optimizer=&adam&, metrics=[&accuracy&])  现在我们可以训练它了!  # 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文件,可阅读运行说明。
IT168企业级小议验证码的安全性及如何绕过 -
| 关注黑客与极客
小议验证码的安全性及如何绕过
共281255人围观
,发现 7 个不明物体
什么是验证码?
CAPTCHA是(全自动区分计算机和人类的图灵测试)的简称,是用于区分计算机和人类的一种程序算法,这种程序必须能生成并评价人类能很容易通过但计算机却通不过的测试。
像我们平时最常遇到的,就是基于图片的验证码。这类图片验证码通常包含的,都是些易于用户识别简单的验证信息。如下图所示。用户必须准确的识别图像内的字符,并以此作为人机验证的答案,方可通过验证码的人机测试。相反如果验证码填写错误,那么验证码字符将会自动刷新并更换一组新的验证字符,直到用户能够填写正确的验证字符为止。
验证码的重要性:
防止与认证相关的攻击行为:
以下列举的是一些较易受到暴力攻击的点。例如:
登录:一旦缺少验证码的保护,攻击者则很可能通过暴力破解的方式非法接管用户账户。
忘记密码:如果网络应用程序使用详细消息响应帐户存在或不存在,那么攻击者则可以进行用户名的枚举。
注册:程序批量创建垃圾账户。此外还可以进行用户名的枚举。(正常情况下没有应用程序会允许用户,同时注册两个相同用户名的账号)
避免垃圾邮件和DOS:
我们知道很多网站都有提交表单的功能,并需要由站点管理员审核通过。例如:会员申请,联系我们,反馈表,调查表等。这些功能都需要验证码的保护,如果不加以防护那么将会导致以下情况的出现:
大量的垃圾表单可能产生,不仅会影响网站的访问速度,还会加大站点管理员的工作量,而且一些合法用户的请求,也可能会因此被拒绝。
电子邮件轰炸:一些功能可以发送电子邮件到一个任意的邮件地址。如果没有得到有效的验证保护,那么恶意攻击者则可以利用程序,向特定的目标发送大量的垃圾邮件。
保护数据挖掘机器人:
某些包含大量数据的站点极易遭受数据挖掘攻击,因此它们也需要验证码的保护。例如:社交网络和搜索引擎。
验证码为什么能被绕过?
验证码被绕过,有以下两个原因:
在以下的内容,我将会带大家认识到这两个问题所在。以及如何解决这些问题,建立更为安全的人机验证。
设计问题则意味着验证码本质上的脆弱性,但执行却不存在问题。以下演示将有助于我们了解设计问题的真正原因,以及如何破解它:
设计问题#1:
以下的示例中我们可以看到,这里的验证码就是一道数学运题。而这里的问题就出在页面的HTML源码上。
你可以在Github上下载到该验证码的源码:
如何破解?
在这种情况下攻击者往往都会通过获取该页面的HTML源码,计算答案并提交HTTP响应来破解验证码。
你可以在Github上下载到该利用代码:
设计问题#2:
某些验证码可能会采用相对有限的问题数据库。例如以下是一个基于图片的验证码,很显然这里不能再利用上面提到的破解方案来破解。但这里的问题出在,这里的图片验证码字符是固定并且有限的,在本例中该验证码只会在来回10个固定字符组合中更换。因此一旦掌握了它的问题数据库,那么破解也自然就不成问题了。
你可以在Github上下载到该验证码的源码:
如何破解?
攻击者首先必须手动解决这10个验证码问题,并同时记录下这些问题的答案。然后通过工具将这些问题的答案存放在自己的数据库中,进行不断的暴力攻击尝试即可。
你可以在Github上下载到该利用代码:
执行问题:
执行问题则意味着验证码由于执行不力而可被破解,但从设计的角度来看是完美的。
以下示范将有助于我们了解,执行问题的真正含义以及如何破解它:
执行问题#1:
在演示中,我们正在使用Google reCAPTCHA人机验证。我们使用API将用户解决的CAPTCHA响应发送给Google的端点。更多请点击:&。API以JSON的输出形式回复请求,以及HTTP状态码。到现在为止,还没发现什么问题 !!
但是执行问题也就出在这里。开发人员无法检查JSON响应,而以检查发送的HTTP状态码是否为200 OK,作为验证码正确与否的判断依据。
你可以在Github上下载到该验证码的源码:
如何破解?
攻击者只需要制作一个脚本即可将任何值发送给人机验证码,并且都将会被服务器所接收,因为无论你发送什么答案,服务器都只会通过检查Google API发送的状态码是否为200 OK来作为判断依据。下图中,我们作为答案发送的值是“InvalidAnswerOfCAPTCHA”
你可以在Github上下载到该利用代码:
执行问题#2:
验证码存在于web页面,在用户提交后将被验证,但问题却出在了if和else一个简单的子句中。这个错误是由于开发人员将响应码写在了其它部分形成的。所以这里即使验证码答案是错误的,应用程序仍将给予用户积极的响应。
你可以在Github上下载到该验证码的源码:
如何破解?
攻击者只需要制作一个脚本,即可向验证码发送任意值。在下图中,我们作为答案发送的值是“InvalidAnswerOfCAPTCHA”
你可以在Github上下载到该利用代码:
执行问题#3:
验证码存在于web页面,但在提交后未在服务器端进行验证。
你可以在Github上下载到该验证码的源码:
如何破解?
攻击者只需通过输入错误的验证码和任意电子邮件,就可以轻松地绕过它。
你可以在Github上下载到该利用代码:
如何保护自己免受CAPTCHA攻击?
其实这个问题也很简单,大家可以按照以下步骤,来制作一个强大的CAPTHCA功能:
设计:实施设计良好的CAPTCHA方案。从以上示例中我们可以看到,大多数我们自己设计的验证码都或多或少的存在一些问题。因此,我建议大家尽可能的使用像Google这样的第三方CAPTCHA。
执行:在你选择了具有良好设计的人机识别系统后,下一步是正确的执行。我们已经看到,尽管有一个设计良好的CAPTCHA,但是如果不能正确执行,仍然可以被破解。如果你使用的是Google reCAPTCHA,请参照以下操作步骤:
以检查Google发送的JSON响应取代HTTP状态码检查。
在if和else子句中实现正确的逻辑,区分有效和无效的答案。
不要透露你的私人CAPTCHA密钥。
你可以从这里下载安全的CAPTCHA代码:
在实际业务及生产中,某些功能会要求有CAPTCHA。而不安全的CAPTCHA,将会导致敏感数据被窃取,认证攻击,DOS用户甚至管理员等严重问题的发生。因此对于开发人员和使用者而言,具有一个好的设计和实施的CAPTCHA至关重要!
所有脚本的Github链接:
*参考来源:,FB小编 secist 编译,转载请注明来自FreeBuf()
为一个验证码让程序员改过多次,基本犯了此文章中所有问题,这是有多傻
必须您当前尚未登录。
必须(保密)
每个人的心中都有一个梦。。
关注我们 分享每日精选文章利用Python破解验证码实例详解
作者:程序员实验室
字体:[ ] 类型:转载 时间:
这篇文章主要给大家介绍的是如何通过一个简单的例子来实现破解验证码。从本文中我们可以学习到 Python 基本知识,PIL 模块的使用,破解验证码的原理。文中通过实例一步步介绍的很详细,相信对大家理解和学习具有一定的参考借鉴价值,有需要的朋友们下面来一起看看吧。
本实验将通过一个简单的例子来讲解破解验证码的原理,将学习和实践以下知识点:
&&&&& Python基本知识
&&&&& PIL模块的使用
二、实例详解
安装 pillow(PIL)库:
$ sudo apt-get update
$ sudo apt-get install python-dev
$ sudo apt-get install libtiff5-dev libjpeg8-dev zlib1g-dev \
libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python-tk
$ sudo pip install pillow
下载实验用的文件:
$ wget http://labfile./courses/364/python_captcha.zip
$ unzip python_captcha.zip
$ cd python_captcha
这是我们实验使用的验证码 captcha.gif
提取文本图片
在工作目录下新建 crack.py 文件,进行编辑。
#-*- coding:utf8 -*-
from PIL import Image
im = Image.open("captcha.gif")
#(将图片转换为8位像素模式)
im = im.convert("P")
#打印颜色直方图
print im.histogram()
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0 , 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1, 2, 0, 1, 0, 0, 1, 0, 2, 0, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 3, 1, 3, 3, 0, 0, 0, 0, 0, 0, 1, 0, 3, 2, 132, 1, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0 , 1, 0, 1, 0, 0, 8, 1, 0, 0, 0, 0, 1, 6, 0, 2, 0, 0, 0, 0, 18, 1, 1, 1, 1, 1, 2, 365, 115, 0, 1, 0, 0, 0, 135, 186, 0, 0, 1, 0, 0, 0, 116, 3, 0, 0, 0, 0, 0, 21, 1, 1, 0, 0, 0, 2, 10, 2, 0, 0, 0, 0, 2, 10, 0, 0, 0, 0, 1, 0, 625]
颜色直方图的每一位数字都代表了在图片中含有对应位的颜色的像素的数量。
每个像素点可表现256种颜色,你会发现白点是最多(白色序号255的位置,也就是最后一位,可以看到,有625个白色像素)。红像素在序号200左右,我们可以通过排序,得到有用的颜色。
his = im.histogram()
values = {}
for i in range(256):
values[i] = his[i]
for j,k in sorted(values.items(),key=lambda x:x[1],reverse = True)[:10]:
我们得到了图片中最多的10种颜色,其中 220 与 227 才是我们需要的红色和灰色,可以通过这一讯息构造一种黑白二值图片。
#-*- coding:utf8 -*-
from PIL import Image
im = Image.open("captcha.gif")
im = im.convert("P")
im2 = Image.new("P",im.size,255)
for x in range(im.size[1]):
for y in range(im.size[0]):
pix = im.getpixel((y,x))
if pix == 220 or pix == 227: # these are the numbers to get
im2.putpixel((y,x),0)
im2.show()
得到的结果:
提取单个字符图片
接下来的工作是要得到单个字符的像素集合,由于例子比较简单,我们对其进行纵向切割:
inletter = False
foundletter=False
letters = []
for y in range(im2.size[0]):
for x in range(im2.size[1]):
pix = im2.getpixel((y,x))
if pix != 255:
inletter = True
if foundletter == False and inletter == True:
foundletter = True
if foundletter == True and inletter == False:
foundletter = False
letters.append((start,end))
inletter=False
print letters
[(6, 14), (15, 25), (27, 35), (37, 46), (48, 56), (57, 67)]
得到每个字符开始和结束的列序号。
import hashlib
import time
for letter in letters:
m = hashlib.md5()
im3 = im2.crop(( letter[0] , 0, letter[1],im2.size[1] ))
m.update("%s%s"%(time.time(),count))
im3.save("./%s.gif"%(m.hexdigest()))
count += 1
(接上面的代码)
对图片进行切割,得到每个字符所在的那部分图片。
AI 与向量空间图像识别
在这里我们使用向量空间搜索引擎来做字符识别,它具有很多优点:
不需要大量的训练迭代
不会训练过度
你可以随时加入/移除错误的数据查看效果
很容易理解和编写成代码
提供分级结果,你可以查看最接近的多个匹配
对于无法识别的东西只要加入到搜索引擎中,马上就能识别了。
当然它也有缺点,例如分类的速度比神经网络慢很多,它不能找到自己的方法解决问题等等。
向量空间搜索引擎名字听上去很高大上其实原理很简单。拿文章里的例子来说:
你有 3 篇文档,我们要怎么计算它们之间的相似度呢?2 篇文档所使用的相同的单词越多,那这两篇文章就越相似!但是这单词太多怎么办,就由我们来选择几个关键单词,选择的单词又被称作特征,每一个特征就好比空间中的一个维度(x,y,z 等),一组特征就是一个矢量,每一个文档我们都能得到这么一个矢量,只要计算矢量之间的夹角就能得到文章的相似度了。
用 Python 类实现向量空间:
import math
class VectorCompare:
#计算矢量大小
def magnitude(self,concordance):
for word,count in concordance.iteritems():
total += count ** 2
return math.sqrt(total)
#计算矢量之间的 cos 值
def relation(self,concordance1, concordance2):
relevance = 0
topvalue = 0
for word, count in concordance1.iteritems():
if concordance2.has_key(word):
topvalue += count * concordance2[word]
return topvalue / (self.magnitude(concordance1) * self.magnitude(concordance2))
它会比较两个 python 字典类型并输出它们的相似度(用 0~1 的数字表示)
将之前的内容放在一起
还有取大量验证码提取单个字符图片作为训练集合的工作,但只要是有好好读上文的同学就一定知道这些工作要怎么做,在这里就略去了。可以直接使用提供的训练集合来进行下面的操作。
iconset目录下放的是我们的训练集。
最后追加的内容:
#将图片转换为矢量
def buildvector(im):
for i in im.getdata():
d1[count] = i
count += 1
v = VectorCompare()
iconset = ['0','1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
#加载训练集
imageset = []
for letter in iconset:
for img in os.listdir('./iconset/%s/'%(letter)):
if img != "Thumbs.db" and img != ".DS_Store":
temp.append(buildvector(Image.open("./iconset/%s/%s"%(letter,img))))
imageset.append({letter:temp})
#对验证码图片进行切割
for letter in letters:
m = hashlib.md5()
im3 = im2.crop(( letter[0] , 0, letter[1],im2.size[1] ))
guess = []
#将切割得到的验证码小片段与每个训练片段进行比较
for image in imageset:
for x,y in image.iteritems():
if len(y) != 0:
guess.append( ( v.relation(y[0],buildvector(im3)),x) )
guess.sort(reverse=True)
print "",guess[0]
count += 1
一切准备就绪,运行我们的代码试试:
python crack.py
(0.02894, '7')
(0.77002, 's')
(0.8929, '9')
(0.44473, 't')
(0.06273, '9')
(0.72628, 'j')
是正解,干得漂亮。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 验证码破解 的文章

 

随机推荐