コード例 #1
0
def _parseResponse(output, rsp):
    from mcl.object.Demarshaler import Demarshaler
    demarsh = Demarshaler(rsp)
    try:
        dnsHdr = _parseDnsHeader(demarsh)
    except:
        output.RecordError(
            'Response not long enough (%d) to contain valid DNS response' %
            len(rsp))
        return mcl.target.CALL_FAILED

    from mcl.object.XmlOutput import XmlOutput
    xml = XmlOutput()
    xml.Start('Dns')
    xml.AddAttribute('id', '0x%04x' % dnsHdr['id'])
    if dnsHdr['qr'] != 0:
        xml.AddSubElement('Response')
    xml.AddAttribute('opCode', '0x%02x' % dnsHdr['opcode'])
    if dnsHdr['aa'] != 0:
        xml.AddSubElement('Authority')
    if dnsHdr['tc'] != 0:
        xml.AddSubElement('Truncated')
    if dnsHdr['ra'] != 0:
        xml.AddSubElement('RecursionAvailable')
    rspStr = None
    if dnsHdr['rcode'] == 0:
        rspStr = 'No Error'
    elif dnsHdr['rcode'] == 1:
        rspStr = 'Format Error'
    elif dnsHdr['rcode'] == 2:
        rspStr = 'Server Failure'
    elif dnsHdr['rcode'] == 3:
        rspStr = 'Name Error (domain does not exist)'
    elif dnsHdr['rcode'] == 4:
        rspStr = 'Not Implemented'
    elif dnsHdr['rcode'] == 5:
        rspStr = 'Operation Refused'
    elif dnsHdr['rcode'] == 6:
        rspStr = 'The name exists'
    elif dnsHdr['rcode'] == 7:
        rspStr = 'The RRset (name,type) exists'
    elif dnsHdr['rcode'] == 8:
        rspStr = 'The RRset (name,type) does not exist'
    elif dnsHdr['rcode'] == 9:
        rspStr = 'The requestor is not authorized to perform this operation'
    elif dnsHdr['rcode'] == 10:
        rspStr = 'The zone specified is not a zone'
    elif dnsHdr['rcode'] == 16:
        rspStr = 'Bad Signature'
    elif dnsHdr['rcode'] == 17:
        rspStr = 'Bad Key'
    elif dnsHdr['rcode'] == 18:
        rspStr = 'Bad Time'
    else:
        rspStr = 'Unkown error'
    sub = xml.AddSubElement('ResponseCode')
    if rspStr != None:
        sub.SetText(rspStr)
    sub.AddAttribute('code', '%i' % dnsHdr['rcode'])
    sub = xml.AddSubElement('QuestionData')
    if dnsHdr['qdcount'] > 0:
        i = 0
        while i < dnsHdr['qdcount']:
            subsub = sub.AddSubElement('Question')
            _parseQuestion(demarsh, subsub)
            i = i + 1

    sub = xml.AddSubElement('AnswerData')
    if dnsHdr['ancount'] > 0:
        i = 0
        while i < dnsHdr['ancount']:
            subsub = sub.AddSubElement('Answer')
            _parseResource(demarsh, subsub)
            i = i + 1

    sub = xml.AddSubElement('NameServerData')
    if dnsHdr['nscount'] > 0:
        i = 0
        while i < dnsHdr['nscount']:
            subsub = sub.AddSubElement('NameServer')
            _parseResource(demarsh, subsub)
            i = i + 1

    sub = xml.AddSubElement('AdditionalRecordsData')
    if dnsHdr['arcount'] > 0:
        i = 0
        while i < dnsHdr['arcount']:
            subsub = sub.AddSubElement('AdditionalData')
            _parseResource(demarsh, subsub)
            i = i + 1

    output.RecordXml(xml)
    output.EndWithStatus(mcl.target.CALL_SUCCEEDED)
    return True
