def determine_map(cls, module: interfaces.context.ModuleInterface) -> \ Dict[str, List[Tuple[int, int]]]: """Returns the virtual map from a windows kernel module.""" layer = module.context.layers[module.layer_name] if not isinstance(layer, intel.Intel): raise result = {} # type: Dict[str, List[Tuple[int, int]]] try: system_va_type = module.get_enumeration('_MI_SYSTEM_VA_TYPE') large_page_size = (layer.page_size** 2) // module.get_type("_MMPTE").size except exceptions.SymbolError: raise exceptions.SymbolError("Required structures not found") if module.has_symbol('MiVisibleState'): symbol = module.get_symbol('MiVisibleState') visible_state = module.object( object_type='pointer', offset=symbol.address, subtype=module.get_type('_MI_VISIBLE_STATE')).dereference() if hasattr(visible_state, 'SystemVaRegions'): for i in range(visible_state.SystemVaRegions.count): lookup = system_va_type.lookup(i) region_range = result.get(lookup, []) region_range.append( (visible_state.SystemVaRegions[i].BaseAddress, visible_state.SystemVaRegions[i].NumberOfBytes)) result[lookup] = region_range elif hasattr(visible_state, 'SystemVaType'): system_range_start = module.object( object_type="pointer", offset=module.get_symbol("MmSystemRangeStart").address) result = cls._enumerate_system_va_type( large_page_size, system_range_start, module, visible_state.SystemVaType) else: raise exceptions.SymbolError("Required structures not found") elif module.has_symbol('MiSystemVaType'): system_range_start = module.object( object_type="pointer", offset=module.get_symbol("MmSystemRangeStart").address) symbol = module.get_symbol('MiSystemVaType') array_count = (0xFFFFFFFF + 1 - system_range_start) // large_page_size type_array = module.object(object_type='array', offset=symbol.address, count=array_count, subtype=module.get_type('char')) result = cls._enumerate_system_va_type(large_page_size, system_range_start, module, type_array) else: raise exceptions.SymbolError("Required structures not found") return result
def _enumerate_system_va_type(cls, large_page_size: int, system_range_start: int, module: interfaces.context.ModuleInterface, type_array: interfaces.objects.ObjectInterface) -> Dict[str, List[Tuple[int, int]]]: result = {} # type: Dict[str, List[Tuple[int, int]]] system_va_type = module.get_enumeration('_MI_SYSTEM_VA_TYPE') start = system_range_start prev_entry = -1 cur_size = large_page_size for entry in type_array: entry = system_va_type.lookup(entry) if entry != prev_entry: region_range = result.get(entry, []) region_range.append((start, cur_size)) result[entry] = region_range start = start + cur_size cur_size = large_page_size else: cur_size += large_page_size prev_entry = entry return result
def consume_type( self, module: interfaces.context.ModuleInterface, offset: int, length: int ) -> Tuple[Tuple[ Optional[interfaces.objects.ObjectInterface], Optional[str], Union[ None, List, interfaces.objects.ObjectInterface]], int]: """Returns a (leaf_type, name, object) Tuple for a type, and the number of bytes consumed.""" result = None, None, None # type: Tuple[Optional[interfaces.objects.ObjectInterface], Optional[str], Optional[Union[List, interfaces.objects.ObjectInterface]]] leaf_type = self.context.object(module.get_enumeration("LEAF_TYPE"), layer_name=module._layer_name, offset=offset) consumed = leaf_type.vol.base_type.size remaining = length - consumed if leaf_type in [ leaf_type.LF_CLASS, leaf_type.LF_CLASS_ST, leaf_type.LF_STRUCTURE, leaf_type.LF_STRUCTURE_ST, leaf_type.LF_INTERFACE ]: structure = module.object(object_type="LF_STRUCTURE", offset=offset + consumed) name_offset = structure.name.vol.offset - structure.vol.offset name, value, excess = self.determine_extended_value( leaf_type, structure.size, module, remaining - name_offset) structure.size = value structure.name = name consumed += remaining result = leaf_type, name, structure elif leaf_type in [leaf_type.LF_MEMBER, leaf_type.LF_MEMBER_ST]: member = module.object(object_type="LF_MEMBER", offset=offset + consumed) name_offset = member.name.vol.offset - member.vol.offset name, value, excess = self.determine_extended_value( leaf_type, member.offset, module, remaining - name_offset) member.offset = value member.name = name result = leaf_type, name, member consumed += member.vol.size + len(name) + 1 + excess elif leaf_type in [ leaf_type.LF_ARRAY, leaf_type.LF_ARRAY_ST, leaf_type.LF_STRIDED_ARRAY ]: array = module.object(object_type="LF_ARRAY", offset=offset + consumed) name_offset = array.name.vol.offset - array.vol.offset name, value, excess = self.determine_extended_value( leaf_type, array.size, module, remaining - name_offset) array.size = value array.name = name result = leaf_type, name, array consumed += remaining elif leaf_type in [leaf_type.LF_ENUMERATE]: enum = module.object(object_type='LF_ENUMERATE', offset=offset + consumed) name_offset = enum.name.vol.offset - enum.vol.offset name, value, excess = self.determine_extended_value( leaf_type, enum.value, module, remaining - name_offset) enum.value = value enum.name = name result = leaf_type, name, enum consumed += enum.vol.size + len(name) + 1 + excess elif leaf_type in [leaf_type.LF_ARGLIST, leaf_type.LF_ENUM]: enum = module.object(object_type="LF_ENUM", offset=offset + consumed) name_offset = enum.name.vol.offset - enum.vol.offset name = self.parse_string(enum.name, leaf_type < leaf_type.LF_ST_MAX, size=remaining - name_offset) enum.name = name result = leaf_type, name, enum consumed += remaining elif leaf_type in [leaf_type.LF_UNION]: union = module.object(object_type="LF_UNION", offset=offset + consumed) name_offset = union.name.vol.offset - union.vol.offset name = self.parse_string(union.name, leaf_type < leaf_type.LF_ST_MAX, size=remaining - name_offset) result = leaf_type, name, union consumed += remaining elif leaf_type in [ leaf_type.LF_MODIFIER, leaf_type.LF_POINTER, leaf_type.LF_PROCEDURE ]: obj = module.object(object_type=leaf_type.lookup(), offset=offset + consumed) result = leaf_type, None, obj consumed += remaining elif leaf_type in [leaf_type.LF_FIELDLIST]: sub_length = remaining sub_offset = offset + consumed fields = [] while length > consumed: subfield, sub_consumed = self.consume_type( module, sub_offset, sub_length) sub_consumed += self.consume_padding(module.layer_name, sub_offset + sub_consumed) sub_length -= sub_consumed sub_offset += sub_consumed consumed += sub_consumed fields.append(subfield) result = leaf_type, None, fields elif leaf_type in [leaf_type.LF_BITFIELD]: bitfield = module.object(object_type="LF_BITFIELD", offset=offset + consumed) result = leaf_type, None, bitfield consumed += remaining else: raise TypeError("Unhandled leaf_type: {}".format(leaf_type)) return result, consumed