Example #1
0
def smbCommandHook_SMB_COM_TREE_CONNECT_ANDX(connId, smbServer, SMBCommand,
                                             recvPacket):
    treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters(
        SMBCommand['Parameters'])

    treeConnectAndXData = smb.SMBTreeConnectAndX_Data(
        flags=recvPacket['Flags2'])
    treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters[
        'PasswordLength']
    treeConnectAndXData.fromString(SMBCommand['Data'])

    path = smbserver.decodeSMBString(recvPacket['Flags2'],
                                     treeConnectAndXData['Path'])
    local_path = ntpath.basename(path)
    service = smbserver.decodeSMBString(recvPacket['Flags2'],
                                        treeConnectAndXData['Service'])

    report_tree_connect_attempt(connId, {
        "Path": path,
        "local_path": local_path,
        "Service": service
    })

    return smbserver.SMBCommands.smbComTreeConnectAndX(smbserver.SMBCommands(),
                                                       connId, smbServer,
                                                       SMBCommand, recvPacket)
Example #2
0
def smbCommandHook_SMB_COM_TREE_CONNECT_ANDX(connId, smbServer, SMBCommand, recvPacket):
    treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters(SMBCommand['Parameters'])

    treeConnectAndXData = smb.SMBTreeConnectAndX_Data(flags=recvPacket['Flags2'])
    treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters['PasswordLength']
    treeConnectAndXData.fromString(SMBCommand['Data'])

    path = smbserver.decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Path'])
    local_path = ntpath.basename(path)
    service = smbserver.decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Service'])

    report_tree_connect_attempt(connId, {"Path": path, "local_path": local_path, "Service": service})

    return smbserver.SMBCommands.smbComTreeConnectAndX(smbserver.SMBCommands(), connId, smbServer, SMBCommand, recvPacket)
Example #3
0
    def queryPathInformation(self,
                             connId,
                             smbServer,
                             recvPacket,
                             parameters,
                             data,
                             maxDataCount=0):
        # The trick we play here is that Windows clients first ask for the file
        # and then it asks for the directory containing the file.
        # It is important to answer the right questions for the attack to work

        connData = smbServer.getConnectionData(connId)

        respSetup = ''
        respParameters = ''
        respData = ''
        errorCode = 0

        queryPathInfoParameters = smb.SMBQueryPathInformation_Parameters(
            flags=recvPacket['Flags2'], data=parameters)
        if len(data) > 0:
            queryPathInfoData = smb.SMBQueryPathInformation_Data(data)

        if connData['ConnectedShares'].has_key(recvPacket['Tid']):
            path = ''
            try:
                origPathName = decodeSMBString(
                    recvPacket['Flags2'], queryPathInfoParameters['FileName'])
                origPathName = os.path.normpath(origPathName.replace(
                    '\\', '/'))

                if connData.has_key('MS15011') is False:
                    connData['MS15011'] = {}

                smbServer.log(
                    "Client is asking for QueryPathInformation for: %s" %
                    origPathName, logging.INFO)
                if connData['MS15011'].has_key(
                        origPathName) or origPathName == '.':
                    # We already processed this entry, now it's asking for a directory
                    infoRecord, errorCode = queryPathInformation(
                        path, '/', queryPathInfoParameters['InformationLevel'])
                else:
                    # First time asked, asking for the file
                    infoRecord, errorCode = queryPathInformation(
                        path, self.defaultFile,
                        queryPathInfoParameters['InformationLevel'])
                    connData['MS15011'][os.path.dirname(
                        origPathName)] = infoRecord
            except Exception, e:
                #import traceback
                #traceback.print_exc()
                smbServer.log("queryPathInformation: %s" % e, logging.ERROR)

            if infoRecord is not None:
                respParameters = smb.SMBQueryPathInformationResponse_Parameters(
                )
                respData = infoRecord
