一、验证码综述
全自动区分计算机和人类的图灵测试(英语:Completely Automated Public Turing test to tell Computers and Humans Apart,简称CAPTCHA),俗称验证码,是一种区分用户是计算机和人的公共全自动程序。在CAPTCHA测试中,作为服务器的计算机会自动生成一个问题由用户来解答。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类。
目前常见的OCR有tesseract-ocr、有道OCR、百度OCR等等。
1.1 验证码的分类
验证码的种类非常多,静态图形验证码是最常见,也是难度较高的一种。另外,对于验证码使用打码平台是一种万能的方法,暂不涉及。本文对已有的方法进行归纳总结,重点提供对静态图形验证码的破解思路。
二、静态图形验证码
2.1 图形验证码的识别流程
本人大概将验证码分为了5个类,识别难度按照数字从低到高递增(可以直接用tesseract-ocr识别的为第一类,必须用机器学习来是别的为第五类,为最高类)。具体如下所示:
2.2 图形处理基础知识
2.2.1 OCR
OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程。如何除错或利用辅助信息提高识别正确率,是OCR最重要的课题,ICR(Intelligent Character Recognition)的名词也因此而产生。衡量一个OCR系统性能好坏的主要指标有:拒识率、误识率、识别速度、用户界面的友好性,产品的稳定性,易用性及可行性等。
目前OCR已经将图片验证码的破解难度大大降低,本文主要以tesseract-ocr为例,分享一下图片验证码破解的其他内容。
2.2.2 Image
Image库是操作图片的基本库,能够在像素点的层面分析并操作图片。要识别图片验证码,这个库是基础,当掌握这个库之后,对验证码的识别的思路会开阔很多。因此,本库的学习将会非常重要。
2.2.3 tesseract-ocr
当我们对图片处理结束之后,就需要对其进行识别,推荐一个比较强大的识别软件:tesseract-ocr。
它可以对图片内容自动进行识别,并返回识别后的返回值
牛逼之处在于,若识别有误,可以使用这个工具进行训练,相当于机器学习中的监督学习,然后再进行识别就会提高准确度。
tesseract-ocr本身具有api可以调用,但是使用较为复杂。因此,并不推荐,建议使用pytesseract来代替。
2.2.4 pytesseract
这个是使用python操作pytesseract的一个库。
2.3 常用技巧
2.3.1 预处理
预处理指的就是在正式对验证码进行识别之前对其进行一些处理,以帮助我们能够更好的识别验证码。
2.3.1.1 关键知识点
RGB: 通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。
RGBA: 在RGB的基础上新增了透明度
灰度: 将彩色的图像转化为单个数字来表示
二值化: 将图像使用黑和白两种颜色来表示
2.3.1.2 噪点
2.3.1.3 干扰线
根据颜色清除
单像素干扰线
2.3.1.4 opencv
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
腐蚀: 原图中的高亮区域被蚕食,效果图拥有比原图更小的高亮区域
膨胀: 对图像高亮部分进行“领域扩张”,效果图拥有比原图更大的高亮区域
开运算: 先腐蚀后膨胀
可以使用开运算来清除噪点
闭运算: 先膨胀后腐蚀
可以使用闭运算来将两块分割的区块连接起来
2.3.2 二值化
将图片中的各像素点按照一个阈值划分为黑白两种颜色,对于验证码颜色和背景颜色相差较大的情况下,这种方法非常好用。代码如下:
2.3.2.1 阈值法
1# 本例中首先把图片转为灰度,然后再划分阈值
2def Binarized(Picture):
3 Pixels = Picture.load()
4 (Width, Height) = Picture.size
5 Threshold = 80 # 阈值
6 for i in xrange(Width):
7 for j in xrange(Height):
8 if Pixels[i, j] > Threshold: # 大于阈值的置为背景色,否则置为前景色(文字的颜色)
9 Pixels[i, j] = BACKCOLOR
10 else:
11 Pixels[i, j] = TEXTCOLOR
12 return Picture
2.3.3 分割
破解较难验证码的重点和难点就在于能否成功分割字符,这一点也是机器视觉里的一道难题,对物件的识别能力。对于颜色相同又完全粘连的字符,比如google的验证码,目前是没法做到5%以上的识别率的。不过google的验证码基本上人类也只有30%的识别率
2.3.3.1 投影法
2.3.3.2 水滴法
滴水算法的过程是从图片顶部开始向下走,向水滴滴落一样沿着字符轮廓下滑,当滴到轮廓凹处渗入笔画,穿过笔画后继续滴落,最终水滴所经过的轨迹就构成了字符的分割路径。
2.3.3.3 极小值点分割法
我们同样先统计一些字符,记下平均字符宽度,当遇到两个字符粘连时,从平均字符宽度处向两侧找竖直方向上有效像素个数的极小值点,然后从极小值点进行分割。
2.3.4 整理
2.3.4.1 旋转
可以旋转至最窄点
2.3.5 识别
对图形验证的识别,可以有各种方法,可以使用pytesseract,也可以自己写图形相似度算法,也可以直接使用现成的机器学习算法。经过试验,tesseract-ocr已经可以满足大部分的破解情况了,但是相比于写算法或机器学习,ocr大大降低了验证码的破解难度。
2.4 练习
去噪实例
以下面的验证码为例:
找到验证码中每个颜色:
1def scan(im, xx, yy):
2 pix = im.load()
3 dic = {}
4 for x in xrange(xx):
5 for y in xrange(yy):
6 if pix[x,y] in dic.keys():
7 dic[pix[x,y]]['count'] = dic[pix[x,y]]['count'] + 1
8 if x > dic[pix[x,y]]['right']:
9 dic[pix[x,y]]['right'] = x
10 if x < dic[pix[x,y]]['left']:
11 dic[pix[x,y]]['left'] = x
12 if y > dic[pix[x,y]]['up']:
13 dic[pix[x,y]]['up'] = y
14 if y < dic[pix[x,y]]['down']:
15 dic[pix[x,y]]['down'] = y
16 else:
17 dic[pix[x,y]] = {'count':1, 'left':x, 'right':x, 'up':y, 'down':y}
18 return dic
找到验证码颜色,按照像素点范围大小、像素点数目多少来判断。
1def geticode(dic):
2 l = []
3 for i in dic.keys():
4 if 9 < abs(dic[i]['right']-dic[i]['left']) < 61 and abs(dic[i]['up']-dic[i]['down']) < 11:
5 l.append(i)
6 tmp = 0 #验证码颜色
7 for i in l:
8 print str(i) + 't' + str(dic[i])
9 if dic[i]['count'] > tmp:
10 tmp = i
11 print str(tmp) + 't' + str(dic[tmp])
12 return tmp
清除除验证码外的其他颜色:
1def clean(im, xx, yy, icode):
2 pix = im.load()
3 for x in xrange(xx):
4 for y in xrange(yy):
5 if pix[x,y] != icode:
6 im.putpixel((x,y), 255)
7 return im
主函数:
1def main(file):
2 im = Image.open(file)
3 im = im.convert('L')
4 xx, yy = im.size
5 icode = geticode(scan(im, xx, yy))
6 im = clean(im, xx, yy, icode)
7 im.show()
8 test = image_to_string(im)
9 print test
2.6 机器学习识别验证码
兜哥的书已经写得很详细了,以后再分享一下机器学习方面的体会,常用的破解算法:
-
朴素贝叶斯算法
-
逻辑回归算法
-
神经网络算法
-
TensorFlow
-
循环神经网络算法
三、动态图形验证码
基本上每帧都有一个字符和其他的分开,用最简单的扫描法就能分割出来。
剩下的就很轻松了,旋转还原之后,先填充内部空白,缩小细化之后做成模板对比,识别率怎么也得有90%了。
原本一张图就能搞定的事情,偏偏给了我们8张图,而且每张图还有一点区别,平白无故增大了很多信息量。
四、语音验证码
还有就是声音验证码的识别,现在很多验证码为了提高用户体验和照顾视觉障碍的用户,都有声音验证码,一般来说是机器生成一段读数字的语音。但是在这方面上很多程序员都偷懒了,预先找了10个数字的声音录音,然后生成的时候把他们随机拼到一起,结果就是这样:
五、短信验证码
存在问题:
-
绕过
-
爆破
-
直接回显
-
……
六、滑块验证码
目前滑块验证码已经逐步退出的历史舞台,最新版的极验验证码也基本舍弃了滑块验证码,主要原因在于滑块验证码已经不够安全,新的验证码采用了机器学习检测+图片识别+逻辑验证码将更为广泛的应用。以下是破解的一些方法。
6.1 系统层工具使用
系统层工具,即第三方工具通过调用系统层api进行各类操作,这类工具基本完全模拟人的行为,无法通过js指纹收集直接检测其是否为工具,这类工具中比较出名的有sikuli、按键精灵、大漠插件(游戏外挂应用较多)等。其中,sikuli较为好用,可以利用sikuli实现拖拽。
6.2 selenium webdriver
常用的破解验证码工具,可以驱动浏览器工作,并向浏览器嵌入代码从而实现浏览器的操控,功能强大。
6.3 图像匹配技术
主要问题集中在找坐标,即使用python、java对图像匹配定位然后拖动,思路如下:
-
屏幕截图、使用原生代码对当前窗口截图
-
图像识别,通过验证码图像与截图中图像相似度匹配找到验证码所在位置
-
做差找到验证码实际在浏览器中的位置
-
使用代码api实现拖动
七、参考
https://www.zhihu.com/question/32209043
未完待续
更多动态,请长按下方二维码关注我们
本文始发于微信公众号(宜信安全应急响应中心):验证码的破解
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论