热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

验证码识别思路

因为某些原因,最近写了个不停注册某网站账号的chrome扩展。(算外挂吗?)该网站注册时需要输入验证码,且单次有效,所以穷举不可取。(验证神马的,最讨厌了!)首先要确定验证

因为某些原因,最近写了个不停注册某网站账号的chrome扩展。(算外挂吗?)

  该网站注册时需要输入验证码,且单次有效,所以穷举不可取。(验证神马的,最讨厌了!)

================================================================

  首先要确定验证码图片是实时生成的还是只是静态图片,收集大量验证码看看是不是有大量相同的:

  最近erlang代码写得比较多,就用erlang实现了,至于存储,直接放磁盘算了。

《验证码识别思路》

-export([start/0]).
start() ->
inets:services(),
inets:start(),
S = lists:sum([get_img(X)||X<-lists:seq(1,10000)]),
io:format("~p/~p",[S,10000]).
get_img(N) ->
io:format("~p~n",[N]),
UrlPic = "http://网址就不公开了/xxx.do?yyy=zzz",
case httpc:request(UrlPic) of
{ok,{_,_H,Data}} ->
Bin = list_to_binary(Data),
<<Id:128>> = erlang:md5(Bin),
FileName = lists:flatten(io_lib:format("img/~.16b.jpg",[Id])),
case file:read_file_info(FileName) of
{ok,_} -> io:format("exists: ~p~n",[FileName]),1;
_ -> file:write_file(FileName,Bin),0
end;
Why ->
io:format("~p~n",[Why]),
get_img(N)
end.

《验证码识别思路》

  代码里对获得的图片计算了标准md5校验码作为图片文件名,判断两个图片是否完全一致的办法是看两个图片的校验码是否一致。

  测试发现,当收集了300多个图片后开始出现重复。超过5000个图片后,碰撞率变得很高。最终当我收集了1w8张验证码图片时,图片命中率高达97%。

  也许有人觉得单看验证码判断图片是否一致的方法有问题,但如果100张图片中有97张的验证码都和之前的某张的一样,但实际内容却不同,那就见鬼了。由于我好奇心比较重,为了看看有没有这种见鬼的事,我改了下上面的代码,将md5冲突的新图片保存下来人工确认,见鬼的事没有发生,内容长度确实是完全一模一样。

================================================================

  以上说明该网站的验证码就是预先一大堆静态图片,估计总数大概是2w,每次请求时随机取一张图片返回。这样做的原因估计是这么做对性能影响很小。

  这么算吧:2w张图片,人工写1000个映射关系,命中率就5%,每次请求一幅图片的时间不会超过500ms,平均不用10秒遇到一张已经知道验证码的图片。于是,于是……于是我两天晚上抽空填了3000个验证码,最后速度嘛,大概5s一个账号。

  可能有人会好奇我怎么输入3000个验证码,其实是我特地写了个小程序方便录入:

《验证码识别思路》

================================================================

  问题虽然基本解决,但我还是更倾向于用代码来识别验证码。

  感觉erlang做GUI程序不方便,还是用回C#来做这部分工作。

  从网上找了好几个.NET下的OCR引擎,识别率极低:识别出一个数字的概率大概等于瞎猫碰上死老鼠。看来靠第三方是搞不定的了,还得靠自己。

  观察验证码的特点:所有验证码都是4位0-9整数,80&#215;30像素,1.4kB左右,色调比较单一,数字都稍微扭曲了点,但不同验证码的同个数字的相似度非常高:

《验证码识别思路》

《验证码识别思路》

《验证码识别思路》

《验证码识别思路》

  我相信看到这,熟悉Matlab的同学一定乐死了。但是,我不熟悉,还是用土方法吧:对图片取灰度,截取4个小图,抽取0-9十个样本,分析时每个数字与样本匹配,相似度最高的就是对应数字。

  很不幸,这种方法识别出来的数字也不是很靠谱,四个数字通常只能识别两三个,完整识别出来的几乎没有。正当我准备对图片进行归一化调整时,我发现验证码图片中,相同位置的相同数字相似度极高,但不同位置的相同数字相似度倒是不高。

  既然规律找到了,方案自然就出来了:在取样本时,每个位置的数字的样本分开管理,下面是核心匹配代码:

《验证码识别思路》

