做授权测试这些年,验证码一直是登录爆破路上最大的拦路虎。尤其是那种4位数字、扭曲比较严重的验证码,手动输入一轮还能忍,但每请求一次刷新一张、还要配合字典跑上千个密码时,人就麻了。后来我把ddddocr和yakit的MITM热加载结合在一起,在授权测试中彻底打通了“验证码识别+web登录爆破”这条链路——请求自动带出验证码,yakit自动完成识别、回填、爆破,全程不用手动介入。这篇文章就把整套方案的架构、代码和踩坑记录完整晒出来,适合正在做Web渗透测试、或者准备在CTF里打登录爆破题的同学参考。
我用的方案不是简单的“跑个识别脚本”,而是把ddddocr封装成本地OCR服务,再通过yakit插件在流量层自动接管验证码。整个过程会被拆成几个模块,每一步为什么这么做、坑在哪里、怎么改,文章里都会写清楚。
1. 为什么要把验证码识别做进yakit插件
1.1 传统验证码爆破的三重痛点
先说最常见的做法:遇到验证码时,手动把图片保存下来,然后跑一段ddddocr脚本识别,再把识别结果填回爆破工具。听着不算复杂,但实际操作起来问题很多。
第一是效率低。4位数验证码还好,识别一次大概几百毫秒,但如果验证码是6位混合字符甚至带干扰线,识别成功率就算只有八成,每次失败都要重新刷新、重新下载、重新识别。一个字典跑下来几千次请求,可能一半时间都花在“搬运验证码图片”上。
第二是联动差。Burp、yakit这类工具的爆破模块本身不认识验证码,它们只负责把payload填进字段。验证码需要额外写脚本处理,数据怎么在脚本和爆破工具之间传递,往往要手动用剪贴板或临时文件来中转。这样不仅慢,还容易串数据——上一轮识别的验证码还没用上,还没来得及刷新,服务器已经把它作废了。
第三是状态维护难。很多登录接口的验证码是跟着Session或Cookie走的。爆破工具如果每个请求都重新建Session,验证码和手机号/用户名就对应不上,必然导致大量误报。真正的问题是:验证码不只是“一张图”,它是一个绑定会话状态的资源。要爆破成功,必须在同一个会话里完成“获取验证码->识别验证码->提交登录”这个闭环。
1.2 MITM热加载:把OCR服务串进流量管道
yakit的MITM热加载功能,简单说就是在中间人代理处理每一个HTTP/HTTPS请求和响应时,插入一段自定义逻辑。这就像一个中转站,流量从客户端到达服务器之前、以及响应返回客户端之前,都会经过你写的脚本,由脚本决定是原样放行还是修改数据包。
把这个机制用在验证码爆破上,思路就变成:
- 当浏览器或攻击脚本访问登录页时,yakit拦到验证码图片响应(通常是一个GET请求返回的图片流)。
- 热加载脚本把图片二进制提取出来,POST给本地跑着的ddddocr服务。
- OCR服务返回值发给热加载脚本,脚本再把识别结果绑到当前会话,等真正的登录请求发出时,自动替换掉验证码参数。
这样一来,人工只需要做一件事:启动爆破任务。剩下的验证码获取、识别、回填全部由管道自动完成。
1.3 整套链路的架构分层
整体架构分三层:
| 层级 | 组件 | 职责 |
|---|---|---|
| 识别层 | Python + ddddocr | 接收图片,返回识别文本 |
| 桥接层 | yakit MITM热加载脚本 | 拦截流量、提取图片、调用OCR、回填验证码字段 |
| 执行层 | yakit Web Fuzzer / 手工发包 | 按字典发送登录请求,完成爆破 |
三层之间通过本地HTTP接口通信,不依赖外网服务,所以即使目标站在内网环境,只要本机能跑yakit和Python服务,就能成立。这个分层还有一个额外好处:OCR服务和代理工具解耦,后续如果要换其他OCR引擎,比如加个深度学习模型,只需要改识别层,不用动yakit脚本。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与选型:ddddocr、Python版本、模型加载
2.1 为什么用ddddocr而不是其它OCR方案
市面上能识别验证码的方案其实不少——Tesseract是一个老牌选择,但从实践效果看,除非你花大量时间调图像二值化、字符分割,否则Tesseract对扭曲、粘连字符的表现非常一般,4位数字还行,混入字母基本就废。商用OCR服务(如各类云识别API)识别率高一些,但需要联网,而且在授权测试中把目标站的验证码图片发到第三方服务,本身就是个隐患。
ddddocr
