def add_members(view: BinaryView, structure: StructureBuilder, start: int, length: int): offset = 0 br = BinaryReader(view) if (dv := view.get_data_var_at(start)) is None: dv = view.get_next_data_var_after(start) offset = dv.address - start
def resolve_byte_sig_pattern(self, identifier): pattern = [] for byte in identifier.split(' '): if byte == '?': pattern.append(byte) elif byte != '': pattern.append(int(byte, 16)) br = BinaryReader(self) result = 0 length = len(pattern) - 1 for function in self.functions: br.seek(function.start) while self.get_functions_containing( br.offset + length ) != None and function in self.get_functions_containing(br.offset + length): found = True count = 0 for entry in pattern: byte = br.read8() count += 1 if entry != byte and entry != '?': found = False break br.offset -= count if found: result = br.offset break instruction_length = self.get_instruction_length(br.offset) #account for unknown or bad instruction if instruction_length == 0: break br.offset += instruction_length if result != 0: break if result == 0: return None else: return self.get_functions_containing(result)[0].lowest_address
def parse_binary(self): br = BinaryReader(self.rawbv) br.seek(0) binary_bytes = br.read(self.rawbv.end) self.bininfo = ELF('thisbinary', binary_bytes) self.text_seg = None self.text_seg_index = 0 for s in self.bininfo.segments: if s.header.p_type == PT.LOAD and s.header.p_flags & PF.EXEC: self.text_seg = s break self.text_seg_index += 1 if self.text_seg is None: show_message_box('Parse Fail', 'Can\'t find text segment of binary!', icon=MessageBoxIcon.ErrorIcon) return False return True
def xor_dec(bv, key, xref_funcs, y_offsets): br = BinaryReader(bv) bw = BinaryWriter(bv) print "Decrypted strings:" for xref in xref_funcs[0]: # print xref.function, hex(xref.address) il = xref.function.get_low_level_il_at(xref.address).medium_level_il if (il.operation == MediumLevelILOperation.MLIL_CALL): enc_str = il.params[0].value.value str_size = il.params[1].value.value diff = il.params[2].value.value dec_str = '' br.seek(enc_str) bw.seek(enc_str) for i in xrange(str_size): enc_byte = br.read8() x = ((enc_byte - diff) ^ key) + diff dec_str = dec_str + chr(x) # Patch binary bw.write8(x)
def analyze_cxx_abi(view, start=None, length=None, task=None): platform = view.platform arch = platform.arch void_p_ty = Type.pointer(arch, Type.void()) char_p_ty = Type.pointer(arch, Type.int(1)) unsigned_int_ty = Type.int(arch.default_int_size, False) signed_int_ty = Type.int(arch.default_int_size, True) base_type_info_ty = Type.named_type( NamedTypeReference(name='std::type_info')) base_type_info_ptr_ty = Type.pointer(arch, base_type_info_ty) def char_array_ty(length): return Type.array(Type.int(1), strings[0].length) def type_info_ty(kind=None): type_info_struct = Structure() type_info_struct.append(void_p_ty, 'vtable') type_info_struct.append(char_p_ty, 'name') if kind == 'si_class': type_info_struct.append(base_type_info_ptr_ty, 'base_type') return Type.structure_type(type_info_struct) def vtable_ty(vfunc_count): vtable_struct = Structure() vtable_struct.append(signed_int_ty, 'top_offset') vtable_struct.append(base_type_info_ptr_ty, 'typeinfo') vtable_struct.append(Type.array(void_p_ty, vfunc_count), 'functions') return Type.structure_type(vtable_struct) if platform.name.startswith("windows-"): long_size = arch.default_int_size else: long_size = arch.address_size if arch.name.startswith('x86'): char_signed = True else: char_signed = False # not always true short_size = 2 # not always true long_long_size = 8 # not always true ty_for_cxx_builtin = { 'void': Type.void(), 'wchar_t': Type.int(2, sign=char_signed, altname='wchar_t'), 'bool': Type.bool(), 'char': Type.int(1, sign=char_signed), 'signed char': Type.int(1, sign=True), 'unsigned char': Type.int(1, sign=False), 'short': Type.int(short_size, sign=True), 'unsigned short': Type.int(short_size, sign=False), 'int': Type.int(arch.default_int_size, sign=True), 'unsigned int': Type.int(arch.default_int_size, sign=False), 'long': Type.int(long_size, sign=True), 'unsigned long': Type.int(long_size, sign=False), 'long long': Type.int(long_long_size, sign=True), 'unsigned long long': Type.int(long_long_size, sign=False), '__int128': Type.int(16, sign=True), 'unsigned __int128': Type.int(16, sign=False), 'float': Type.float(4), 'double': Type.float(8), '__float80': Type.float(10), '__float128': Type.float(16), 'char32_t': Type.int(4, sign=char_signed, altname='char32_t'), 'char16_t': Type.int(2, sign=char_signed, altname='char16_t'), } def ty_from_demangler_node(node, cv_qual=frozenset(), arg_count_hint=None): if node.kind == 'builtin': if node.value in ty_for_cxx_builtin: return ty_for_cxx_builtin[node.value] else: return None elif node.kind in ['name', 'qual_name']: named_ty_ref = NamedTypeReference(name=str(node)) return Type.named_type(named_ty_ref) elif node.kind in ['pointer', 'lvalue', 'rvalue']: pointee_ty = ty_from_demangler_node(node.value) if pointee_ty is None: return None is_const = ('const' in cv_qual) is_volatile = ('volatile' in cv_qual) if node.kind == 'pointer': return Type.pointer(arch, pointee_ty, is_const, is_volatile) elif node.kind == 'lvalue': return Type.pointer( arch, pointee_ty, is_const, is_volatile, ref_type=ReferenceType.ReferenceReferenceType) elif node.kind == 'rvalue': return Type.pointer(arch, pointee_ty, is_const, is_volatile, ref_type=ReferenceType.RValueReferenceType) elif node.kind == 'cv_qual': return ty_from_demangler_node(node.value, cv_qual=node.qual) elif node.kind == 'func': is_ctor_dtor = False if node.name and node.name.kind == 'qual_name': qual_name = node.name.value if qual_name[-1].kind in ['ctor', 'dtor']: is_ctor_dtor = True if is_ctor_dtor: ret_ty = Type.void() elif node.ret_ty is not None: ret_ty = ty_from_demangler_node(node.ret_ty) if ret_ty is None: return None else: ret_ty = Type.int(arch.default_int_size).with_confidence(0) arg_nodes = list(node.arg_tys) arg_tys = [] var_arg = False if arg_nodes[-1].kind == 'builtin' and arg_nodes[-1].value == '...': arg_nodes.pop() var_arg = True elif arg_nodes[0].kind == 'builtin' and arg_nodes[ 0].value == 'void': arg_nodes = arg_nodes[1:] this_arg = False if node.name and node.name.kind == 'qual_name': qual_name = node.name.value if is_ctor_dtor or (arg_count_hint is not None and len(arg_nodes) == arg_count_hint - 1): this_arg = True this_node = Node('qual_name', qual_name[:-1]) this_ty = ty_from_demangler_node(this_node) if this_ty is None: return None arg_tys.append(Type.pointer(arch, this_ty)) for arg_node in arg_nodes: arg_ty = ty_from_demangler_node(arg_node) if arg_ty is None: return None arg_tys.append(arg_ty) ty = Type.function(ret_ty, arg_tys, variable_arguments=var_arg) if arg_count_hint is not None: # toplevel invocation, so return whether we inferred a this argument return this_arg, ty else: return ty else: log.log_warn("Cannot convert demangled AST {} to a type".format( repr(node))) reader = BinaryReader(view) def read(size): if size == 4: return reader.read32() elif size == 8: return reader.read64() else: assert False symbols = view.get_symbols(start, length) if task: task.set_total(len(symbols)) mangled_re = re.compile('_?_Z') demangler_failures = 0 for symbol in symbols: if task and not task.advance(): break if not mangled_re.match(symbol.raw_name): continue is_data = (symbol.type == SymbolType.DataSymbol) is_code = (symbol.type in [ SymbolType.FunctionSymbol, SymbolType.ImportedFunctionSymbol ]) raw_name, suffix = symbol.raw_name, '' if '@' in raw_name: match = re.match(r'^(.+?)(@.+)$', raw_name) raw_name, suffix = match.group(1), match.group(2) try: name_ast = parse_mangled(raw_name) if name_ast is None: log.log_warn( "Demangler failed to recognize {}".format(raw_name)) demangler_failures += 1 except NotImplementedError as e: log.log_warn("Demangler feature missing on {}: {}".format( raw_name, str(e))) demangler_failures += 1 if name_ast: if name_ast.kind == 'func': short_name = str(name_ast.name) else: short_name = str(name_ast) symbol = Symbol(symbol.type, symbol.address, short_name=short_name + suffix, full_name=str(name_ast) + suffix, raw_name=symbol.raw_name) else: symbol = Symbol(symbol.type, symbol.address, short_name=symbol.raw_name, full_name=None, raw_name=symbol.raw_name) view.define_auto_symbol(symbol) if name_ast is None: continue elif is_data and name_ast.kind == 'typeinfo_name': strings = view.get_strings(symbol.address, 1) if not strings: continue view.define_data_var(symbol.address, char_array_ty(length)) elif is_data and name_ast.kind == 'typeinfo': reader.offset = symbol.address + arch.address_size * 2 kind = None # heuristic: is this is an abi::__si_class_type_info? base_or_flags = read(arch.default_int_size) base_symbol = view.get_symbol_at(base_or_flags) if base_symbol and base_symbol.raw_name.startswith('_ZTI'): kind = 'si_class' view.define_data_var(symbol.address, type_info_ty(kind)) elif is_data and name_ast.kind == 'vtable': vtable_addr = symbol.address reader.offset = vtable_addr + arch.address_size * 2 while True: vfunc_count = 0 check_next = True while True: vfunc_ptr_symbol = view.get_symbol_at(reader.offset) if vfunc_ptr_symbol and vfunc_ptr_symbol.raw_name.startswith( '_Z'): # any C++ symbol definitely terminates the vtable check_next = False break # heuristic: existing function vfunc_addr = read(arch.address_size) if view.get_function_at(vfunc_addr): vfunc_count += 1 continue # explicitly reject null pointers; in position-independent code # address zero can belong to the executable segment if vfunc_addr == 0: check_next = False break # heuristic: pointer to executable memory vfunc_segment = view.get_segment_at(vfunc_addr) if vfunc_addr != 0 and vfunc_segment and vfunc_segment.executable: view.add_function(vfunc_addr) vfunc_count += 1 log.log_info( 'Discovered function at {:#x} via {}'.format( vfunc_addr, symbol.full_name or symbol.short_name)) changed = True continue # we've fell off the end of the vtable break view.define_data_var(vtable_addr, vtable_ty(vfunc_count)) if check_next: # heuristic: can another vtable follow this one? let's see if it has typeinfo, # since that should be always true for when we have a virtual base typeinfo_ptr = read(arch.address_size) typeinfo_ptr_symbol = view.get_symbol_at(typeinfo_ptr) if typeinfo_ptr_symbol and typeinfo_ptr_symbol.raw_name.startswith( '_ZTI'): vtable_addr = reader.offset - 2 * arch.address_size # documentat it with a symbol secondary_symbol_name = '{}_secondary_{:x}'.format( symbol.short_name, vtable_addr - symbol.address) secondary_symbol = Symbol( SymbolType.DataSymbol, vtable_addr, short_name=secondary_symbol_name) view.define_auto_symbol(secondary_symbol) continue break elif is_code and name_ast.kind == 'func': func = view.get_function_at(symbol.address) demangled = ty_from_demangler_node( name_ast, arg_count_hint=len(func.function_type.parameters)) if demangled is not None: this_arg, ty = demangled func.apply_auto_discovered_type(ty) view.update_analysis() if demangler_failures: log.log_warn('{} demangler failures'.format(demangler_failures))
class GenericBinary(BinaryView): MAGIC = b'' HDR_SIZE = 0 ARCH = 'aarch64' TEXT = 0 RODATA = 1 DATA = 2 BSS = 3 app_name = '' base = 0 bss_offset = 0 bss_size = 0 data_offset = 0 data_size = 0 dynamic = {} dynamic_offset = 0 dynstr = b'\x00' entrypoint = 0 eh_frame_hdr_size = 0 eh_frame_hdr_start = 0 hdr = b'' hdr_read_offset = 0 plt_entries = [] reader = BinaryReader relocations = [] rodata_offset = 0 rodata_size = 0 text_offset = 0 text_size = 0 writer = BinaryWriter def log(self, msg, error=False): msg = f'[Switch-Binja-Loader] {msg}' if not error: log_info(msg) else: log_error(msg) # Common Constructor def __init__(self, data): self.raw = data self.reader = BinaryReader(data, Endianness.LittleEndian) self.writer = BinaryWriter(data, Endianness.LittleEndian) @classmethod def is_valid_for_data(cls, data): return data.read(0, 4) == cls.MAGIC def page_align_up(self, value): return (value + 0xfff) // 0x1000 * 0x1000 def page_align_down(self, value): return value // 0x1000 * 0x1000 def page_pad(self, binary): return binary + b'\x00' * (self.page_align_up(len(binary)) - len(binary)) def up_signed(self, val, size): return unpack(LE + SIGNED_SIZE_MAP[size], val)[0] def make_section(self, name, offset, size): FLAGS = { '.text': SectionSemantics.ReadOnlyCodeSectionSemantics, '.rodata': SectionSemantics.ReadOnlyDataSectionSemantics } self.log( f"Making section {name} {hex(offset)}-{hex(offset + size)} (len: {hex(size)})" ) self.add_user_section( name, offset, size, FLAGS[name] if name in FLAGS else SectionSemantics.ReadWriteDataSectionSemantics) def make_segment(self, name, memory_offset, file_offset, size, empty=False): FLAGS = { '.text': SegmentFlag.SegmentExecutable | SegmentFlag.SegmentReadable, '.rodata': SegmentFlag.SegmentReadable, \ '.data': SegmentFlag.SegmentReadable | SegmentFlag.SegmentWritable, '.bss': SegmentFlag.SegmentReadable | SegmentFlag.SegmentWritable } self.add_user_segment(memory_offset, size, file_offset, size if not empty else 0, FLAGS[name]) self.make_section(name, memory_offset, size) def get_dynstr(self, o): return self.dynstr[o:self.dynstr.index(b'\x00', o)] def process_relocations(self, offset, size): locations = set() self.reader.seek(self.HDR_SIZE + offset) relocation_size = 8 if self.armv7 else 0x18 for x in range(size // relocation_size): if self.armv7: offset = self.reader.read32() info = self.reader.read32() addend = None r_type = info & 0xFF r_sym = info >> 8 else: offset = self.reader.read64() info = self.reader.read64() addend = self.up_signed(self.reader.read(8), 8) r_type = info & 0xFFFFFFFF r_sym = info >> 32 sym = self.syms[r_sym] if r_sym != 0 else None if r_type != R_AARCH64_TLSDESC and r_type != R_ARM_TLS_DESC: locations.add(offset) self.relocations.append((offset, r_type, sym, addend)) return locations def try_unmangle(self, value): if value[:2] != b'_Z': return (None, value) decoded_name = value.decode('ascii') demangled_type, demangled_name = demangle_gnu3(Architecture[self.ARCH], decoded_name) decoded_name = get_qualified_name(demangled_name) return (demangled_type, decoded_name) def init(self): self.log(f'Loading {self.name} {self.app_name}') self.raw = b'' self.platform = Architecture[self.ARCH].standalone_platform self.reader.seek(self.HDR_SIZE + 4) mod_offset = self.reader.read32() mod_file_offset = self.HDR_SIZE + mod_offset offset = self.HDR_SIZE self.make_segment('.text', self.base + self.text_offset, offset, self.text_size) offset += self.text_size self.make_segment('.rodata', self.base + self.rodata_offset, offset, self.rodata_size) offset += self.rodata_size self.make_segment('.data', self.base + self.data_offset, offset, self.data_size) offset += self.data_size self.reader.seek(mod_file_offset) if self.reader.read(4) != b'MOD0': self.log(f'MOD0(@ {hex(mod_offset)}) Magic invalid') else: self.log('Parsing MOD0') self.dynamic_offset = mod_offset + self.up_signed( self.reader.read(4), 4) dynamic_file_offset = self.HDR_SIZE + self.dynamic_offset if self.bss_offset == 0: self.bss_offset = mod_offset + self.up_signed( self.reader.read(4), 4) dynamic_size = self.bss_offset - self.dynamic_offset if self.bss_size == 0: bss_end = mod_offset + self.up_signed(self.reader.read(4), 4) self.bss_size = bss_end - self.bss_offset self.reader.seek(mod_file_offset + 0x10) self.eh_frame_hdr_start = mod_offset + self.up_signed( self.reader.read(4), 4) eh_frame_hdr_end = mod_offset + self.up_signed( self.reader.read(4), 4) self.eh_frame_hdr_size = eh_frame_hdr_end - self.eh_frame_hdr_start self.module_offset = mod_offset + self.up_signed( self.reader.read(4), 4) libnx = False if self.reader.read(4) == b'LNY0': libnx = True libnx_got_start = mod_offset + self.up_signed( self.reader.read(4), 4) libnx_got_end = mod_offset + self.up_signed( self.reader.read(4), 4) self.make_section('.got', self.base + libnx_got_start, libnx_got_end - libnx_got_start) self.reader.seek(dynamic_file_offset) tag1 = self.reader.read64() self.reader.seek(dynamic_file_offset + 0x10) tag2 = self.reader.read64() self.reader.seek(dynamic_file_offset) self.armv7 = tag1 > 0xFFFFFFFF or tag2 > 0xFFFFFFFF offset_size = 4 if self.armv7 else 8 self.reader.seek(dynamic_file_offset) self.dynamic = {x: [] for x in MULTIPLE_DTS} for index in range(dynamic_size // 0x10): if self.armv7: tag = self.reader.read32() val = self.reader.read32() else: tag = self.reader.read64() val = self.reader.read64() if tag == DT_NULL: break if tag in MULTIPLE_DTS: self.dynamic[tag].append(val) else: self.dynamic[tag] = val self.make_section('.dynamic', self.base + self.dynamic_offset, dynamic_size) if DT_STRTAB in self.dynamic and DT_STRSZ in self.dynamic: self.log("Reading .dynstr") self.reader.seek(self.HDR_SIZE + self.dynamic[DT_STRTAB]) self.dynstr = self.reader.read(self.dynamic[DT_STRSZ]) for start_key, size_key, name in [ (DT_STRTAB, DT_STRSZ, '.dynstr'), (DT_INIT_ARRAY, DT_INIT_ARRAYSZ, '.init_array'), (DT_FINI_ARRAY, DT_FINI_ARRAYSZ, '.fini_array'), (DT_RELA, DT_RELASZ, '.rela.dyn'), (DT_REL, DT_RELSZ, '.rel.dyn'), (DT_JMPREL, DT_PLTRELSZ, ('.rel.plt' if self.armv7 else '.rela.plt')), ]: if start_key in self.dynamic and size_key in self.dynamic: self.make_section(name, self.base + self.dynamic[start_key], self.dynamic[size_key]) needed = [self.get_dynstr(i) for i in self.dynamic[DT_NEEDED]] self.syms = [ ] # symbols, symbols is already an attribute for BinaryView if DT_SYMTAB in self.dynamic and DT_STRTAB in self.dynamic: self.reader.seek(self.HDR_SIZE + self.dynamic[DT_SYMTAB]) while True: if self.dynamic[DT_SYMTAB] < self.dynamic[ DT_STRTAB] and self.reader.offset - self.HDR_SIZE >= self.dynamic[ DT_STRTAB]: break if self.armv7: st_name = self.reader.read32() st_value = self.reader.read32() st_size = self.reader.read32() st_info = self.reader.read8() st_other = self.reader.read8() st_shndx = self.reader.read16() else: st_name = self.reader.read32() st_info = self.reader.read8() st_other = self.reader.read8() st_shndx = self.reader.read16() st_value = self.reader.read64() st_size = self.reader.read64() if st_name > len(self.dynstr): break self.syms.append( ElfSym(self.get_dynstr(st_name), st_info, st_other, st_shndx, st_value, st_size)) self.make_section('.dynsym', self.base + self.dynamic[DT_SYMTAB], (self.reader.offset - self.HDR_SIZE) - self.dynamic[DT_SYMTAB]) locations = set() plt_got_end = None if DT_REL in self.dynamic and DT_RELSZ in self.dynamic: locations |= self.process_relocations(self.dynamic[DT_REL], self.dynamic[DT_RELSZ]) if DT_RELA in self.dynamic and DT_RELASZ in self.dynamic: locations |= self.process_relocations(self.dynamic[DT_RELA], self.dynamic[DT_RELASZ]) if DT_JMPREL in self.dynamic and DT_PLTRELSZ in self.dynamic: plt_locations = self.process_relocations( self.dynamic[DT_JMPREL], self.dynamic[DT_PLTRELSZ]) locations |= plt_locations plt_got_start = min(plt_locations) plt_got_end = max(plt_locations) + offset_size if DT_PLTGOT in self.dynamic: self.make_section('.got.plt', self.base + self.dynamic[DT_PLTGOT], plt_got_end - plt_got_start) if not self.armv7: self.reader.seek(self.HDR_SIZE) text = self.reader.read(self.text_size) last = 12 while True: # This block was straight copy pasted from https://github.com/reswitched/loaders/blob/30a2f1f1d6c997a46cc4225c1f443c19d21fc66c/nxo64.py#L406 pos = text.find(pack('<I', 0xD61F0220), last) if pos == -1: break last = pos + 1 if (pos % 4) != 0: continue off = pos - 12 a, b, c, d = unpack_from('<IIII', text, off) if d == 0xD61F0220 and ( a & 0x9f00001f) == 0x90000010 and ( b & 0xffe003ff) == 0xf9400211: base = off & ~0xFFF immhi = (a >> 5) & 0x7ffff immlo = (a >> 29) & 3 paddr = base + ((immlo << 12) | (immhi << 14)) poff = ((b >> 10) & 0xfff) << 3 target = paddr + poff if plt_got_start <= target < plt_got_end: self.plt_entries.append((off, target)) text = b'' plt_start = min(self.plt_entries)[0] plt_end = max(self.plt_entries)[0] + 0x10 self.make_section('.plt', self.base + plt_start, plt_end - plt_start) if not libnx: if plt_got_end is not None: got_ok = False got_end = plt_got_end + offset_size while got_end in locations and ( DT_INIT_ARRAY not in self.dynamic or got_end < self.dynamic[DT_INIT_ARRAY]): got_ok = True got_end += offset_size if got_ok: self.make_section('.got', self.base + plt_got_end, got_end - plt_got_end) else: plt_got_start = 0 plt_got_end = 0 self.bss_offset = self.bss_offset self.bss_size = self.page_align_up(self.bss_size) self.make_segment('.bss', self.base + self.bss_offset, 0, self.bss_size, empty=True) undefined_count = 0 for sym in self.syms: if not sym.shndx and sym.name: undefined_count += 1 last_ea = max([self.base + seg.end for seg in self.segments]) undef_ea = self.page_align_up(last_ea) + 8 undef_offset = self.base + plt_got_start for idx, symbol in enumerate(self.syms): if symbol.name: symbol.resolved = self.base + symbol.value decoded_type, decoded_name = self.try_unmangle(symbol.name) if symbol.shndx: if symbol.type == STT_FUNC: self.create_user_function(symbol.resolved) self.define_user_symbol( Symbol(SymbolType.FunctionSymbol, symbol.resolved, decoded_name)) if decoded_type is not None: self.get_function_at( symbol.resolved).set_user_type(decoded_type) else: if decoded_type is not None: self.define_data_var(symbol.resolved, decoded_type) self.define_user_symbol( Symbol(SymbolType.DataSymbol, symbol.resolved, decoded_name)) else: self.define_user_symbol( Symbol(SymbolType.ImportedFunctionSymbol, undef_ea, decoded_name)) undef_ea += offset_size got_name_lookup = {} for offset, r_type, symbol, addend in self.relocations: target = self.base + offset if symbol != None: decoded_type, decoded_name = self.try_unmangle(symbol.name) if decoded_type != None: self.define_data_var( target, Type.pointer(Architecture[self.ARCH], decoded_type)) self.define_auto_symbol( Symbol(SymbolType.DataSymbol, target, decoded_name)) else: decoded_type = decoded_name = None packed = None offset_raw = None if r_type in [R_ARM_GLOB_DAT, R_ARM_JUMP_SLOT, R_ARM_ABS32]: if symbol: offset_raw = symbol.resolved packed = pack(LE + UNSIGNED_SIZE_MAP[4], offset_raw) elif r_type == R_ARM_RELATIVE: self.reader.seek(target) offset_raw = self.base + self.reader.read32() packed = pack(LE + UNSIGNED_SIZE_MAP[4], offset_raw) elif r_type in [ R_AARCH64_GLOB_DAT, R_AARCH64_JUMP_SLOT, R_AARCH64_ABS64 ]: offset_raw = symbol.resolved + addend packed = pack(LE + UNSIGNED_SIZE_MAP[8], offset_raw) if addend == 0: got_name_lookup[offset] = symbol.name elif r_type == R_AARCH64_RELATIVE: offset_raw = self.base + addend packed = pack(LE + UNSIGNED_SIZE_MAP[8], offset_raw) if packed is not None: if offset_raw != self.base and offset_raw != self.base + 0x10 and offset_raw < self.base + self.text_offset + self.text_size: self.create_user_function(offset_raw) if decoded_type is not None: self.get_function_at(offset_raw).set_user_type( decoded_type) self.write(target, packed) for func, target in self.plt_entries: if target in got_name_lookup: addr = self.base + func decoded_type, decoded_name = self.try_unmangle( got_name_lookup[target]) self.define_user_symbol( Symbol(SymbolType.ImportedFunctionSymbol, addr, decoded_name)) # Try to find entrypoint if not already set if self.entrypoint == 0: for sym in self.syms: if sym.name == b'_init': self.entrypoint = sym.resolved break if self.entrypoint != 0: self.add_entry_point(self.entrypoint) return True
def __init__(self, data): self.raw = data self.reader = BinaryReader(data, Endianness.LittleEndian) self.writer = BinaryWriter(data, Endianness.LittleEndian)
def __init__(self, data): self.reader = BinaryReader(data, Endianness.LittleEndian) BinaryView.__init__(self, parent_view=data, file_metadata=data.file) self.data = data