Example #4
0
    def smbComNtCreateAndX(self, connId, smbServer, SMBCommand, recvPacket):
        connData = smbServer.getConnectionData(connId)

        ntCreateAndXParameters = smb.SMBNtCreateAndX_Parameters(SMBCommand['Parameters'])
        ntCreateAndXData       = smb.SMBNtCreateAndX_Data( flags = recvPacket['Flags2'], data = SMBCommand['Data'])

        respSMBCommand        = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX)

        #ntCreateAndXParameters.dump()

        # Let's try to avoid allowing write requests from the client back to us
        # not 100% bulletproof, plus also the client might be using other SMB
        # calls (e.g. SMB_COM_WRITE)
        createOptions =  ntCreateAndXParameters['CreateOptions']
        if createOptions & smb.FILE_DELETE_ON_CLOSE == smb.FILE_DELETE_ON_CLOSE:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['Disposition'] & smb.FILE_OVERWRITE == FILE_OVERWRITE:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['Disposition'] & smb.FILE_OVERWRITE_IF == FILE_OVERWRITE_IF:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['AccessMask'] & smb.FILE_WRITE_DATA == FILE_WRITE_DATA:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['AccessMask'] & smb.FILE_APPEND_DATA == FILE_APPEND_DATA:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['AccessMask'] & smb.GENERIC_WRITE == GENERIC_WRITE:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['AccessMask'] & 0x10000 == 0x10000:
            errorCode = STATUS_ACCESS_DENIED
        else:
            errorCode = STATUS_SUCCESS

        if errorCode == STATUS_ACCESS_DENIED:
            return [respSMBCommand], None, errorCode

        # 1. Let's grab the extension and map the file's contents we will deliver
        origPathName = os.path.normpath(decodeSMBString(recvPacket['Flags2'],ntCreateAndXData['FileName']).replace('\\','/'))

        _, origPathNameExtension = os.path.splitext(origPathName)
        origPathNameExtension = origPathNameExtension.upper()[1:]

        if origPathNameExtension.upper() in self.extensions:
            targetFile = self.extensions[origPathNameExtension.upper()]
        else:
            targetFile = self.defaultFile
        
        # 2. We change the filename in the request for our targetFile
        ntCreateAndXData['FileName'] = encodeSMBString( flags = recvPacket['Flags2'], text = targetFile)
        SMBCommand['Data'] = ntCreateAndXData.getData()
        smbServer.log("%s is asking for %s. Delivering %s" % (connData['ClientIP'], origPathName,targetFile),logging.INFO)

        # 3. We call the original call with our modified data
        return self.origsmbComNtCreateAndX(connId, smbServer, SMBCommand, recvPacket)
Example #5
0
    def smbComNtCreateAndX(self, connId, smbServer, SMBCommand, recvPacket):
        connData = smbServer.getConnectionData(connId)

        ntCreateAndXParameters = smb.SMBNtCreateAndX_Parameters(SMBCommand['Parameters'])
        ntCreateAndXData       = smb.SMBNtCreateAndX_Data( flags = recvPacket['Flags2'], data = SMBCommand['Data'])

        respSMBCommand        = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX)

        #ntCreateAndXParameters.dump()

        # Let's try to avoid allowing write requests from the client back to us
        # not 100% bulletproof, plus also the client might be using other SMB
        # calls (e.g. SMB_COM_WRITE)
        createOptions =  ntCreateAndXParameters['CreateOptions']
        if createOptions & smb.FILE_DELETE_ON_CLOSE == smb.FILE_DELETE_ON_CLOSE:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['Disposition'] & smb.FILE_OVERWRITE == FILE_OVERWRITE:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['Disposition'] & smb.FILE_OVERWRITE_IF == FILE_OVERWRITE_IF:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['AccessMask'] & smb.FILE_WRITE_DATA == FILE_WRITE_DATA:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['AccessMask'] & smb.FILE_APPEND_DATA == FILE_APPEND_DATA:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['AccessMask'] & smb.GENERIC_WRITE == GENERIC_WRITE:
            errorCode = STATUS_ACCESS_DENIED
        elif ntCreateAndXParameters['AccessMask'] & 0x10000 == 0x10000:
            errorCode = STATUS_ACCESS_DENIED
        else:
            errorCode = STATUS_SUCCESS

        if errorCode == STATUS_ACCESS_DENIED:
            return [respSMBCommand], None, errorCode

        # 1. Let's grab the extension and map the file's contents we will deliver
        origPathName = os.path.normpath(decodeSMBString(recvPacket['Flags2'],ntCreateAndXData['FileName']).replace('\\','/'))

        _, origPathNameExtension = os.path.splitext(origPathName)
        origPathNameExtension = origPathNameExtension.upper()[1:]

        if self.extensions.has_key(origPathNameExtension.upper()):
            targetFile = self.extensions[origPathNameExtension.upper()]
        else:
            targetFile = self.defaultFile
        
        # 2. We change the filename in the request for our targetFile
        ntCreateAndXData['FileName'] = encodeSMBString( flags = recvPacket['Flags2'], text = targetFile)
        SMBCommand['Data'] = str(ntCreateAndXData)
        smbServer.log("%s is asking for %s. Delivering %s" % (connData['ClientIP'], origPathName,targetFile),logging.INFO)

        # 3. We call the original call with our modified data
        return self.origsmbComNtCreateAndX(connId, smbServer, SMBCommand, recvPacket)
