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
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
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