コード例 #2
0
class DemarshalMessage():

    def __init__(self, data=None):
        from mcl.object.Demarshaler import Demarshaler
        self.demarsh = Demarshaler()
        self.SetData(data)

    def __getitem__(self, index):
        onIndex = 0
        for key in self.m_cache.keys():
            for entry in self.m_cache[key]:
                if onIndex == index:
                    return {'key': entry['key'],'type': entry['type'],
                       'retrieved': entry['retrieved']
                       }
                onIndex = onIndex + 1

    def __iter__(self):
        self.onIndex = 0
        return self

    def next(self):
        if self.onIndex >= self.m_totalEntries:
            raise StopIteration
        else:
            entry = self.__getitem__(self.onIndex)
            self.onIndex = self.onIndex + 1
            return entry

    def FindBool(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_BOOL, instance)

    def FindData(self, key, type=MSG_TYPE_BINARY, instance=-1):
        return self._GetCacheEntryData(key, type, instance)

    def FindError(self, key, instance=-1):
        entry = self._GetCacheEntry(key, MSG_TYPE_BINARY, instance)
        self.demarsh.SetData(entry['data'])
        if IsBigEndian(entry['type']):
            endian = self.demarsh.BIG_ENDIAN
        else:
            endian = self.demarsh.LITTLE_ENDIAN
        errors = self.demarsh.GetError(endian)
        if self.demarsh.BytesLeft() != 0:
            if entry['retrieved'] == True:
                self.m_numRetrieved = self.m_numRetrieved - 1
            entry['retrieved'] = False
            raise RuntimeError('Failed to demarshal errors')
        return errors

    def FindMessage(self, key, instance=-1):
        return DemarshalMessage(self._GetCacheEntryData(key, MSG_TYPE_MSG, instance))

    def FindIpAddr(self, key, instance=-1):
        entry = self._GetCacheEntry(key, MSG_TYPE_BINARY, instance)
        self.demarsh.SetData(entry['data'])
        if IsBigEndian(entry['type']):
            endian = self.demarsh.BIG_ENDIAN
        else:
            endian = self.demarsh.LITTLE_ENDIAN
        ipAddr = self.demarsh.GetIpAddr(endian)
        if self.demarsh.BytesLeft() != 0:
            if entry['retrieved'] == True:
                self.m_numRetrieved = self.m_numRetrieved - 1
            entry['retrieved'] = False
            raise RuntimeError('Failed to demarshal IpAddr object')
        return ipAddr

    def FindS8(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_S8, instance)

    def FindS16(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_S16, instance)

    def FindS32(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_S32, instance)

    def FindS64(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_S64, instance)

    def FindString(self, key, instance=-1, encoding='utf-8', replace='backslashreplace'):
        entry = self.PeekByKey(key, instance)
        if entry == None:
            raise RuntimeError("Failed to find instance %d of key '0x%08x'" % (instance, key))
        if entry['type'] & MSG_TYPE_MASK == MSG_TYPE_UTF16:
            str = self.FindStringUtf16(key, instance)
            if encoding != None:
                return str.encode(encoding, replace)
            else:
                return str

        else:
            return self.FindStringUtf8(key, instance)
        return

    def FindStringUtf8(self, key, instance=-1):
        entry = self._GetCacheEntry(key, MSG_TYPE_UTF8, instance)
        strArray = entry['data']
        if len(strArray) == 0:
            return ''
        if strArray[len(strArray) - 1] != 0:
            if entry['retrieved'] == True:
                self.m_numRetrieved = self.m_numRetrieved - 1
            entry['retrieved'] = False
            raise RuntimeError('String to demarshal is not NULL-terminated')
        cList = list()
        for val in strArray:
            if val == 0:
                break
            cList.append(chr(val))

        return ''.join(cList)

    def FindStringUtf16(self, key, instance=-1):
        entry = self._GetCacheEntry(key, MSG_TYPE_UTF16, instance)
        if len(entry['data']) == 0:
            return ''
        cList = list()
        i = 0
        while i < len(entry['data']):
            if IsBigEndian(entry['type']):
                cList.append(unichr(entry['data'][i] << 8 | entry['data'][i + 1]))
            else:
                cList.append(unichr(entry['data'][i] | entry['data'][i + 1] << 8))
            i = i + 2

        if cList[len(cList) - 1] != '\x00':
            if entry['retrieved'] == True:
                self.m_numRetrieved = self.m_numRetrieved - 1
            entry['retrieved'] = False
            raise RuntimeError('String to demarshal is not NULL-terminated')
        del cList[len(cList) - 1]
        return ''.join(cList)

    def FindTime(self, key, instance=-1):
        entry = self._GetCacheEntry(key, MSG_TYPE_BINARY, instance)
        self.demarsh.SetData(entry['data'])
        if IsBigEndian(entry['type']):
            endian = self.demarsh.BIG_ENDIAN
        else:
            endian = self.demarsh.LITTLE_ENDIAN
        t = self.demarsh.GetTime(endian)
        if self.demarsh.BytesLeft() != 0:
            if entry['retrieved'] == True:
                self.m_numRetrieved = self.m_numRetrieved - 1
            entry['retrieved'] = False
            raise RuntimeError('Failed to demarshal Time object')
        return t

    def FindU8(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_U8, instance)

    def FindU16(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_U16, instance)

    def FindU32(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_U32, instance)

    def FindU64(self, key, instance=-1):
        return self._GetCacheEntryData(key, MSG_TYPE_U64, instance)

    def GetCount(self, key=MSG_KEY_INVALID):
        if key == MSG_KEY_INVALID:
            return self.m_totalEntries
        else:
            if self.m_cache.has_key(key):
                return len(self.m_cache[key])
            return 0

    def GetNumRetrieved(self):
        return self.m_numRetrieved

    def PeekByKey(self, key, instance=-1):
        try:
            entry = self._FindCacheEntry(key, instance)
            return {'key': entry['key'],'type': entry['type']}
        except:
            return None

        return None

    def Reset(self, key=MSG_KEY_INVALID, instance=-1):
        if self.m_cache != None:
            if key == MSG_KEY_INVALID and instance < 0:
                self.m_cache = None
            elif instance < 0:
                for entry in self.m_cache:
                    if entry['key'] == key:
                        if entry['retrieved'] == True:
                            self.m_numRetrieved = self.m_numRetrieved - 1
                        entry['retrieved'] = False

            elif instance < len(self.m_cache):
                if key == MSG_KEY_INVALID or self.m_cache[instance]['key'] == key:
                    if self.m_cache[instance]['retrieved'] == True:
                        self.m_numRetrieved = self.m_numRetrieved - 1
                    self.m_cache[instance]['retrieved'] = False
        return

    def SetData(self, data):
        self.m_cache = dict()
        self.m_numRetrieved = 0
        self.m_totalEntries = 0
        if data != None:
            self._ParseData(data)
        return

    def _FindCacheEntry(self, key, instance):
        if key == MSG_KEY_INVALID:
            onInstance = 0
            for key in self.m_cache.keys():
                for entry in self.m_cache[key]:
                    if instance < 0:
                        if not entry['retrieved']:
                            return entry
                    else:
                        if instance == onInstance:
                            return entry
                        onInstance = onInstance + 1

        else:
            onInstance = 0
            if self.m_cache.has_key(key):
                for entry in self.m_cache[key]:
                    if instance < 0:
                        if not entry['retrieved']:
                            return entry
                    else:
                        if instance == onInstance:
                            return entry
                        onInstance = onInstance + 1

        raise RuntimeError("Failed to find instance %d of key '0x%08x'" % (instance, key))

    def _GetCacheEntry(self, key, type, instance):
        entry = self._FindCacheEntry(key, instance)
        if type != MSG_TYPE_INVALID:
            if entry['type'] & MSG_TYPE_MASK != type:
                raise RuntimeError('Instance %d of key 0x%08x is not the correct type (expected=%u found=%u)' % (instance, key, type, entry['type'] & MSG_TYPE_MASK))
        entry['retrieved'] = True
        self.m_numRetrieved = self.m_numRetrieved + 1
        return entry

    def _GetCacheEntryData(self, key, type, instance):
        entry = self._GetCacheEntry(key, type, instance)
        self.demarsh.SetData(entry['data'])
        baseType = entry['type'] & MSG_TYPE_MASK
        if IsBigEndian(type):
            endian = self.demarsh.BIG_ENDIAN
        else:
            endian = self.demarsh.LITTLE_ENDIAN
        if baseType == MSG_TYPE_BOOL:
            if self.demarsh.GetU8() == 0:
                return False
            else:
                return True

        else:
            if baseType == MSG_TYPE_U8:
                return self.demarsh.GetU8()
            if baseType == MSG_TYPE_S8:
                return self.demarsh.GetS8()
            if baseType == MSG_TYPE_U16:
                return self.demarsh.GetU16(endian)
            if baseType == MSG_TYPE_S16:
                return self.demarsh.GetS16(endian)
            if baseType == MSG_TYPE_U32:
                return self.demarsh.GetU32(endian)
            if baseType == MSG_TYPE_S32:
                return self.demarsh.GetS32(endian)
            if baseType == MSG_TYPE_U64:
                return self.demarsh.GetU64(endian)
            if baseType == MSG_TYPE_S64:
                return self.demarsh.GetS64(endian)
            return entry['data']

    def _ParseData(self, data):
        import array
        if data == None or len(data) == 0:
            self.m_cache = dict()
            return
        else:
            version = data[0]
            if version != CURRENT_VERSION:
                raise RuntimeError('Failed to get valid version from data')
            currentIndex = 1
            while currentIndex < len(data):
                entry = {'retrieved': False}
                entry['type'] = data[currentIndex]
                currentIndex = currentIndex + 1
                if IsBigEndian(entry['type']):
                    entry['key'] = data[currentIndex] << 24 | data[currentIndex + 1] << 16 | data[currentIndex + 2] << 8 | data[currentIndex + 3]
                else:
                    entry['key'] = data[currentIndex] | data[currentIndex + 1] << 8 | data[currentIndex + 2] << 16 | data[currentIndex + 3] << 24
                currentIndex = currentIndex + 4
                entry['data'] = array.array('B')
                baseType = entry['type'] & MSG_TYPE_MASK
                if baseType == MSG_TYPE_BOOL or baseType == MSG_TYPE_U8 or baseType == MSG_TYPE_S8:
                    entry['data'].append(data[currentIndex])
                    currentIndex = currentIndex + 1
                elif baseType == MSG_TYPE_U16 or baseType == MSG_TYPE_S16:
                    entry['data'].extend(data[currentIndex:currentIndex + 2])
                    currentIndex = currentIndex + 2
                elif baseType == MSG_TYPE_U32 or baseType == MSG_TYPE_S32:
                    entry['data'].extend(data[currentIndex:currentIndex + 4])
                    currentIndex = currentIndex + 4
                elif baseType == MSG_TYPE_U64 or baseType == MSG_TYPE_S64:
                    entry['data'].extend(data[currentIndex:currentIndex + 8])
                    currentIndex = currentIndex + 8
                else:
                    if entry['type'] & MSG_TYPE_MODIFIER_SIZE_32:
                        if IsBigEndian(entry['type']):
                            size = data[currentIndex] << 24 | data[currentIndex + 1] << 16 | data[currentIndex + 2] << 8 | data[currentIndex + 3]
                        else:
                            size = data[currentIndex] | data[currentIndex + 1] << 8 | data[currentIndex + 2] << 16 | data[currentIndex + 3] << 24
                        currentIndex = currentIndex + 4
                    else:
                        size = data[currentIndex]
                        currentIndex = currentIndex + 1
                    entry['data'].extend(data[currentIndex:currentIndex + size])
                    currentIndex = currentIndex + size
                if not self.m_cache.has_key(entry['key']):
                    self.m_cache[entry['key']] = list()
                self.m_cache[entry['key']].append(entry)
                self.m_totalEntries = self.m_totalEntries + 1

            return
