Example #1
0
    def getLogOffAnswer(self, recvPacket):

        if self.isSMB2 is False:
            respSMBCommand = SMBCommand(SMB.SMB_COM_LOGOFF_ANDX)

            resp = NewSMBPacket()
            resp['Flags1'] = SMB.FLAGS1_REPLY
            resp['Pid'] = recvPacket['Pid']
            resp['Tid'] = recvPacket['Tid']
            resp['Mid'] = recvPacket['Mid']
            resp['Uid'] = recvPacket['Uid']

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

            resp.addCommand(respSMBCommand)

        else:
            respSMBCommand = SMB2Logoff_Response()

            resp = SMB2Packet()
            resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR
            resp['Status'] = STATUS_SUCCESS
            resp['CreditRequestResponse'] = 1
            resp['CreditCharge'] = recvPacket['CreditCharge']
            resp['Command'] = recvPacket['Command']
            resp['SessionID'] = recvPacket['SessionID']
            resp['Reserved'] = recvPacket['Reserved']
            resp['MessageID'] = recvPacket['MessageID']
            resp['TreeID'] = recvPacket['TreeID']
            resp['Data'] = respSMBCommand

        return resp
Example #2
0
 def getSMBPacket(self):
     data = self.__NBSession.recv_packet()
     try:
         packet = NewSMBPacket(data=data.get_trailer())
         smbCommand = SMBCommand(packet['Data'][0])
     except Exception, e:
         # Maybe a SMB2 packet?
         try:
             packet = SMB2Packet(data=data.get_trailer())
             smbCommand = None
         except Exception, e:
             LOG.error('SOCKS: %s' % str(e))
Example #3
0
 def __init__(self,
              remoteName,
              sessPort=445,
              extendedSecurity=True,
              nmbSession=None,
              negPacket=None):
     self.extendedSecurity = extendedSecurity
     SMB3.__init__(self,
                   remoteName,
                   remoteName,
                   sess_port=sessPort,
                   session=nmbSession,
                   negSessionResponse=SMB2Packet(negPacket))
Example #4
0
    def getSMBPacket(self):
        data = self.__NBSession.recv_packet()
        try:
            packet = NewSMBPacket(data=data.get_trailer())
            smbCommand = SMBCommand(packet['Data'][0])
        except Exception:
            # Maybe a SMB2 packet?
            try:
                packet = SMB2Packet(data=data.get_trailer())
                smbCommand = None
            except Exception as e:
                LOG.debug("Exception:", exc_info=True)
                LOG.error('SOCKS: %s' % str(e))

        return packet, smbCommand