Example #6
0
    def queryPathInformation(self, connId, smbServer, recvPacket, parameters, data, maxDataCount = 0):
        # The trick we play here is that Windows clients first ask for the file
        # and then it asks for the directory containing the file.
        # It is important to answer the right questions for the attack to work
        
        connData = smbServer.getConnectionData(connId)

        respSetup = b''
        respParameters = b''
        respData = b''
        errorCode = 0

        queryPathInfoParameters = smb.SMBQueryPathInformation_Parameters(flags = recvPacket['Flags2'], data = parameters)

        if recvPacket['Tid'] in connData['ConnectedShares']:
            path = ''
            try:
               origPathName = decodeSMBString(recvPacket['Flags2'], queryPathInfoParameters['FileName'])
               origPathName = os.path.normpath(origPathName.replace('\\','/'))

               if ('MS15011' in connData) is False:
                   connData['MS15011'] = {}

               smbServer.log("Client is asking for QueryPathInformation for: %s" % origPathName,logging.INFO)
               if origPathName in connData['MS15011'] or origPathName == '.':
                   # We already processed this entry, now it's asking for a directory
                   infoRecord, errorCode = queryPathInformation(path, '/', queryPathInfoParameters['InformationLevel'])
               else:
                   # First time asked, asking for the file
                   infoRecord, errorCode = queryPathInformation(path, self.defaultFile, queryPathInfoParameters['InformationLevel'])
                   connData['MS15011'][os.path.dirname(origPathName)] = infoRecord
            except Exception as e:
               #import traceback
               #traceback.print_exc()
               smbServer.log("queryPathInformation: %s" % e,logging.ERROR)

            if infoRecord is not None:
                respParameters = smb.SMBQueryPathInformationResponse_Parameters()
                respData = infoRecord
        else:
            errorCode = STATUS_SMB_BAD_TID
           
        smbServer.setConnectionData(connId, connData)

        return respSetup, respParameters, respData, errorCode
Example #7
0
    def create_and_x(self, conn_id, smb_server, smb_command, recv_packet):
        """
        Our version of smbComNtCreateAndX looks for special test files and
        fools the rest of the framework into opening them as if they were
        normal files.
        """
        conn_data = smb_server.getConnectionData(conn_id)

        # Wrap processing in a try block which allows us to throw SmbException
        # to control the flow.
        try:
            ncax_parms = imp_smb.SMBNtCreateAndX_Parameters(
                smb_command["Parameters"])

            path = self.get_share_path(conn_data, ncax_parms["RootFid"],
                                       recv_packet["Tid"])
            log.info("[SMB] Requested share path: %s", path)

            disposition = ncax_parms["Disposition"]
            log.debug("[SMB] Requested disposition: %s", disposition)

            # Currently we only support reading files.
            if disposition != imp_smb.FILE_OPEN:
                raise SmbException(STATUS_ACCESS_DENIED,
                                   "Only support reading files")

            # Check to see if the path we were given is actually a
            # magic path which needs generating on the fly.
            if path not in [SERVER_MAGIC, TESTS_MAGIC]:
                # Pass the command onto the original handler.
                return imp_smbserver.SMBCommands.smbComNtCreateAndX(
                    conn_id, smb_server, smb_command, recv_packet)

            flags2 = recv_packet["Flags2"]
            ncax_data = imp_smb.SMBNtCreateAndX_Data(flags=flags2,
                                                     data=smb_command["Data"])
            requested_file = imp_smbserver.decodeSMBString(
                flags2, ncax_data["FileName"])
            log.debug("[SMB] User requested file '%s'", requested_file)

            if path == SERVER_MAGIC:
                fid, full_path = self.get_server_path(requested_file)
            else:
                assert (path == TESTS_MAGIC)
                fid, full_path = self.get_test_path(requested_file)

            resp_parms = imp_smb.SMBNtCreateAndXResponse_Parameters()
            resp_data = ""

            # Simple way to generate a fid
            if len(conn_data["OpenedFiles"]) == 0:
                fakefid = 1
            else:
                fakefid = conn_data["OpenedFiles"].keys()[-1] + 1
            resp_parms["Fid"] = fakefid
            resp_parms["CreateAction"] = disposition

            if os.path.isdir(path):
                resp_parms[
                    "FileAttributes"] = imp_smb.SMB_FILE_ATTRIBUTE_DIRECTORY
                resp_parms["IsDirectory"] = 1
            else:
                resp_parms["IsDirectory"] = 0
                resp_parms["FileAttributes"] = ncax_parms["FileAttributes"]

            # Get this file's information
            resp_info, error_code = imp_smbserver.queryPathInformation(
                "", full_path, level=imp_smb.SMB_QUERY_FILE_ALL_INFO)

            if error_code != STATUS_SUCCESS:
                raise SmbException(error_code, "Failed to query path info")

            resp_parms["CreateTime"] = resp_info["CreationTime"]
            resp_parms["LastAccessTime"] = resp_info["LastAccessTime"]
            resp_parms["LastWriteTime"] = resp_info["LastWriteTime"]
            resp_parms["LastChangeTime"] = resp_info["LastChangeTime"]
            resp_parms["FileAttributes"] = resp_info["ExtFileAttributes"]
            resp_parms["AllocationSize"] = resp_info["AllocationSize"]
            resp_parms["EndOfFile"] = resp_info["EndOfFile"]

            # Let's store the fid for the connection
            # smbServer.log("Create file %s, mode:0x%x" % (pathName, mode))
            conn_data["OpenedFiles"][fakefid] = {}
            conn_data["OpenedFiles"][fakefid]["FileHandle"] = fid
            conn_data["OpenedFiles"][fakefid]["FileName"] = path
            conn_data["OpenedFiles"][fakefid]["DeleteOnClose"] = False

        except SmbException as s:
            log.debug("[SMB] SmbException hit: %s", s)
            error_code = s.error_code
            resp_parms = ""
            resp_data = ""

        resp_cmd = imp_smb.SMBCommand(imp_smb.SMB.SMB_COM_NT_CREATE_ANDX)
        resp_cmd["Parameters"] = resp_parms
        resp_cmd["Data"] = resp_data
        smb_server.setConnectionData(conn_id, conn_data)

        return [resp_cmd], None, error_code
