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: Dict[str, List[Tuple[int, int]]] = {} system_va_type = module.get_enumeration('_MI_SYSTEM_VA_TYPE') large_page_size = (layer.page_size** 2) // module.get_type("_MMPTE").size 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(None, module.name, "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(None, module.name, "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: 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.""" 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 elif leaf_type in [leaf_type.LF_STRING_ID, leaf_type.LF_FUNC_ID]: string_id = module.object(object_type=leaf_type.lookup(), offset=offset + consumed) name_offset = string_id.name.vol.offset - string_id.vol.offset name = self.parse_string(string_id.name, leaf_type < leaf_type.LF_ST_MAX, size=remaining - name_offset) result = leaf_type, name, string_id elif leaf_type in [ leaf_type.LF_UDT_SRC_LINE, leaf_type.LF_UDT_MOD_SRC_LINE ]: src_line = module.object(object_type=leaf_type.lookup(), offset=offset + consumed) result = leaf_type, None, src_line elif leaf_type in [leaf_type.LF_BUILDINFO]: buildinfo = module.object(object_type=leaf_type.lookup(), offset=offset + consumed) buildinfo.arguments.count = buildinfo.count consumed += buildinfo.arguments.vol.size result = leaf_type, None, buildinfo else: raise TypeError("Unhandled leaf_type: {}".format(leaf_type)) return result, consumed
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.""" 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 type_handler, has_name, value_attribute = self.type_handlers.get( leaf_type.lookup(), ('LF_UNKNOWN', False, None)) if type_handler in ['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 type_handler in ['LF_BUILDINFO']: parsed_obj = module.object(object_type=type_handler, offset=offset + consumed) parsed_obj.arguments.count = parsed_obj.count consumed += parsed_obj.arguments.vol.size result = leaf_type, None, parsed_obj elif type_handler in self.type_handlers: parsed_obj = module.object(object_type=type_handler, offset=offset + consumed) current_consumed = remaining if has_name: name_offset = parsed_obj.name.vol.offset - parsed_obj.vol.offset if value_attribute: name, value, excess = self.determine_extended_value( leaf_type, getattr(parsed_obj, value_attribute), module, remaining - name_offset) setattr(parsed_obj, value_attribute, value) current_consumed = parsed_obj.vol.size + len( name) + 1 + excess else: name = self.parse_string(parsed_obj.name, leaf_type < leaf_type.LF_ST_MAX, size=remaining - name_offset) parsed_obj.name = name else: name = None result = leaf_type, name, parsed_obj consumed += current_consumed else: raise TypeError(f"Unhandled leaf_type: {leaf_type}") return result, consumed