def from_address(cls, address: int, view: BinaryView) -> Category: if address == 0: return None from .class_t import Class, ClassRO category_t_type = view.types['category_t'] category_t = Type.named_type_from_type('category_t', category_t_type) if view.get_data_var_at(address) is None: view.define_user_data_var(address, category_t) members = get_structure_members(address, category_t_type, view) members['name'] = (view.get_ascii_string_at(members['name'], 1).value if members['name'] else '') members['cls'] = Class.from_address(members['cls'], view) if members['cls'] is None: cls_offset = next(m.offset for m in category_t_type.structure.members if m.name == 'cls') cls_name = view.get_symbol_at(address + cls_offset) cls_name = cls_name.name if cls_name is not None else members[ 'name'] class_match = re.match( r'_OBJC_(META)?CLASS_\$_(?P<classname>[_A-Za-z0-9=/]+)(@GOT)?', cls_name) if class_match is not None: cls_name = class_match.group('classname') cls_ = view.session_data['ClassNames'].get(cls_name) if cls_ is None: cls_ = Class(None, view, None, None, None, {}, {}) cls_.vtable = ClassRO(address, *([None] * 11)) cls_.vtable.name = cls_name view.session_data['ClassNames'][cls_name] = cls_ members['cls'] = cls_ else: cls_name = members['cls'].vtable.name members['instanceMethods'] = MethodList.from_address( members['instanceMethods'], cls_name, view) if members['cls'] is not None and not members['cls'].methods: members['cls']._methods = members['instanceMethods'].methods elif members['cls'] is not None: members['cls']._methods.update(members['instanceMethods'].methods) members['protocols'] = ProtocolList.from_address( members['protocols'], view) return cls(address, **members)
def add_objects_to_library(lib: TypeLibrary, view: BinaryView): for address, var in view.data_vars.items(): symbol = view.get_symbol_at(address) if symbol is None: continue symbol_type = Symbol.type if symbol_type != SymbolType.DataSymbol: continue lib.add_named_object(symbol.raw_name, var.type)
def perform_get_lines_for_data(self, ctxt, view: BinaryView, addr: int, type_: Type, prefix: list, width: int, context): from_bytes = _get_from_bytes(view) symbol: Symbol = view.get_symbol_at(addr) cfstring = view.types.get('CFString') if cfstring is None: log_debug('CFString is not defined; how did we even get here?') return [DisassemblyTextLine(prefix, addr)] cfstring = cfstring.structure buffer = from_bytes( view.read(addr + cfstring['buffer'].offset, view.address_size)) info = from_bytes( view.read(addr + cfstring['info'].offset, cfstring['info'].type.width)) length = from_bytes( view.read(addr + cfstring['length'].offset, cfstring['length'].type.width)) if info & 0xff == 0xc8: info_string = 'noinline,default,nofree,NI' elif info & 0xff == 0xd0: info_string = 'noinline,default,nofree,EUI' else: info_string = ( f'{_cfstring_allocator_properties[(info >> 5) & 0x3]},' f'{"U" if info & 16 else ""}' f'{"N" if info & 8 else ""}' f'{"L" if info & 4 else ""}' f'{"I" if info & 1 else ""}') if 'U' not in info_string: string = view.get_ascii_string_at(buffer, 0) if string is None: log_debug('string returned None; how did we even get here?') return [DisassemblyTextLine(prefix, addr)] string = string.value else: string = view.read(buffer, length * 2) if symbol is None: name = f'data_{addr:x}' else: name = symbol.short_name prefix = [ InstructionTextToken(InstructionTextTokenType.TypeNameToken, 'CFString'), InstructionTextToken(InstructionTextTokenType.TextToken, ' '), InstructionTextToken(InstructionTextTokenType.AnnotationToken, f'{{{info_string}}}'), InstructionTextToken(InstructionTextTokenType.TextToken, ' '), InstructionTextToken(InstructionTextTokenType.DataSymbolToken, name, addr), InstructionTextToken(InstructionTextTokenType.TextToken, ' = '), InstructionTextToken(InstructionTextTokenType.StringToken, f'{string!r}', buffer), InstructionTextToken(InstructionTextTokenType.TextToken, ' ') ] return [DisassemblyTextLine(prefix, addr)]