Example #8
0
    def smbComTreeConnectAndX(self, connId, smbServer, SMBCommand, recvPacket):
        connData = smbServer.getConnectionData(connId)

        resp = smb.NewSMBPacket()
        resp['Flags1'] = smb.SMB.FLAGS1_REPLY
        resp[
            'Flags2'] = smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_LONG_NAMES | recvPacket[
                'Flags2'] & smb.SMB.FLAGS2_UNICODE

        resp['Tid'] = recvPacket['Tid']
        resp['Mid'] = recvPacket['Mid']
        resp['Pid'] = connData['Pid']

        respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_TREE_CONNECT_ANDX)
        respParameters = smb.SMBTreeConnectAndXResponse_Parameters()
        respData = smb.SMBTreeConnectAndXResponse_Data()

        treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters(
            SMBCommand['Parameters'])

        if treeConnectAndXParameters['Flags'] & 0x8:
            respParameters = smb.SMBTreeConnectAndXExtendedResponse_Parameters(
            )

        treeConnectAndXData = smb.SMBTreeConnectAndX_Data(
            flags=recvPacket['Flags2'])
        treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters[
            'PasswordLength']
        treeConnectAndXData.fromString(SMBCommand['Data'])

        errorCode = STATUS_SUCCESS

        UNCOrShare = decodeSMBString(recvPacket['Flags2'],
                                     treeConnectAndXData['Path'])

        # Is this a UNC?
        if ntpath.ismount(UNCOrShare):
            path = UNCOrShare.split('\\')[3]
        else:
            path = ntpath.basename(UNCOrShare)

        # We won't search for the share.. all of them exist :P
        smbServer.log("TreeConnectAndX request for %s" % path, logging.INFO)
        #share = searchShare(connId, path, smbServer)
        share = {}
        # Simple way to generate a Tid
        if len(connData['ConnectedShares']) == 0:
            tid = 1
        else:
            tid = connData['ConnectedShares'].keys()[-1] + 1
        connData['ConnectedShares'][tid] = share
        connData['ConnectedShares'][tid]['path'] = '/'
        connData['ConnectedShares'][tid]['shareName'] = path
        resp['Tid'] = tid
        #smbServer.log("Connecting Share(%d:%s)" % (tid,path))

        respParameters['OptionalSupport'] = smb.SMB.SMB_SUPPORT_SEARCH_BITS

        if path == 'IPC$':
            respData['Service'] = 'IPC'
        else:
            respData['Service'] = path
        respData['PadLen'] = 0
        respData['NativeFileSystem'] = encodeSMBString(recvPacket['Flags2'],
                                                       'NTFS')

        respSMBCommand['Parameters'] = respParameters
        respSMBCommand['Data'] = respData

        resp['Uid'] = connData['Uid']
        resp.addCommand(respSMBCommand)
        smbServer.setConnectionData(connId, connData)

        return None, [resp], errorCode