Example #5
0
    def processSessionSetup(self, recvPacket):

        if self.isSMB2 is False:
            respSMBCommand = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
            smbCommand = SMBCommand(recvPacket['Data'][0])

            if smbCommand['WordCount'] == 12:
                respParameters = SMBSessionSetupAndX_Extended_Response_Parameters(
                )
                respData = SMBSessionSetupAndX_Extended_Response_Data()

                # First of all, we should received a type 1 message. Let's answer it
                # NEGOTIATE_MESSAGE
                challengeMessage = self.sessionData['CHALLENGE_MESSAGE']
                challengeMessage['flags'] &= ~(NTLMSSP_NEGOTIATE_SIGN)

                respToken = SPNEGO_NegTokenResp()
                # accept-incomplete. We want more data
                respToken['NegResult'] = '\x01'
                respToken['SupportedMech'] = TypesMech[
                    'NTLMSSP - Microsoft NTLM Security Support Provider']
                respToken['ResponseToken'] = str(challengeMessage)

                respParameters['SecurityBlobLength'] = len(respToken)
                respData['SecurityBlobLength'] = respParameters[
                    'SecurityBlobLength']
                respData['SecurityBlob'] = respToken.getData()

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

                resp = NewSMBPacket()
                resp['Flags1'] = SMB.FLAGS1_REPLY
                resp['Flags2'] = SMB.FLAGS2_NT_STATUS
                resp['Pid'] = recvPacket['Pid']
                resp['Tid'] = recvPacket['Tid']
                resp['Mid'] = recvPacket['Mid']
                resp['Uid'] = 0
                errorCode = STATUS_MORE_PROCESSING_REQUIRED
                resp['ErrorCode'] = errorCode >> 16
                resp['ErrorClass'] = errorCode & 0xff
                resp.addCommand(respSMBCommand)

                self.__NBSession.send_packet(resp.getData())
                recvPacket, smbCommand = self.getSMBPacket()

                sessionSetupParameters = SMBSessionSetupAndX_Extended_Parameters(
                    smbCommand['Parameters'])
                sessionSetupData = SMBSessionSetupAndX_Extended_Data()
                sessionSetupData[
                    'SecurityBlobLength'] = sessionSetupParameters[
                        'SecurityBlobLength']
                sessionSetupData.fromString(smbCommand['Data'])

                if unpack('B',
                          sessionSetupData['SecurityBlob'][0])[0] != ASN1_AID:
                    # If there no GSSAPI ID, it must be an AUTH packet
                    blob = SPNEGO_NegTokenResp(
                        sessionSetupData['SecurityBlob'])
                    token = blob['ResponseToken']
                else:
                    # NEGOTIATE packet
                    blob = SPNEGO_NegTokenInit(
                        sessionSetupData['SecurityBlob'])
                    token = blob['MechToken']

                # Now we should've received a type 3 message
                authenticateMessage = NTLMAuthChallengeResponse()
                authenticateMessage.fromString(token)

                try:
                    username = (
                        '%s/%s' %
                        (authenticateMessage['domain_name'].decode('utf-16le'),
                         authenticateMessage['user_name'].decode('utf-16le'))
                    ).upper()
                except UnicodeDecodeError:
                    # Not Unicode encoded?
                    username = ('%s/%s' %
                                (authenticateMessage['domain_name'],
                                 authenticateMessage['user_name'])).upper()

                # Check if we have a connection for the user
                if self.activeRelays.has_key(username):
                    LOG.info('SOCKS: Proxying client session for %s@%s(445)' %
                             (username, self.targetHost))
                    errorCode = STATUS_SUCCESS
                    smbClient = self.activeRelays[username][
                        'protocolClient'].session
                    uid = smbClient.getSMBServer().get_uid()
                else:
                    LOG.error('SOCKS: No session for %s@%s(445) available' %
                              (username, self.targetHost))
                    errorCode = STATUS_ACCESS_DENIED
                    uid = 0
                    smbClient = None

                resp = NewSMBPacket()
                resp['Flags1'] = recvPacket['Flags1'] | SMB.FLAGS1_REPLY
                resp['Flags2'] = recvPacket[
                    'Flags2'] | SMB.FLAGS2_EXTENDED_SECURITY
                resp['Command'] = recvPacket['Command']
                resp['Pid'] = recvPacket['Pid']
                resp['Tid'] = recvPacket['Tid']
                resp['Mid'] = recvPacket['Mid']
                resp['Uid'] = uid
                resp['ErrorCode'] = errorCode >> 16
                resp['ErrorClass'] = errorCode & 0xff
                respData['NativeOS'] = ''
                respData['NativeLanMan'] = ''

                if uid == 0:
                    resp['Data'] = '\x00\x00\x00'
                    smbClient = None
                else:
                    respToken = SPNEGO_NegTokenResp()
                    # accept-completed
                    respToken['NegResult'] = '\x00'
                    respParameters['SecurityBlobLength'] = len(respToken)
                    respData['SecurityBlobLength'] = respParameters[
                        'SecurityBlobLength']
                    respData['SecurityBlob'] = respToken.getData()

                    respSMBCommand['Parameters'] = respParameters
                    respSMBCommand['Data'] = respData
                    resp.addCommand(respSMBCommand)

                self.__NBSession.send_packet(resp.getData())

                return smbClient, username
            else:
                LOG.error(
                    'SOCKS: Can\'t handle standard security at the moment!')
                return None
        else:
            respSMBCommand = SMB2SessionSetup_Response()
            sessionSetupData = SMB2SessionSetup(recvPacket['Data'])

            securityBlob = sessionSetupData['Buffer']

            rawNTLM = False
            if unpack('B', securityBlob[0])[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']:
                        # Nope, do we know it?
                        if MechTypes.has_key(mechType):
                            mechStr = MechTypes[mechType]
                        else:
                            mechStr = hexlify(mechType)
                        LOG.debug(
                            "Unsupported MechType '%s', we just want NTLMSSP, answering"
                            % mechStr)
                        # We don't know the token, we answer back again saying
                        # we just support NTLM.
                        # ToDo: Build this into a SPNEGO_NegTokenResp()
                        respToken = '\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

                        resp = SMB2Packet()
                        resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR
                        resp['Status'] = STATUS_SUCCESS
                        resp['CreditRequestResponse'] = 1
                        resp['CreditCharge'] = recvPacket['CreditCharge']
                        resp['Command'] = recvPacket['Command']
                        resp['SessionID'] = 0
                        resp['Reserved'] = recvPacket['Reserved']
                        resp['MessageID'] = recvPacket['MessageID']
                        resp['TreeID'] = recvPacket['TreeID']
                        resp['Data'] = respSMBCommand

                        self.__NBSession.send_packet(resp.getData())
                        recvPacket, smbCommand = self.getSMBPacket()
                        return self.processSessionSetup(recvPacket)

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

            # NEGOTIATE_MESSAGE
            # First of all, we should received a type 1 message. Let's answer it
            challengeMessage = self.sessionData['CHALLENGE_MESSAGE']
            challengeMessage['flags'] &= ~(NTLMSSP_NEGOTIATE_SIGN)

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

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

            resp = SMB2Packet()
            resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR
            resp['Status'] = STATUS_MORE_PROCESSING_REQUIRED
            resp['CreditRequestResponse'] = 1
            resp['CreditCharge'] = recvPacket['CreditCharge']
            resp['Command'] = recvPacket['Command']
            resp['SessionID'] = 0
            resp['Reserved'] = recvPacket['Reserved']
            resp['MessageID'] = recvPacket['MessageID']
            resp['TreeID'] = recvPacket['TreeID']

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

            self.__NBSession.send_packet(resp.getData())
            recvPacket, smbCommand = self.getSMBPacket()

            sessionSetupData = SMB2SessionSetup(recvPacket['Data'])
            securityBlob = sessionSetupData['Buffer']

            blob = SPNEGO_NegTokenResp(securityBlob)
            token = blob['ResponseToken']

            # AUTHENTICATE_MESSAGE, here we deal with authentication
            authenticateMessage = NTLMAuthChallengeResponse()
            authenticateMessage.fromString(token)

            try:
                username = (
                    '%s/%s' %
                    (authenticateMessage['domain_name'].decode('utf-16le'),
                     authenticateMessage['user_name'].decode('utf-16le'))
                ).upper()
            except UnicodeDecodeError:
                # Not Unicode encoded?
                username = ('%s/%s' %
                            (authenticateMessage['domain_name'],
                             authenticateMessage['user_name'])).upper()

            respToken = SPNEGO_NegTokenResp()

            # Check if we have a connection for the user
            if self.activeRelays.has_key(username):
                LOG.info('SOCKS: Proxying client session for %s@%s(445)' %
                         (username, self.targetHost))
                errorCode = STATUS_SUCCESS
                smbClient = self.activeRelays[username][
                    'protocolClient'].session
                uid = smbClient.getSMBServer()._Session['SessionID']
            else:
                LOG.error('SOCKS: No session for %s@%s(445) available' %
                          (username, self.targetHost))
                errorCode = STATUS_ACCESS_DENIED
                uid = 0
                smbClient = None

            # accept-completed
            respToken['NegResult'] = '\x00'

            resp = SMB2Packet()
            resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR
            resp['Status'] = errorCode
            resp['CreditRequestResponse'] = 1
            resp['CreditCharge'] = recvPacket['CreditCharge']
            resp['Command'] = recvPacket['Command']
            resp['SessionID'] = uid
            resp['Reserved'] = recvPacket['Reserved']
            resp['MessageID'] = recvPacket['MessageID']
            resp['TreeID'] = recvPacket['TreeID']

            respSMBCommand['SecurityBufferOffset'] = 0x48

            # This is important for SAMBA client to work. If it is not set as a guest session,
            # SAMBA will *not* like the fact that the packets are not signed (even tho it was not enforced).
            respSMBCommand['SessionFlags'] = SMB2_SESSION_FLAG_IS_GUEST
            respSMBCommand['SecurityBufferLength'] = len(respToken)
            respSMBCommand['Buffer'] = respToken.getData()
            resp['Data'] = respSMBCommand

            self.__NBSession.send_packet(resp.getData())
            return smbClient, username
Example #6
0
    def getNegoAnswer(self, recvPacket):

        if self.isSMB2 is False:
            smbCommand = SMBCommand(recvPacket['Data'][0])
            respSMBCommand = SMBCommand(SMB.SMB_COM_NEGOTIATE)

            resp = NewSMBPacket()
            resp['Flags1'] = SMB.FLAGS1_REPLY
            resp['Pid'] = recvPacket['Pid']
            resp['Tid'] = recvPacket['Tid']
            resp['Mid'] = recvPacket['Mid']

            dialects = smbCommand['Data'].split('\x02')
            index = dialects.index('NT LM 0.12\x00') - 1
            # Let's fill the data for NTLM
            if recvPacket['Flags2'] & SMB.FLAGS2_EXTENDED_SECURITY:
                resp[
                    'Flags2'] = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_UNICODE
                _dialects_data = SMBExtended_Security_Data()
                _dialects_data['ServerGUID'] = 'A' * 16
                blob = SPNEGO_NegTokenInit()
                blob['MechTypes'] = [
                    TypesMech[
                        'NTLMSSP - Microsoft NTLM Security Support Provider']
                ]
                _dialects_data['SecurityBlob'] = blob.getData()

                _dialects_parameters = SMBExtended_Security_Parameters()
                _dialects_parameters[
                    'Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_NT_SMBS | SMB.CAP_UNICODE
                _dialects_parameters['ChallengeLength'] = 0

            else:
                resp['Flags2'] = SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_UNICODE
                _dialects_parameters = SMBNTLMDialect_Parameters()
                _dialects_data = SMBNTLMDialect_Data()
                _dialects_data['Payload'] = ''
                _dialects_data[
                    'Challenge'] = '\x11\x22\x33\x44\x55\x66\x77\x88'
                _dialects_parameters['ChallengeLength'] = 8
                _dialects_parameters[
                    'Capabilities'] = SMB.CAP_USE_NT_ERRORS | SMB.CAP_NT_SMBS

            _dialects_parameters['Capabilities'] |= SMB.CAP_RPC_REMOTE_APIS
            _dialects_parameters['DialectIndex'] = index
            _dialects_parameters[
                'SecurityMode'] = SMB.SECURITY_AUTH_ENCRYPTED | SMB.SECURITY_SHARE_USER
            _dialects_parameters['MaxMpxCount'] = 1
            _dialects_parameters['MaxNumberVcs'] = 1
            _dialects_parameters['MaxBufferSize'] = 64000
            _dialects_parameters['MaxRawSize'] = 65536
            _dialects_parameters['SessionKey'] = 0
            _dialects_parameters['LowDateTime'] = 0
            _dialects_parameters['HighDateTime'] = 0
            _dialects_parameters['ServerTimeZone'] = 0

            respSMBCommand['Data'] = _dialects_data
            respSMBCommand['Parameters'] = _dialects_parameters

            resp.addCommand(respSMBCommand)
        else:
            resp = SMB2Packet()
            resp['Flags'] = SMB2_FLAGS_SERVER_TO_REDIR
            resp['Status'] = STATUS_SUCCESS
            resp['CreditRequestResponse'] = 1
            resp['CreditCharge'] = 1
            resp['Command'] = SMB2_NEGOTIATE
            resp['SessionID'] = 0
            resp['MessageID'] = 0
            resp['TreeID'] = 0

            respSMBCommand = SMB2Negotiate_Response()

            respSMBCommand['SecurityMode'] = 1
            if isinstance(recvPacket, NewSMBPacket):
                respSMBCommand['DialectRevision'] = SMB2_DIALECT_WILDCARD
            else:
                respSMBCommand['DialectRevision'] = self.serverDialect
                resp['MessageID'] = 1
            respSMBCommand['ServerGuid'] = ''.join(
                [random.choice(string.letters) for _ in range(16)])
            respSMBCommand['Capabilities'] = 0x7
            respSMBCommand['MaxTransactSize'] = 65536
            respSMBCommand['MaxReadSize'] = 65536
            respSMBCommand['MaxWriteSize'] = 65536
            respSMBCommand['SystemTime'] = getFileTime(
                calendar.timegm(time.gmtime()))
            respSMBCommand['ServerStartTime'] = getFileTime(
                calendar.timegm(time.gmtime()))
            respSMBCommand['SecurityBufferOffset'] = 0x80

            blob = SPNEGO_NegTokenInit()
            blob['MechTypes'] = [
                TypesMech[
                    'NEGOEX - SPNEGO Extended Negotiation Security Mechanism'],
                TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']
            ]

            respSMBCommand['Buffer'] = blob.getData()
            respSMBCommand['SecurityBufferLength'] = len(
                respSMBCommand['Buffer'])

            resp['Data'] = respSMBCommand

        return resp
Example #7
0
    def tunnelConnection(self):
        # For the rest of the remaining packets, we should just read and send. Except when trying to log out,
        # that's forbidden! ;)
        while True:
            # 1. Get Data from client
            data = self.__NBSession.recv_packet().get_trailer()

            if len(data) == 0:
                break

            if self.isSMB2 is False:
                packet = NewSMBPacket(data=data)

                if packet['Command'] == SMB.SMB_COM_LOGOFF_ANDX:
                    # We do NOT want to get logged off do we?
                    LOG.debug(
                        'SOCKS: Avoiding logoff for %s@%s:%s' %
                        (self.username, self.targetHost, self.targetPort))
                    data = self.getLogOffAnswer(packet)
                else:
                    # 2. Send it to the relayed session
                    self.clientConnection.getSMBServer()._sess.send_packet(
                        str(data))

                    # 3. Get the target's answer
                    data = self.clientConnection.getSMBServer(
                    )._sess.recv_packet().get_trailer()

                    packet = NewSMBPacket(data=data)

                    if packet['Command'] == SMB.SMB_COM_TRANSACTION or packet[
                            'Command'] == SMB.SMB_COM_TRANSACTION2:
                        try:
                            while True:
                                # Anything else to read? with timeout of 1 sec. This is something to test or find
                                # a better way to control
                                data2 = self.clientConnection.getSMBServer(
                                )._sess.recv_packet(timeout=1).get_trailer()
                                self.__NBSession.send_packet(str(data))
                                data = data2
                        except Exception, e:
                            if str(e).find('timed out') > 0:
                                pass
                            else:
                                raise

                    if len(data) == 0:
                        break
            else:
                packet = SMB2Packet(data=data)
                origID = packet['MessageID']

                # Just in case, let's remove any signing attempt
                packet['Signature'] = ""
                packet['Flags'] &= ~(SMB2_FLAGS_SIGNED)

                # Let's be sure the TreeConnect Table is filled with fake data
                if self.clientConnection.getSMBServer(
                )._Session['TreeConnectTable'].has_key(
                        packet['TreeID']) is False:
                    self.clientConnection.getSMBServer(
                    )._Session['TreeConnectTable'][packet['TreeID']] = {}
                    self.clientConnection.getSMBServer(
                    )._Session['TreeConnectTable'][
                        packet['TreeID']]['EncryptData'] = False

                if packet['Command'] == SMB2_LOGOFF:
                    # We do NOT want to get logged off do we?
                    LOG.debug(
                        'SOCKS: Avoiding logoff for %s@%s:%s' %
                        (self.username, self.targetHost, self.targetPort))
                    data = self.getLogOffAnswer(packet)
                else:
                    # 2. Send it to the relayed session
                    self.clientConnection.getSMBServer().sendSMB(packet)

                    # 3. Get the target's answer
                    packet = self.clientConnection.getSMBServer().recvSMB()

                    if len(str(packet)) == 0:
                        break
                    else:
                        packet['MessageID'] = origID
                        data = str(packet)

            # 4. Send it back to the client
            self.__NBSession.send_packet(str(data))