コード例 #3
0
 def __init__(self, data=None):
     from mcl.object.Demarshaler import Demarshaler
     self.demarsh = Demarshaler()
     self.SetData(data)
def DataHandlerMain(namespace, InputFilename, OutputFilename):
    import mcl.imports
    import mcl.data.Input
    import mcl.data.Output
    import mcl.status
    import mcl.target
    import mcl.object.Message
    mcl.imports.ImportNamesWithNamespace(namespace,
                                         'mca.survey.cmd.registryquery',
                                         globals())
    input = mcl.data.Input.GetInput(InputFilename)
    output = mcl.data.Output.StartOutput(OutputFilename, input)
    output.Start('RegistryQuery', 'registryquery', [])
    msg = mcl.object.Message.DemarshalMessage(input.GetData())
    if input.GetStatus() != mcl.status.MCL_SUCCESS:
        errorMsg = msg.FindMessage(mcl.object.Message.MSG_KEY_RESULT_ERROR)
        moduleError = errorMsg.FindU32(
            mcl.object.Message.MSG_KEY_RESULT_ERROR_MODULE)
        osError = errorMsg.FindU32(mcl.object.Message.MSG_KEY_RESULT_ERROR_OS)
        output.RecordModuleError(moduleError, osError, errorStrings)
        output.EndWithStatus(input.GetStatus())
        return True
    else:
        if msg.GetCount() == 0:
            output.EndWithStatus(mcl.target.CALL_SUCCEEDED)
            return True
        from mcl.object.XmlOutput import XmlOutput
        xml = XmlOutput()
        xml.Start('Keys')
        sub = None
        while msg.GetNumRetrieved() < msg.GetCount():
            if mcl.CheckForStop():
                output.EndWithStatus(mcl.target.CALL_FAILED)
                return False
            key = msg.FindMessage(MSG_KEY_RESULT_KEY)
            keyinfo = KeyInfo()
            keyinfo.Demarshal(key)
            sub = xml.AddSubElement('Key')
            sub.AddAttribute('name', keyinfo.name)
            sub.AddAttribute('hive', _getHiveString(keyinfo.hive))
            sub.AddTimeElement('LastUpdate', keyinfo.lastUpdate)
            sub.AddAttribute('class', keyinfo.classValue)
            if keyinfo.flags & KEY_FLAG_ACCESS_DENIED:
                sub.AddAttribute('denied', 'true')
            for entry in key:
                if entry['retrieved']:
                    continue
                if entry['key'] == MSG_KEY_RESULT_SUBKEY:
                    subkey = Subkey()
                    subkey.Demarshal(key)
                    sub2 = sub.AddSubElement('Subkey')
                    sub2.AddAttribute('name', subkey.name)
                    sub2.AddTimeElement('LastUpdate', subkey.lastUpdate)
                elif entry['key'] == MSG_KEY_RESULT_VALUE:
                    value = Value()
                    value.Demarshal(key)
                    sub2 = sub.AddSubElement('Value')
                    sub2.AddAttribute('name', value.name)
                    sub2.AddAttribute('type', _getTypeString(value.type))
                    sub2.AddAttribute('typeValue', '0x%x' % value.nativeType)
                    rawSub = sub2.AddSubElement('Raw')
                    rawSub.SetTextAsData(value.data)
                    from mcl.object.Demarshaler import Demarshaler
                    demarsh = Demarshaler(value.data)
                    dataEndian = demarsh.LITTLE_ENDIAN
                    if value.type == VALUE_TYPE_REG_DWORD:
                        try:
                            dword = demarsh.GetU32(dataEndian)
                            sub2.AddSubElementWithText('Translated',
                                                       '%u' % dword)
                        except:
                            pass

                    elif value.type == VALUE_TYPE_REG_DWORD_BIG_ENDIAN:
                        try:
                            dword = demarsh.GetU32(demarsh.BIG_ENDIAN)
                            sub2.AddSubElementWithText('Translated',
                                                       '%u' % dword)
                        except:
                            pass

                    elif value.type == VALUE_TYPE_REG_QWORD:
                        try:
                            qword = demarsh.GetU64(dataEndian)
                            sub2.AddSubElementWithText('Translated',
                                                       '%u' % qword)
                        except:
                            pass

                    elif value.type == VALUE_TYPE_REG_SZ or value.type == VALUE_TYPE_REG_EXPAND_SZ:
                        try:
                            if len(value.data) == 0:
                                str = ''
                            else:
                                if len(value.data) % 2:
                                    value.data.append(0)
                                cList = list()
                                i = 0
                                while i < len(value.data):
                                    if dataEndian == demarsh.BIG_ENDIAN:
                                        cList.append(
                                            unichr(value.data[i] << 8
                                                   | value.data[i + 1]))
                                    else:
                                        cList.append(
                                            unichr(value.data[i]
                                                   | value.data[i + 1] << 8))
                                    i = i + 2
                                    while len(cList) > 0 and cList[
                                            len(cList) - 1] == u'\x00':
                                        del cList[len(cList) - 1]

                                    str = u''.join(cList).encode(
                                        'utf-8', 'backslashreplace')

                            sub2.AddSubElementWithText('Translated', str)
                        except:
                            pass

                else:
                    output.RecordError('Unhandled item key (0x%08x)' %
                                       entry['key'])
                    output.EndWithStatus(mcl.target.CALL_FAILED)
                    return True

        output.RecordXml(xml)
        output.End()
        return True