Example #9
0
    def findFirst2(self, connId, smbServer, recvPacket, parameters, data,
                   maxDataCount):
        connData = smbServer.getConnectionData(connId)

        respSetup = ''
        respParameters = ''
        respData = ''
        errorCode = STATUS_SUCCESS
        findFirst2Parameters = smb.SMBFindFirst2_Parameters(
            recvPacket['Flags2'], data=parameters)

        # 1. Let's grab the extension and map the file's contents we will deliver
        origPathName = os.path.normpath(
            decodeSMBString(recvPacket['Flags2'],
                            findFirst2Parameters['FileName']).replace(
                                '\\', '/'))
        origFileName = os.path.basename(origPathName)

        _, origPathNameExtension = os.path.splitext(origPathName)
        origPathNameExtension = origPathNameExtension.upper()[1:]

        if self.extensions.has_key(origPathNameExtension.upper()):
            targetFile = self.extensions[origPathNameExtension.upper()]
        else:
            targetFile = self.defaultFile

        if (len(data) > 0):
            findFirst2Data = smb.SMBFindFirst2_Data(data)
        else:
            findFirst2Data = ''

        if connData['ConnectedShares'].has_key(recvPacket['Tid']):
            path = connData['ConnectedShares'][recvPacket['Tid']]['path']

            # 2. We call the normal findFirst2 call, but with our targetFile
            searchResult, searchCount, errorCode = findFirst2(
                path, targetFile, findFirst2Parameters['InformationLevel'],
                findFirst2Parameters['SearchAttributes'])

            respParameters = smb.SMBFindFirst2Response_Parameters()
            endOfSearch = 1
            sid = 0x80  # default SID
            searchCount = 0
            totalData = 0
            for i in enumerate(searchResult):
                #i[1].dump()
                try:
                    # 3. And we restore the original filename requested ;)
                    i[1]['FileName'] = encodeSMBString(
                        flags=recvPacket['Flags2'], text=origFileName)
                except:
                    pass

                data = i[1].getData()
                lenData = len(data)
                if (totalData + lenData) >= maxDataCount or (
                        i[0] + 1) > findFirst2Parameters['SearchCount']:
                    # We gotta stop here and continue on a find_next2
                    endOfSearch = 0
                    # Simple way to generate a fid
                    if len(connData['SIDs']) == 0:
                        sid = 1
                    else:
                        sid = connData['SIDs'].keys()[-1] + 1
                    # Store the remaining search results in the ConnData SID
                    connData['SIDs'][sid] = searchResult[i[0]:]
                    respParameters['LastNameOffset'] = totalData
                    break
                else:
                    searchCount += 1
                    respData += data
                    totalData += lenData

            respParameters['SID'] = sid
            respParameters['EndOfSearch'] = endOfSearch
            respParameters['SearchCount'] = searchCount
        else:
            errorCode = STATUS_SMB_BAD_TID

        smbServer.setConnectionData(connId, connData)

        return respSetup, respParameters, respData, errorCode
    def smbComTreeConnectAndX(self, connId, smbServer, SMBCommand, recvPacket):
        connData = smbServer.getConnectionData(connId)

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

        # Uncommenting this will stop at the first connection relayed and won't relaying until all targets
        # are processed. There might be a use case for this
        #if 'relayToHost' in connData:
        #    # Connection already relayed, let's just answer the request (that will return object not found)
        #    return self.smbComTreeConnectAndX(connId, smbServer, SMBCommand, recvPacket)

        try:
            if self.config.mode.upper() == 'REFLECTION':
                self.targetprocessor = TargetsProcessor(
                    singleTarget='SMB://%s:445/' % connData['ClientIP'])
            if self.authUser == '/':
                LOG.info(
                    'SMBD-%s: Connection from %s authenticated as guest (anonymous). Skipping target selection.'
                    % (connId, connData['ClientIP']))
                return self.origsmbComTreeConnectAndX(connId, smbServer,
                                                      recvPacket)
            self.target = self.targetprocessor.getTarget(
                identity=self.authUser)
            if self.target is None:
                # No more targets to process, just let the victim to fail later
                LOG.info(
                    'SMBD-%s: Connection from %s@%s controlled, but there are no more targets left!'
                    % (connId, self.authUser, connData['ClientIP']))
                return self.origsmbComTreeConnectAndX(connId, smbServer,
                                                      recvPacket)

            LOG.info(
                'SMBD-%s: Connection from %s@%s controlled, attacking target %s://%s'
                % (connId, self.authUser, connData['ClientIP'],
                   self.target.scheme, self.target.netloc))

            if self.config.mode.upper() == 'REFLECTION':
                # Force standard security when doing reflection
                LOG.debug("Downgrading to standard security")
                extSec = False
                recvPacket['Flags2'] += (~smb.SMB.FLAGS2_EXTENDED_SECURITY)
            else:
                extSec = True
            # Init the correct client for our target
            client = self.init_client(extSec)
        except Exception as e:
            LOG.error("Connection against target %s://%s FAILED: %s" %
                      (self.target.scheme, self.target.netloc, str(e)))
            self.targetprocessor.logTarget(self.target)
        else:
            connData['relayToHost'] = True
            connData['Authenticated'] = False
            del (connData['NEGOTIATE_MESSAGE'])
            del (connData['CHALLENGE_MESSAGE'])
            del (connData['AUTHENTICATE_MESSAGE'])
            connData['SMBClient'] = client
            connData['EncryptionKey'] = client.getStandardSecurityChallenge()
            smbServer.setConnectionData(connId, connData)

        resp = smb.NewSMBPacket()
        resp['Flags1'] = smb.SMB.FLAGS1_REPLY
        resp['Flags2'] = smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_LONG_NAMES | \
                         recvPacket['Flags2'] & smb.SMB.FLAGS2_UNICODE

        resp['Tid'] = recvPacket['Tid']
        resp['Mid'] = recvPacket['Mid']
        resp['Pid'] = connData['Pid']

        respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_TREE_CONNECT_ANDX)
        respParameters = smb.SMBTreeConnectAndXResponse_Parameters()
        respData = smb.SMBTreeConnectAndXResponse_Data()

        treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters(
            SMBCommand['Parameters'])

        if treeConnectAndXParameters['Flags'] & 0x8:
            respParameters = smb.SMBTreeConnectAndXExtendedResponse_Parameters(
            )

        treeConnectAndXData = smb.SMBTreeConnectAndX_Data(
            flags=recvPacket['Flags2'])
        treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters[
            'PasswordLength']
        treeConnectAndXData.fromString(SMBCommand['Data'])

        ## Process here the request, does the share exist?
        UNCOrShare = decodeSMBString(recvPacket['Flags2'],
                                     treeConnectAndXData['Path'])

        # Is this a UNC?
        if ntpath.ismount(UNCOrShare):
            path = UNCOrShare.split('\\')[3]
        else:
            path = ntpath.basename(UNCOrShare)

        # This is the key, force the client to reconnect.
        # It will loop until all targets are processed for this user
        errorCode = STATUS_NETWORK_SESSION_EXPIRED
        resp['ErrorCode'] = errorCode >> 16
        resp['_reserved'] = 0o3
        resp['ErrorClass'] = errorCode & 0xff

        if path == 'IPC$':
            respData['Service'] = 'IPC'
        else:
            respData['Service'] = path
        respData['PadLen'] = 0
        respData['NativeFileSystem'] = encodeSMBString(recvPacket['Flags2'],
                                                       'NTFS')

        respSMBCommand['Parameters'] = respParameters
        respSMBCommand['Data'] = respData

        resp['Uid'] = connData['Uid']
        resp.addCommand(respSMBCommand)
        smbServer.setConnectionData(connId, connData)

        return None, [resp], errorCode
