Example #1
0
    def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLastChunk=True):
        pkt = smb.NewSMBPacket()
        pkt['Tid'] = tid

        command = pack('<H', setup)

        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

        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
Example #2
0
def smbTransaction2(packet, packetNum, SMBCommand, questions, replies):
    # Test return code is always 0, otherwise leave before doing anything
    if packet['ErrorCode'] != 0:
        return False

    print "SMB_COM_TRANSACTION2 ",
    try:
        if (packet['Flags1'] & smb.SMB.FLAGS1_REPLY) == 0:
            # Query

            trans2Parameters = smb.SMBTransaction2_Parameters(
                SMBCommand['Parameters'])

            # Do the stuff
            if trans2Parameters['ParameterCount'] != trans2Parameters[
                    'TotalParameterCount']:
                # TODO: Handle partial parameters
                #print "Unsupported partial parameters in TRANSACT2!"
                raise Exception("Unsupported partial parameters in TRANSACT2!")
            else:
                trans2Data = smb.SMBTransaction2_Data()
                # Standard says servers shouldn't trust Parameters and Data comes
                # in order, so we have to parse the offsets, ugly

                paramCount = trans2Parameters['ParameterCount']
                trans2Data['Trans_ParametersLength'] = paramCount
                dataCount = trans2Parameters['DataCount']
                trans2Data['Trans_DataLength'] = dataCount

                if trans2Parameters['ParameterOffset'] > 0:
                    paramOffset = trans2Parameters[
                        'ParameterOffset'] - 63 - trans2Parameters[
                            'SetupLength']
                    trans2Data['Trans_Parameters'] = SMBCommand['Data'][
                        paramOffset:paramOffset + paramCount]
                else:
                    trans2Data['Trans_Parameters'] = ''

                if trans2Parameters['DataOffset'] > 0:
                    dataOffset = trans2Parameters[
                        'DataOffset'] - 63 - trans2Parameters['SetupLength']
                    trans2Data['Trans_Data'] = SMBCommand['Data'][
                        dataOffset:dataOffset + dataCount]
        else:
            # Response
            # ToDo not implemented yet
            a = 1

    except Exception, e:
        print "ERROR: %s" % e
        print "Command: 0x%x" % packet['Command']
        print "Packet: %d %r" % (packetNum, packet.getData())
        return True
Example #3
0
def send_nt_trans(tid, setup, data, param, firstDataCnt):
	pkt = smb.NewSMBPacket()
	pkt['Tid'] = tid

	command = pack('<H', setup)

	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'] = firstDataCnt
	transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len

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

	conn.sendSMB(pkt)
	
	i = firstDataCnt
	while i < len(data):
		sendSize = min(4096, len(data) - i)
		send_trans2_second(tid, data[i:i+sendSize], i)
		i += sendSize
	
	conn.recvSMB()
Example #4
0
def send_trans2(conn, tid, setup, name, param, data):
    pkt = smb.NewSMBPacket()
    pkt['Tid'] = tid

    command = pack('<H', setup)

    transCommand = smb.SMBCommand(smb.SMB.SMB_COM_TRANSACTION2)
    transCommand['Parameters'] = smb.SMBTransaction2_Parameters()
    transCommand['Parameters']['MaxDataCount'] = len(data)
    transCommand['Data'] = smb.SMBTransaction2_Data()

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

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

    transCommand['Parameters']['ParameterCount'] = len(param)
    transCommand['Parameters']['ParameterOffset'] = 32 + 2 + 28 + len(
        command) + len(name) + padLen

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

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

    transCommand['Data']['Name'] = name
    transCommand['Data']['Trans_Parameters'] = param
    transCommand['Data']['Trans_Data'] = data
    pkt.addCommand(transCommand)

    conn.sendSMB(pkt)
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 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
    def send_big_transfer(connection,
                          tid,
                          setup,
                          data,
                          params,
                          first_fragment,
                          send_last=True):
        packet = smb.NewSMBPacket()
        packet['Tid'] = tid

        command = struct.pack('<H', setup)

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

        fixed_offset = 32 + 3 + 38 + len(command)

        if len(params) > 0:
            pad_len = (4 - fixed_offset % 4) % 4
            pad_bytes = '\xFF' * pad_len
            transfer_command['Data']['Pad1'] = pad_bytes
        else:
            transfer_command['Data']['Pad1'] = ''
            pad_len = 0

        transfer_command['Parameters']['ParameterCount'] = len(params)
        transfer_command['Parameters'][
            'ParameterOffset'] = fixed_offset + pad_len

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

        transfer_command['Parameters']['DataCount'] = first_fragment
        transfer_command['Parameters']['DataOffset'] = transfer_command['Parameters']['ParameterOffset'] + \
            len(params) + pad_to_len

        transfer_command['Data']['Trans_Parameters'] = params
        transfer_command['Data']['Trans_Data'] = data[:first_fragment]

        packet.addCommand(transfer_command)

        connection.sendSMB(packet)
        connection.recvSMB()  # must be success

        i = first_fragment
        while i < len(data):
            send_size = min(4096, len(data) - i)
            if len(data) - i <= 4096:
                if not send_last:
                    break
            send_transfer_second(connection, tid, data[i:i + send_size], i)
            i += send_size

        if send_last:
            connection.recvSMB()
        return i