- 验证码二次处理案例
- 验证码调试方法
- 验证码响应包有token参数,登录需校验情况如何设置
- 验证码中为base64,如何识别验证码
- 验证码响应包有明文验证码,如何配合工具使用
- intruder模块都是一个验证码
- 一般的数字运算验证码
- 混淆、变形的数字运算验证码
releases下载最新插件与验证码识别端(captcha-killer-modified.jar
、codereg.py
)
安装python依赖,根据requirement.txt的内容进行下载依赖(pip install -r requirement.txt )
再使用python3 codereg.py
开启验证码识别模块,前提安装ddddocr
POST /reg HTTP/1.1
Host: 127.0.0.1:8888
Authorization:Basic f0ngauth
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 8332
<@BASE64><@IMG_RAW></@IMG_RAW></@BASE64>
其余用法移步captcha-killer用法
1.查看模板是否正确,模板
4.报错 Typeerror: classification() got an unexpected keyword argument img_base64
或者网页返回server got ifself in trouble
的500报错
async def handle_cb(request) :
img_base64 = await request.text()
img_bytes = base64.b64decode(img_base64)
return web. Response(text=ocr.classification(img_bytes))
可以自写中转,将处理后的验证码通过接口返回,如下代码:
# -*- coding: utf-8 -*-
# @Time : 2022/11/29 4:22 下午
# @Software: f0ng
from flask import Flask,Response,render_template
app = Flask(__name__)
import requests,time
proxies = {
'http':'127.0.0.1:8080',
'https':'127.0.0.1:8080'
}
def shibie():
headers = { # 校验用户信息
"Cookie":"ASP.NET_SessionId=fmbv2azmygla0hfkt3v5dupt",
}
url = 'http://xxxxx.xxxx/CreateCode' # 目标下载链接
r = requests.get(url ,headers=headers ,proxies=proxies) # 发送请求
with open ('1.gif', 'wb+') as f:
f.write(r.content)
f.close
from PIL import Image, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
import os
gifFileName = '1.gif'
# 使用Image模块的open()方法打开gif动态图像时,默认是第一帧
im = Image.open(gifFileName)
pngDir = gifFileName[:-4]
# 创建存放每帧图片的文件夹(文件夹名与图片名称相同)
if os.path.exists(pngDir) == False:
os.mkdir(pngDir)
try:
while True:
# 保存当前帧图片
current = im.tell()
im.save(pngDir + '/' + str(current) + '.png')
# 获取下一帧图片
im.seek(current + 1)
except EOFError:
print("pass")
@app.route("/1")
def index3():
shibie()
with open("1/0.png", 'rb') as f:
image = f.read()
resp = Response(image, mimetype="image/jpeg")
return resp
if __name__ == '__main__':
app.debug = True # 设置调试模式,生产模式的时候要关掉debug
app.run(host="0.0.0.0", port="8888")
代码先将gif截取成1.png,再通过接口/1
返回1.png的图片,故获取验证码的请求可以改为本地的/1
请求,如下图
实现成功
插件里获取验证码->识别->手动在repeater输入->显示验证码是否正确
如果验证码不正确,说明请求验证码的cookie等校验用户信息不一致,需要加上该cookie等校验用户信息的参数,如果为二次处理验证码的请求,需在请求验证码的代码中带上用户cookie等校验用户信息的参数。
输入响应提取的正则,提取校验的关键字
在intruder中增加校验的参数@captcha-killer-modified@
在logger中可以看到实际的请求
右键模板,选择模板库->ddddocr即可
由于后续脚本增加了Basic认证,可以自行添加Basic认证头即可
- 可以更换关键字,或者直接输入类似
"iVBO
图片文件头后的base64编码如下:
感谢微信群师傅@手挥五弦 提供的解决方法
- 如果遇到base64的,以下案例可以使用
data:image/jpeg;base64
,其他情况类似
增加intruder的爆破时间,验证码加载需要时间
json格式中,在关键字中填写关键字;其他格式可以参考10-提取关键字错误
当遇到了验证码在验证码响应包里出现,如下:
可以直接通过工具提取验证码的值
在burp模块中使用@captcha-killer-modified@替换验证码参数即可 repeater举例,请求为
实际请求为
- 查看intruder的attack type是否为
Pitchfork
,如果不是,那就选中这个模式,再测试,否则会出现验证码固定的问题
- 选中
是否使用该插件
再进行测试
- 通过logger查看请求包,打开
\n
视图,查看是不是以\n
换行,如果是,请用send to captcha panel
发送验证码,正常情况下,http包是以\r\n
换行 - 排查是否有其他服务占用了8888端口(默认py文件会起服务部署在8888端口)
- 一般问题出在新版burp上,由于jdk的原因导致代码运行错误,可以下载相应jdk版本的插件
- 点击识别无响应,可以将服务识别端
codereg.py
放置在VPS上,使用公网地址访问即可
0.24.1
临时更新插件按钮,开启按钮才会使用该插件
降级Pillow的版本,比如使用9.5.0版本
pip uninstall -y Pillow
pip install Pillow==9.5.0
更换burp版本进行尝试,目前原因未知 使用0.25.3版本即可
运行脚本报错,The port is required to be int,将脚本中default="8888"
更改为default=8888
再次运行即可
使用reg2
模板【可能不够准确】
使用reg3
模板【默认不支持该接口,需捐赠,可试用验证码接口,捐赠到一定额度可以有若依验证码的识别接口,以及进内部群,内部群成员捐赠有折扣,后面可能会分享其他类型的技术,不局限于captcha-killer-modified这个插件,后期会酌情涨价】
在Burp Suite中无法实现,但是yakit中的插件可以实现(笔者开发,未公开)【默认不支持该接口,需捐赠捐赠到一定额度可以有该功能,以及进内部群,内部群成员捐赠有折扣,目前测试一秒两次登录请求、验证码错误会自动纠错】
- 不能获取验证码,说明插件配置有问题,也可能是插件不适配该类型的验证码
- 能获取到验证码,说明插件本身没问题;识别端返回错误或者不返回,极有可能是python服务运行有问题,或者启动了代理,可以尝试关闭代理、更换jdk等方式尝试解决
正确做法✅:抛出完整的逻辑,如我遇到了什么问题,在FAQ或者README中按照xxx方式进行了调试,具体问题是识别到了验证码,但是接口返回错误,并给出完整的截图,包括模板、python文件启动截图、识别日志等
错误做法❌:《我验证码获取不到》、《这个验证码识别不了》、《怎么识别验证码》、诸如此类等
- 检查线程是否为1
- 检查延时是否超过1秒,如果1秒不行,则直接加大成5秒,站点的响应速度不同,延时也并非一成不变的