Example #11
0
    def smbComTreeConnectAndX(self, connId, smbServer, SMBCommand, recvPacket):
        connData = smbServer.getConnectionData(connId)

        resp = smb.NewSMBPacket()
        resp['Flags1'] = smb.SMB.FLAGS1_REPLY
        resp['Flags2'] = smb.SMB.FLAGS2_EXTENDED_SECURITY | smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_LONG_NAMES | recvPacket['Flags2'] & smb.SMB.FLAGS2_UNICODE

        resp['Tid'] = recvPacket['Tid']
        resp['Mid'] = recvPacket['Mid']
        resp['Pid'] = connData['Pid']

        respSMBCommand        = smb.SMBCommand(smb.SMB.SMB_COM_TREE_CONNECT_ANDX)
        respParameters        = smb.SMBTreeConnectAndXResponse_Parameters()
        respData              = smb.SMBTreeConnectAndXResponse_Data()

        treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters(SMBCommand['Parameters'])

        if treeConnectAndXParameters['Flags'] & 0x8:
            respParameters        = smb.SMBTreeConnectAndXExtendedResponse_Parameters()

        treeConnectAndXData                    = smb.SMBTreeConnectAndX_Data( flags = recvPacket['Flags2'] )
        treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters['PasswordLength']
        treeConnectAndXData.fromString(SMBCommand['Data'])

        errorCode = STATUS_SUCCESS

        UNCOrShare = decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Path'])

        # Is this a UNC?
        if ntpath.ismount(UNCOrShare):
            path = UNCOrShare.split('\\')[3]
        else:
            path = ntpath.basename(UNCOrShare)

        # We won't search for the share.. all of them exist :P
        smbServer.log("TreeConnectAndX request for %s" % path, logging.INFO)
        #share = searchShare(connId, path, smbServer) 
        share = {}
        # Simple way to generate a Tid
        if len(connData['ConnectedShares']) == 0:
           tid = 1
        else:
           tid = connData['ConnectedShares'].keys()[-1] + 1
        connData['ConnectedShares'][tid] = share
        connData['ConnectedShares'][tid]['path'] = '/'
        connData['ConnectedShares'][tid]['shareName'] = path
        resp['Tid'] = tid
        #smbServer.log("Connecting Share(%d:%s)" % (tid,path))

        respParameters['OptionalSupport'] = smb.SMB.SMB_SUPPORT_SEARCH_BITS

        if path == 'IPC$':
            respData['Service']               = 'IPC'
        else:
            respData['Service']               = path
        respData['PadLen']                = 0
        respData['NativeFileSystem']      = encodeSMBString(recvPacket['Flags2'], 'NTFS' )

        respSMBCommand['Parameters']             = respParameters
        respSMBCommand['Data']                   = respData 

        resp['Uid'] = connData['Uid']
        resp.addCommand(respSMBCommand)
        smbServer.setConnectionData(connId, connData)

        return None, [resp], errorCode