private int parse_one(int[] hash,int n)
{
int x = 0;
int r = 0;
for (int i = 0; i <10; i++)
{
var r2 = match(hash,n,i);
if (r2 > r) { r = r2; x = i; }
}
return x;
}
private int match(int[] hash, int n, int i)
{
int sum = 0;
int o = i * H * W * 4 + n * W;
for (int x = 0; x {
for (int y = 0; y {
int g1 = cache[o + x + y * 4 * W];
int g2 = hash[x + y * W];
if (g1 > 200 && g2 > 200)
{
sum += 1000;
}
else if (g1 <50 && g2 <50)
{
sum += 5000;
}
else
{
sum += (255 - Math.Abs(g1 - g2));
}
}
}
return sum;
}

《验证码识别思路》

  最终识别率:几乎100%(试了10几张没发现哪个验证码图片识别不出,还是低调点,90%吧)

《验证码识别思路》

  后面就是写个批处理功能,把收集到的验证码转换成JS,供chrome扩展直接查表使用了,最终效果大概是2秒一个账号。至于chrome扩展怎么获取验证码图片,怎么算md5,这些都不是本文的重点,在此略过。

  这个网站的验证码方案有几点不够安全的地方:

  1. 使用静态验证码,且静态验证码总数较少(后来发现原来隔一段时间就换一次,汗);

  2. 各验证码图片的相似度太高,随机性不足,识别难度颇低;

  3. 对于短时间注册大量账号的IP没有相关应对措施。

================================================================

后记:

  昨天到别的机子运行发现这个神一样的注册机用了没多久竟然不灵了,验证码突然一个都识别不出,观察发现该网站的验证码又不一样了,暴汗,一天换一批注册码。

还好不是用人工输入的办法,打算回来继续录入样本识别,发现家里的获得的验证码的图片还是原来的,莫非这些验证码还根据IP或者网络线路发放?真是魔高一尺,道高一丈……

  我表示还是喜欢这种类型验证码,最好是还可以暴力穷举:

《验证码识别思路》


推荐阅读
  • 用阿里云的免费 SSL 证书让网站从 HTTP 换成 HTTPS
    HTTP协议是不加密传输数据的,也就是用户跟你的网站之间传递数据有可能在途中被截获,破解传递的真实内容,所以使用不加密的HTTP的网站是不 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • DVWA学习笔记系列:深入理解CSRF攻击机制
    DVWA学习笔记系列:深入理解CSRF攻击机制 ... [详细]
  • 利用爬虫技术抓取数据,结合Fiddler与Postman在Chrome中的应用优化提交流程
    本文探讨了如何利用爬虫技术抓取目标网站的数据,并结合Fiddler和Postman工具在Chrome浏览器中的应用,优化数据提交流程。通过详细的抓包分析和模拟提交,有效提升了数据抓取的效率和准确性。此外,文章还介绍了如何使用这些工具进行调试和优化,为开发者提供了实用的操作指南。 ... [详细]
  • 本文深入探讨了Ajax的工作机制及其在现代Web开发中的应用。Ajax作为一种异步通信技术,改变了传统的客户端与服务器直接交互的模式。通过引入Ajax,客户端与服务器之间的通信变得更加高效和灵活。文章详细分析了Ajax的核心原理,包括XMLHttpRequest对象的使用、数据传输格式(如JSON和XML)以及事件处理机制。此外,还介绍了Ajax在提升用户体验、实现动态页面更新等方面的具体应用,并讨论了其在当前Web开发中的重要性和未来发展趋势。 ... [详细]
  • 浏览器与服务器在网站访问过程中的数据交互分析
    本文分析了浏览器与服务器在网站访问过程中基于HTTP协议的数据交互机制。HTTP协议具有轻量级和高效通信的特点,主要通过GET、HEAD和POST方法进行数据传输。其“请求-响应”模式确保了数据交互的有序性和可靠性,同时支持多种数据格式和内容类型,为现代Web应用提供了坚实的基础。 ... [详细]
  • -module(udpserver).-import(crc,[comCrc161]).-export([start0,client1]).%%服务端start()->s ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • 在当前的软件开发领域,Lua 作为一种轻量级脚本语言,在 .NET 生态系统中的应用逐渐受到关注。本文探讨了 Lua 在 .NET 环境下的集成方法及其面临的挑战,包括性能优化、互操作性和生态支持等方面。尽管存在一定的技术障碍,但通过不断的学习和实践,开发者能够克服这些困难,拓展 Lua 在 .NET 中的应用场景。 ... [详细]
  • 本文详细介绍了如何在Java Web服务器上部署音视频服务,并提供了完整的验证流程。以AnyChat为例,这是一款跨平台的音视频解决方案,广泛应用于需要实时音视频交互的项目中。通过具体的部署步骤和测试方法,确保了音视频服务的稳定性和可靠性。 ... [详细]
  • Windows 10系统对Intel服务器的影响:来自微软官网的下载选项分析 ... [详细]
  • .Net下RabbitMQ发布订阅模式实践
    一、概念AMQP,即AdvancedMessageQueuingProtocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的 ... [详细]
  • CentOS7 安装RabbitMQ
    1安装编译工具yuminstall-ymakegccgcc-c++m4opensslopenssl-develncurses-develunixODBCunixODBC-devel ... [详细]
  • Java自学知乎!阿里高级算法专家公开10份资料,涨姿势!
    接口概述:接口是Java语言中的一种引用类型,是方法的集合,所以接口的内部主要就是定义方法,包含常量,抽象方法(JDK ... [详细]
  • rtemsapi用户指南Elixir代表了相对较新的编程语言,面向更广泛的受众。它于2011年发布,此后一直在开发中。他的主要特征是取消功能范式 ... [详细]
author-avatar
HGKHGK
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有