Ejemplo n.º 1
0
def smbComTreeConnectAndX(packet, packetNum, SMBCommand, questions, replies):

    # Test return code is always 0, otherwise leave before doing anything
    if packet['ErrorCode'] != 0:
        return False

    print "SMB_COM_TREE_CONNECT_ANDX ",
    try:
        if (packet['Flags1'] & smb.SMB.FLAGS1_REPLY) == 0:
            # Query
            treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters(
                SMBCommand['Parameters'])
            treeConnectAndXData = smb.SMBTreeConnectAndX_Data()
            treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters[
                'PasswordLength']
            treeConnectAndXData.fromString(SMBCommand['Data'])
        else:
            # Response
            treeConnectAndXParameters = smb.SMBTreeConnectAndXResponse_Parameters(
                SMBCommand['Parameters'])
            #treeConnectAndXData       = smb.SMBTreeConnectAndXResponse_Data(SMBCommand['Data'])
    except Exception, e:
        print "ERROR: %s" % e
        print "Command: 0x%x" % packet['Command']
        print "Packet: %d %r" % (packetNum, packet.getData())
        return True
Ejemplo n.º 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)
Ejemplo n.º 3
0
    def do_lots(self, user, pwd_ansi, share, filename, domain=''):
        pkt = smb.NewSMBPacket()
        pkt['Flags1'] = 8

        sessionSetup = smb.SMBCommand(self.SMB_COM_SESSION_SETUP_ANDX)
        sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Parameters()
        sessionSetup['Data'] = smb.SMBSessionSetupAndX_Data()

        sessionSetup['Parameters']['MaxBuffer'] = 65535
        sessionSetup['Parameters']['MaxMpxCount'] = 2
        sessionSetup['Parameters']['VCNumber'] = os.getpid()
        sessionSetup['Parameters']['SessionKey'] = self.get_session_key()
        sessionSetup['Parameters']['AnsiPwdLength'] = len(pwd_ansi)
        sessionSetup['Parameters']['UnicodePwdLength'] = len('')
        sessionSetup['Parameters']['Capabilities'] = self.CAP_RAW_MODE

        sessionSetup['Data']['AnsiPwd'] = pwd_ansi
        sessionSetup['Data']['UnicodePwd'] = ''
        sessionSetup['Data']['Account'] = str(user)
        sessionSetup['Data']['PrimaryDomain'] = str(domain)
        sessionSetup['Data']['NativeOS'] = str(os.name)
        sessionSetup['Data']['NativeLanMan'] = 'pysmb'

        # This is an example of how to use chained ANDX commands

        treeConnect = smb.SMBCommand(self.SMB_COM_TREE_CONNECT_ANDX)
        treeConnect['Parameters'] = smb.SMBTreeConnectAndX_Parameters()
        treeConnect['Data'] = smb.SMBTreeConnectAndX_Data()
        treeConnect['Parameters']['PasswordLength'] = 1
        treeConnect['Data']['Password'] = '******'
        treeConnect['Data']['Path'] = share
        treeConnect['Data']['Service'] = smb.SERVICE_ANY

        openFile = smb.SMBCommand(self.SMB_COM_OPEN_ANDX)
        openFile['Parameters'] = smb.SMBOpenAndX_Parameters()
        openFile['Parameters']['DesiredAccess'] = smb.SMB_ACCESS_READ
        openFile['Parameters']['OpenMode'] = smb.SMB_O_OPEN
        openFile['Parameters']['SearchAttributes'] = 0
        openFile['Data'] = smb.SMBOpenAndX_Data()
        openFile['Data']['FileName'] = filename

        readAndX = smb.SMBCommand(self.SMB_COM_READ_ANDX)
        readAndX['Parameters'] = smb.SMBReadAndX_Parameters()
        readAndX['Parameters']['Offset'] = 0
        readAndX['Parameters']['Fid'] = 0
        readAndX['Parameters']['MaxCount'] = 4000

        pkt.addCommand(sessionSetup)
        pkt.addCommand(treeConnect)
        pkt.addCommand(openFile)
        pkt.addCommand(readAndX)

        # This is an example of how to make a loop with the chained commands
        # treeConnect['Parameters']['AndXCommand'] = self.SMB_COM_TREE_CONNECT_ANDX
        # treeConnect['Parameters']['AndXOffset'] = 72

        self.sendSMB(pkt)

        pkt = self.recvSMB()
Ejemplo n.º 4
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
    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