Example #12
0
    def findFirst2(self, connId, smbServer, recvPacket, parameters, data, maxDataCount):
        connData = smbServer.getConnectionData(connId)

        respSetup = ''
        respParameters = ''
        respData = ''
        findFirst2Parameters = smb.SMBFindFirst2_Parameters( recvPacket['Flags2'], data = parameters)

        # 1. Let's grab the extension and map the file's contents we will deliver
        origPathName = os.path.normpath(decodeSMBString(recvPacket['Flags2'],findFirst2Parameters['FileName']).replace('\\','/'))
        origFileName = os.path.basename(origPathName)

        _, origPathNameExtension = os.path.splitext(origPathName)
        origPathNameExtension = origPathNameExtension.upper()[1:]

        if self.extensions.has_key(origPathNameExtension.upper()):
            targetFile = self.extensions[origPathNameExtension.upper()]
        else:
            targetFile = self.defaultFile

        if connData['ConnectedShares'].has_key(recvPacket['Tid']):
            path = connData['ConnectedShares'][recvPacket['Tid']]['path']

            # 2. We call the normal findFirst2 call, but with our targetFile
            searchResult, searchCount, errorCode = findFirst2(path, 
                          targetFile, 
                          findFirst2Parameters['InformationLevel'], 
                          findFirst2Parameters['SearchAttributes'] )

            respParameters = smb.SMBFindFirst2Response_Parameters()
            endOfSearch = 1
            sid = 0x80 # default SID
            searchCount = 0
            totalData = 0
            for i in enumerate(searchResult):
                #i[1].dump()
                try:
                    # 3. And we restore the original filename requested ;)
                    i[1]['FileName'] = encodeSMBString( flags = recvPacket['Flags2'], text = origFileName)
                except:
                    pass

                data = i[1].getData()
                lenData = len(data)
                if (totalData+lenData) >= maxDataCount or (i[0]+1) > findFirst2Parameters['SearchCount']:
                    # We gotta stop here and continue on a find_next2
                    endOfSearch = 0
                    # Simple way to generate a fid
                    if len(connData['SIDs']) == 0:
                       sid = 1
                    else:
                       sid = connData['SIDs'].keys()[-1] + 1
                    # Store the remaining search results in the ConnData SID
                    connData['SIDs'][sid] = searchResult[i[0]:]
                    respParameters['LastNameOffset'] = totalData
                    break
                else:
                    searchCount +=1
                    respData += data
                    totalData += lenData
                    

            respParameters['SID'] = sid
            respParameters['EndOfSearch'] = endOfSearch
            respParameters['SearchCount'] = searchCount
        else:
            errorCode = STATUS_SMB_BAD_TID   

        smbServer.setConnectionData(connId, connData)

        return respSetup, respParameters, respData, errorCode
Example #13
0
    def create_and_x(self, conn_id, smb_server, smb_command, recv_packet):
        """
        Our version of smbComNtCreateAndX looks for special test files and
        fools the rest of the framework into opening them as if they were
        normal files.
        """
        conn_data = smb_server.getConnectionData(conn_id)

        # Wrap processing in a try block which allows us to throw SmbException
        # to control the flow.
        try:
            ncax_parms = imp_smb.SMBNtCreateAndX_Parameters(
                smb_command["Parameters"])

            path = self.get_share_path(conn_data,
                                       ncax_parms["RootFid"],
                                       recv_packet["Tid"])
            log.info("[SMB] Requested share path: %s", path)

            disposition = ncax_parms["Disposition"]
            log.debug("[SMB] Requested disposition: %s", disposition)

            # Currently we only support reading files.
            if disposition != imp_smb.FILE_OPEN:
                raise SmbException(STATUS_ACCESS_DENIED,
                                   "Only support reading files")

            # Check to see if the path we were given is actually a
            # magic path which needs generating on the fly.
            if path not in [SERVER_MAGIC, TESTS_MAGIC]:
                # Pass the command onto the original handler.
                return imp_smbserver.SMBCommands.smbComNtCreateAndX(conn_id,
                                                                    smb_server,
                                                                    smb_command,
                                                                    recv_packet)

            flags2 = recv_packet["Flags2"]
            ncax_data = imp_smb.SMBNtCreateAndX_Data(flags=flags2,
                                                     data=smb_command[
                                                         "Data"])
            requested_file = imp_smbserver.decodeSMBString(
                flags2,
                ncax_data["FileName"])
            log.debug("[SMB] User requested file '%s'", requested_file)

            if path == SERVER_MAGIC:
                fid, full_path = self.get_server_path(requested_file)
            else:
                assert (path == TESTS_MAGIC)
                fid, full_path = self.get_test_path(requested_file)

            resp_parms = imp_smb.SMBNtCreateAndXResponse_Parameters()
            resp_data = ""

            # Simple way to generate a fid
            if len(conn_data["OpenedFiles"]) == 0:
                fakefid = 1
            else:
                fakefid = conn_data["OpenedFiles"].keys()[-1] + 1
            resp_parms["Fid"] = fakefid
            resp_parms["CreateAction"] = disposition

            if os.path.isdir(path):
                resp_parms[
                    "FileAttributes"] = imp_smb.SMB_FILE_ATTRIBUTE_DIRECTORY
                resp_parms["IsDirectory"] = 1
            else:
                resp_parms["IsDirectory"] = 0
                resp_parms["FileAttributes"] = ncax_parms["FileAttributes"]

            # Get this file's information
            resp_info, error_code = imp_smbserver.queryPathInformation(
                "", full_path, level=imp_smb.SMB_QUERY_FILE_ALL_INFO)

            if error_code != STATUS_SUCCESS:
                raise SmbException(error_code, "Failed to query path info")

            resp_parms["CreateTime"] = resp_info["CreationTime"]
            resp_parms["LastAccessTime"] = resp_info[
                "LastAccessTime"]
            resp_parms["LastWriteTime"] = resp_info["LastWriteTime"]
            resp_parms["LastChangeTime"] = resp_info[
                "LastChangeTime"]
            resp_parms["FileAttributes"] = resp_info[
                "ExtFileAttributes"]
            resp_parms["AllocationSize"] = resp_info[
                "AllocationSize"]
            resp_parms["EndOfFile"] = resp_info["EndOfFile"]

            # Let's store the fid for the connection
            # smbServer.log("Create file %s, mode:0x%x" % (pathName, mode))
            conn_data["OpenedFiles"][fakefid] = {}
            conn_data["OpenedFiles"][fakefid]["FileHandle"] = fid
            conn_data["OpenedFiles"][fakefid]["FileName"] = path
            conn_data["OpenedFiles"][fakefid]["DeleteOnClose"] = False

        except SmbException as s:
            log.debug("[SMB] SmbException hit: %s", s)
            error_code = s.error_code
            resp_parms = ""
            resp_data = ""

        resp_cmd = imp_smb.SMBCommand(imp_smb.SMB.SMB_COM_NT_CREATE_ANDX)
        resp_cmd["Parameters"] = resp_parms
        resp_cmd["Data"] = resp_data
        smb_server.setConnectionData(conn_id, conn_data)

        return [resp_cmd], None, error_code