def test_stream(): dirpath = os.path.join(test_location, "i386") filepath = os.path.join(dirpath, "fauxware") lib1path = os.path.join(dirpath, "libc.so.6") lib2path = os.path.join(dirpath, "ld-linux.so.2") path_ld = cle.Loader(filepath) stream_ld = cle.Loader(open(filepath, 'rb'), auto_load_libs=False, preload_libs=(open(lib1path, 'rb'), open(lib2path, 'rb'))) nose.tools.assert_equal(path_ld.main_object.entry, stream_ld.main_object.entry) nose.tools.assert_equal( [x for x in path_ld.shared_objects.keys() if x != 'fauxware'], list(stream_ld.shared_objects.keys())) nose.tools.assert_equal( path_ld.memory.unpack_word(path_ld.main_object.entry), stream_ld.memory.unpack_word(stream_ld.main_object.entry)) strcmp_string = path_ld.describe_addr( path_ld.memory.unpack_word(0x804a000)) nose.tools.assert_in('libc.so.6', strcmp_string) nose.tools.assert_in('strcmp', strcmp_string) nose.tools.assert_equal( strcmp_string, stream_ld.describe_addr(stream_ld.memory.unpack_word(0x804a000)))
def test_stream(): dirpath = os.path.join(test_location, "i386") filepath = os.path.join(dirpath, "fauxware") lib1path = os.path.join(dirpath, "libc.so.6") lib2path = os.path.join(dirpath, "ld-linux.so.2") path_ld = cle.Loader(filepath) lib1 = cle.Loader.load_object(open(lib1path, 'rb')) lib2 = cle.Loader.load_object(open(lib2path, 'rb')) stream_ld = cle.Loader(open(filepath, 'rb'), auto_load_libs=False, force_load_libs=(lib1, lib2)) nose.tools.assert_equal(path_ld.main_bin.entry, stream_ld.main_bin.entry) nose.tools.assert_equal(path_ld.shared_objects.keys(), stream_ld.shared_objects.keys()) nose.tools.assert_equal( path_ld.memory.read_addr_at(path_ld.main_bin.entry), stream_ld.memory.read_addr_at(stream_ld.main_bin.entry)) strcmp_string = path_ld.whats_at(path_ld.memory.read_addr_at(0x804a000)) nose.tools.assert_in('libc.so.6', strcmp_string) nose.tools.assert_in('strcmp', strcmp_string) nose.tools.assert_equal( strcmp_string, stream_ld.whats_at(stream_ld.memory.read_addr_at(0x804a000)))
def fire(self, return_loader=False, **kwargs): #pylint:disable=arguments-differ if self.project is None: the_binary = self.target.resolve_local_path(self.target.target_path) # preload the binary to decide if it supports setting library options or base addresses preloader = cle.Loader(the_binary, **kwargs) if preloader.main_object.os == "cgc": # CGC binaries do not have libraries to load the_libs = { } lib_opts = { } # CGC binaries cannot be rebased bin_opts = { } self._mem_mapping = { } else: _,_,_,self._mem_mapping = self.scout_bow.fire() the_libs = [ self.target.resolve_local_path(lib) for lib in self._mem_mapping if lib.startswith("/") ] lib_opts = { os.path.basename(lib) : {'base_addr' : libaddr} for lib, libaddr in self._mem_mapping.items() } bin_opts = { "base_addr": 0x555555554000 } if return_loader: return cle.Loader(the_binary, preload_libs=the_libs, lib_opts=lib_opts, main_opts=bin_opts, **kwargs) self.project = angr.Project(the_binary, preload_libs=the_libs, lib_opts=lib_opts, main_opts=bin_opts, **kwargs) if self.static_simproc: self._apply_simprocedures() if return_loader: return self.project.loader return self.project
def _run(self, inst): self._progress_callback(5) partial_ld = None try: # Try automatic loading partial_ld = cle.Loader(self.fname, perform_relocations=False, load_debug_info=False) except archinfo.arch.ArchNotFound as e: partial_ld = cle.Loader(self.fname, perform_relocations=False, load_debug_info=False, arch='x86') gui_thread_schedule(LoadBinary.binary_arch_detect_failed, (self.fname, str(e))) except cle.CLECompatibilityError: # Continue loading as blob pass if partial_ld is None: try: # Try loading as blob; dummy architecture (x86) required, user will select proper arch partial_ld = cle.Loader(self.fname, main_opts={ 'backend': 'blob', 'arch': 'x86' }) except cle.CLECompatibilityError: # Failed to load executable, even as blob! gui_thread_schedule(LoadBinary.binary_loading_failed, (self.fname, )) return self._progress_callback(50) new_load_options, cfg_args, variable_recovery_args = gui_thread_schedule( LoadBinary.run, (partial_ld, )) if cfg_args is None: return engine = None if hasattr(new_load_options['arch'], 'pcode_arch'): engine = angr.engines.UberEnginePcode self.load_options.update(new_load_options) proj = angr.Project(self.fname, load_options=self.load_options, engine=engine) self._progress_callback(95) def callback(): inst._reset_containers() inst.project.am_obj = proj inst.project.am_event( cfg_args=cfg_args, variable_recovery_args=variable_recovery_args) gui_thread_schedule(callback, ())
def fire(self, return_loader=False, **kwargs): #pylint:disable=arguments-differ if self.project is None: the_binary = self.target.resolve_local_path( self.target.target_path) # preload the binary to decide if it supports setting library options or base addresses cle_args = dict(kwargs) cle_args.update(cle_args.pop('load_options', {})) cle_args.pop('use_sim_procedures', None) # TODO do something less hacky than this preload_kwargs = dict(cle_args) preload_kwargs['auto_load_libs'] = False preloader = cle.Loader(the_binary, **preload_kwargs) if self.scout_bow is not None: _, _, _, self._mem_mapping = self.scout_bow.fire() the_libs = [ self.target.resolve_local_path(lib) for lib in self._mem_mapping if lib.startswith("/") ] lib_opts = { os.path.basename(lib): { 'base_addr': libaddr } for lib, libaddr in self._mem_mapping.items() } bin_opts = { "base_addr": 0x555555554000 } if preloader.main_object.pic else {} else: the_libs = {} lib_opts = {} bin_opts = {} self._mem_mapping = {} if return_loader: return cle.Loader(the_binary, preload_libs=the_libs, lib_opts=lib_opts, main_opts=bin_opts, **cle_args) self.project = angr.Project(the_binary, preload_libs=the_libs, lib_opts=lib_opts, main_opts=bin_opts, **kwargs) if self.static_simproc: self._apply_simprocedures() if return_loader: return self.project.loader return self.project
def main(): r = socket.socket() r.connect(("172.17.0.1", 2323)) recvline(r) recvline(r) recvline(r) recvline(r) for i in range(50): print("Iteration %d" % i) bine = recvline(r) obj = cle.Loader(StringIO.StringIO(bine.decode("base64"))) proj = angr.Project(obj) cfg = proj.analyses.CFG() for j in proj.kb.functions: if proj.kb.functions[j].name == "success": success = proj.kb.functions[j].addr if proj.kb.functions[j].name == "failure": failure = proj.kb.functions[j].addr pg = proj.factory.path_group().explore(find=success, avoid=failure) if pg.found: solution = pg.found[0].state.posix.dumps(0) print("Found input to %d: %s" % (i, solution)) r.sendall(solution) else: print("Failure to find a solution on iteration %d" % i) exit() flag = recvline(r) print flag
def test_minidump(): exe = os.path.join(TEST_BASE, 'tests', 'x86', 'windows', 'jusched_x86.dmp') ld = cle.Loader(exe, auto_load_libs=False) nose.tools.assert_is_instance(ld.main_object, cle.Minidump) nose.tools.assert_is_instance(ld.main_object.arch, archinfo.ArchX86) nose.tools.assert_equal(ld.main_object.os, 'windows') nose.tools.assert_equal(len(ld.main_object.segments), 30) sections_map = ld.main_object.sections_map nose.tools.assert_in('jusched.exe', sections_map) nose.tools.assert_in('kernel32.dll', sections_map) nose.tools.assert_equal(len(ld.main_object.threads), 2) registers = ld.main_object.thread_registers(0x0548) nose.tools.assert_is_instance(registers, dict) nose.tools.assert_equal( registers, { 'gs': 43, 'fs': 83, 'edi': 2001343136, 'esi': 2001343136, 'ebx': 0, 'edx': 2001343136, 'ecx': 2001343136, 'eax': 2121117696, 'ebp': 33357196, 'eip': 2000776736, 'eflags': 580, 'esp': 33357152 })
def test_gxx_exception_0(): # Test if we can load exception handlings generated by g++ 7.4.0 binary = os.path.join(TEST_BASE, "x86_64", "exceptions_0") ld = cle.Loader(binary, load_debug_info=True, auto_load_libs=False) nose.tools.assert_equal(len(ld.main_object.exception_handlings), 4) exception_handlings = dict( (exc.start_addr, exc) for exc in ld.main_object.exception_handlings) nose.tools.assert_equal(len(exception_handlings), 4) # 0x400a61 nose.tools.assert_equal(exception_handlings[0x400a61].start_addr, 0x400a61) nose.tools.assert_equal(exception_handlings[0x400a61].size, 0x1a) nose.tools.assert_equal(exception_handlings[0x400a61].func_addr, 0x400a4a) nose.tools.assert_equal(exception_handlings[0x400a61].handler_addr, 0x400a82) # 0x400a98 nose.tools.assert_equal(exception_handlings[0x400a98].start_addr, 0x400a98) nose.tools.assert_equal(exception_handlings[0x400a98].size, 0x1a) nose.tools.assert_equal(exception_handlings[0x400a98].func_addr, 0x400a4a) nose.tools.assert_equal(exception_handlings[0x400a98].handler_addr, 0x400ab9) # 0x400ab2 nose.tools.assert_equal(exception_handlings[0x400ab2].start_addr, 0x400ab2) nose.tools.assert_equal(exception_handlings[0x400ab2].size, 0x5) nose.tools.assert_equal(exception_handlings[0x400ab2].func_addr, 0x400a4a) nose.tools.assert_equal(exception_handlings[0x400ab2].handler_addr, None) # 0x400ac7 nose.tools.assert_equal(exception_handlings[0x400ac7].start_addr, 0x400ac7) nose.tools.assert_equal(exception_handlings[0x400ac7].size, 0x5) nose.tools.assert_equal(exception_handlings[0x400ac7].func_addr, 0x400a4a) nose.tools.assert_equal(exception_handlings[0x400ac7].handler_addr, None)
def test_mipsel(): ping = os.path.join(test_location, 'mipsel', 'darpa_ping') skip = ['libgcc_s.so.1', 'libresolv.so.0'] ld = cle.Loader(ping, skip_libs=skip) dep = set(ld._satisfied_deps) loadedlibs = set(ld.shared_objects) # 1) check dependencies and loaded binaries nose.tools.assert_true( dep.issuperset( {'libresolv.so.0', 'libgcc_s.so.1', 'libc.so.6', 'ld.so.1'})) nose.tools.assert_true(loadedlibs.issuperset({'libc.so.6', 'ld.so.1'})) # 2) Check GOT slot containts the right address # Cle: 4494036 # got = ld.find_symbol_got_entry('__uClibc_main') # addr = ld.memory.read_addr_at(got) # nose.tools.assert_equal(addr, sproc_addr) # TODO: Get the right version of uClibc and devise a test that doesn't use angr ioctl = ld.find_relevant_relocations("ioctl").next() setsockopt = ld.find_relevant_relocations("setsockopt").next() nose.tools.assert_equal(ioctl.rebased_addr, 4494300) nose.tools.assert_equal(setsockopt.rebased_addr, 4494112)
def test_fauxware(): machofile = os.path.join(TEST_BASE, 'tests', 'x86_64', 'fauxware.macho') ld = cle.Loader(machofile, auto_load_libs=False) nose.tools.assert_true(isinstance(ld.main_object,cle.MachO)) nose.tools.assert_equal(ld.main_object.os, 'macos') nose.tools.assert_equal(ld.main_object.entry, 0x100000de0) nose.tools.assert_equal(sorted(list(ld.main_object.exports_by_name))[-1], '_sneaky')
def test_ppc(): libc = os.path.join(test_location, 'ppc', 'libc.so.6') ld = cle.Loader(libc, auto_load_libs=True, main_opts={'custom_base_addr': 0}) # This tests the relocation of _rtld_global_ro in ppc libc6. # This relocation is of type 20, and relocates a non-local symbol relocated = ld.memory.read_addr_at(0x18ace4) nose.tools.assert_equal(relocated % 0x1000, 0xf666e320 % 0x1000)
def hook_entry(binary, asm_code=None, bin_code=None): main_bin = io.BytesIO(binary) b = cle.Loader(main_bin, auto_load_libs=False, perform_relocations=False, main_opts={'base_addr': 0}) start_addr = b.main_object.addr_to_offset(b.main_object.entry) arch = b.main_object.arch if arch.name in ('ARMHF', 'ARMEL') and arch.is_thumb( start_addr): # OMG, thumb mode is a disaster start_addr &= (~1) # recover the real address main_bin.seek(start_addr) padding = (4 - (start_addr + 8) % 4) % 4 # we hardcode the shellcode so that its length is 8 # we can' use arch.asm here because the shellcode THUMB, 8+padding-4 because the shellcode has length 8+padding, # we also need to take into account that in arm, pc points to two instructions ahead, which is 4 bytes in thumb mode main_bin.write(b'xF\x00\xf1' + struct.pack('<H', 8 + padding - 4) + b'\x00G' + b'A' * padding) # now place our payload after this mini shellcode start_addr += 8 + padding main_bin.seek(start_addr) main_bin.write(b.main_object.arch.asm(asm_code) if asm_code else bin_code) main_bin.seek(0) return main_bin.read()
def load(session): all_objects = {} # path to object main_object = None db_objects = session.query(DbObject) # type: List[DbObject] for db_o in db_objects: all_objects[db_o.path] = db_o if db_o.main_object: main_object = db_o if main_object is None: raise AngrCorruptDBError("Corrupt database: No main object.") # build params # FIXME: Load other objects loader = cle.Loader(BytesIO(main_object.content), ) # fix the binary name of the main binary loader._main_binary_path = main_object.path loader.main_object.binary = main_object.path return loader
def test_blob_0(): BASE_ADDR = 0x8000000 ENTRYPOINT = 0x8001337 blob_file = os.path.join(TEST_BASE, 'tests', 'i386', 'all') blob_file_size = os.stat(blob_file).st_size ld = cle.Loader(blob_file, main_opts={ 'backend': 'blob', 'base_addr': BASE_ADDR, 'entry_point': ENTRYPOINT, 'arch': "ARM", }) nose.tools.assert_equal(ld.main_object.linked_base, BASE_ADDR) nose.tools.assert_equal(ld.main_object.mapped_base, BASE_ADDR) nose.tools.assert_equal(ld.main_object.min_addr, BASE_ADDR) nose.tools.assert_equal(ld.main_object.max_addr, BASE_ADDR + blob_file_size - 1) nose.tools.assert_equal(ld.main_object.entry, ENTRYPOINT) nose.tools.assert_true(ld.main_object.contains_addr(BASE_ADDR)) nose.tools.assert_false(ld.main_object.contains_addr(BASE_ADDR - 1)) # ensure that pickling works ld_pickled = pickle.loads(pickle.dumps(ld)) nose.tools.assert_equal(ld_pickled.main_object.mapped_base, BASE_ADDR)
def test_local_symbol_reloc(): filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../binaries/tests/armel/btrfs.ko') ld = cle.Loader(filename) # readelf -r btrfs.ko # Relocation section '.rel.init.text' at offset 0xfe318 contains 94 entries # Offset Info Type Sym.Value Sym. Name # 000000b4 00003c2b R_ARM_MOVW_ABS_NC 00000000 .LANCHOR0 # 000000b8 00003c2c R_ARM_MOVT_ABS 00000000 .LANCHOR0 # there are multiple symbols with name .LANCHOR0, those relocations shall # point to the first byte of .data section init_text_vaddr = ld.main_object.sections_map['.init.text'].vaddr data_vaddr = ld.main_object.sections_map['.data'].vaddr reloc_abs_nc = None reloc_abs = None for r in ld.main_object.relocs: if r.rebased_addr == init_text_vaddr + 0xb4: reloc_abs_nc = r if r.rebased_addr == init_text_vaddr + 0xb8: reloc_abs = r nose.tools.assert_is_not_none(reloc_abs_nc) nose.tools.assert_equals(data_vaddr, reloc_abs_nc.resolvedby.rebased_addr) nose.tools.assert_is_not_none(reloc_abs) nose.tools.assert_equals(data_vaddr, reloc_abs.resolvedby.rebased_addr)
def check_plt_entries(filename): real_filename = os.path.join(TESTS_BASE, 'tests', filename) ld = cle.Loader(real_filename, auto_load_libs=False, main_opts={'base_addr': 0}) if filename == os.path.join('ppc', 'libc.so.6'): # objdump can't find PLT stubs for this... nose.tools.assert_not_equal(ld.main_object._plt, {}) sorted_keys = sorted(ld.main_object._plt.values()) diffs = [y - x for x, y in zip(sorted_keys, sorted_keys[1:])] nose.tools.assert_equal(diffs, [4]*len(diffs)) return # all our mips samples have no PLT, just resolver stubs if filename.startswith('mips'): nose.tools.assert_equal(ld.main_object.plt, {}) return if filename == os.path.join('armel', 'helloworld'): nose.tools.assert_equal(ld.main_object.plt, {'printf': 0x102e0, '__libc_start_main': 0x102ec, '__gmon_start__': 0x102f8, 'abort': 0x10304 } ) return if filename == os.path.join('x86_64', 'true'): nose.tools.assert_equal(ld.main_object.plt, {u'__uflow': 0x1440, u'getenv': 0x1448, u'free': 0x1450, u'abort': 0x1458, u'__errno_location': 0x1460, u'strncmp': 0x1468, u'_exit': 0x1470, u'__fpending': 0x1478, u'textdomain': 0x1480, u'fclose': 0x1488, u'bindtextdomain': 0x1490, u'dcgettext': 0x1498, u'__ctype_get_mb_cur_max': 0x14a0, u'strlen': 0x14a8, u'__stack_chk_fail': 0x14b0, u'mbrtowc': 0x14b8, u'strrchr': 0x14c0, u'lseek': 0x14c8, u'memset': 0x14d0, u'fscanf': 0x14d8, u'close': 0x14e0, u'memcmp': 0x14e8, u'fputs_unlocked': 0x14f0, u'calloc': 0x14f8, u'strcmp': 0x1500, u'memcpy': 0x1508, u'fileno': 0x1510, u'malloc': 0x1518, u'fflush': 0x1520, u'nl_langinfo': 0x1528, u'ungetc': 0x1530, u'__freading': 0x1538, u'realloc': 0x1540, u'fdopen': 0x1548, u'setlocale': 0x1550, u'__printf_chk': 0x1558, u'error': 0x1560, u'open': 0x1568, u'fseeko': 0x1570, u'__cxa_atexit': 0x1578, u'exit': 0x1580, u'fwrite': 0x1588, u'__fprintf_chk': 0x1590, u'mbsinit': 0x1598, u'iswprint': 0x15a0, u'__cxa_finalize': 0x15a8, u'__ctype_b_loc': 0x15b0}) return ld.main_object._plt.pop('__gmon_start__', None) replaced_filename = filename.replace('\\', '/') if replaced_filename not in PLT_CACHE: p1 = subprocess.Popen(['objdump', '-d', real_filename], stdout=subprocess.PIPE) p2 = subprocess.Popen(['grep', '@plt>:'], stdin=p1.stdout, stdout=subprocess.PIPE) p1.stdout.close() dat, _ = p2.communicate() lines = dat.decode().strip().split('\n') ideal_plt = {} for line in lines: addr, ident = line.split() addr = int(addr, 16) name = ident.split('@')[0].strip('<') if '*' in name or name == '__gmon_start__': continue ideal_plt[name] = addr if filename == os.path.join('armhf', 'libc.so.6'): # objdump does these cases wrong as far as I can tell? # or maybe not wrong just... different # there's a prefix to this stub that jumps out of thumb mode # cle finds the arm stub, objdump finds the thumb prefix ideal_plt['free'] += 4 ideal_plt['malloc'] += 4 print("Regenerated ideal PLT for %s as %s", filename, ideal_plt) PLT_CACHE[filename.replace('\\', '/')] = ideal_plt ideal_plt = PLT_CACHE[replaced_filename] nose.tools.assert_equal(ideal_plt, ld.main_object.plt)
def run_sections(arch, filename, sections): binary_path = os.path.join(TESTS_BASE, arch, filename) ld = cle.Loader(binary_path, auto_load_libs=False) nose.tools.assert_equal(len(ld.main_object.sections), len(sections)) for i, section in enumerate(ld.main_object.sections): nose.tools.assert_equal(section.name, sections[i].name) nose.tools.assert_equal(section.offset, sections[i].offset) nose.tools.assert_equal( AT.from_mva(section.vaddr, ld.main_object).to_lva(), sections[i].vaddr) nose.tools.assert_equal(section.memsize, sections[i].memsize) # address lookups nose.tools.assert_is_none( ld.main_object.sections.find_region_containing(-1)) # skip all sections that are not mapped into memory mapped_sections = [section for section in sections if section.vaddr != 0] for section in mapped_sections: nose.tools.assert_equal( ld.main_object.find_section_containing(section.vaddr).name, section.name) nose.tools.assert_equal( ld.main_object.sections.find_region_containing(section.vaddr).name, section.name) if section.memsize > 0: nose.tools.assert_equal( ld.main_object.find_section_containing(section.vaddr + 1).name, section.name) nose.tools.assert_equal( ld.main_object.sections.find_region_containing(section.vaddr + 1).name, section.name) nose.tools.assert_equal( ld.main_object.find_section_containing(section.vaddr + section.memsize - 1).name, section.name) nose.tools.assert_equal( ld.main_object.sections.find_region_containing( section.vaddr + section.memsize - 1).name, section.name) for i in range(len(mapped_sections) - 1): sec_a, sec_b = mapped_sections[i], mapped_sections[i + 1] if sec_a.vaddr + sec_a.memsize < sec_b.vaddr: # there is a gap between sec_a and sec_b for j in range(min(sec_b.vaddr - (sec_a.vaddr + sec_a.memsize), 20)): a = sec_a.vaddr + sec_a.memsize + j nose.tools.assert_is_none( ld.main_object.find_section_containing(a)) nose.tools.assert_is_none( ld.main_object.sections.find_region_containing(a)) nose.tools.assert_is_none( ld.main_object.find_section_containing(0xffffffff), None)
def test_empty_segements(): """ Test for bizarre ELves #1: Energy Micro's compiler makes empty segments :return: """ path = os.path.join(test_location, "armel", "efm32gg.elf") cle.Loader(path, rebase_granularity=0x1000)
def test_relocated(): filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../binaries/tests/i386/fauxware') shared = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../binaries/tests/i386/prelinked') ld = cle.Loader(filename, ld_path=[shared], rebase_granularity=0x1000000) nose.tools.assert_equal(ld.main_object.mapped_base, 0x8048000) nose.tools.assert_sequence_equal( [x.mapped_base for x in ld.all_elf_objects], [0x8048000, 0x9000000, 0xA000000] )
def binary_loaded_info(app_bin): # First, get binary type: executable or shared object(PIE) bin_type = "executable" app_bin = os.path.realpath(app_bin) file_info = os.popen("file " + app_bin) if "shared object" in file_info.read(): bin_type = "shared_object" print "binary type is ", bin_type # Now load binary, calculate program loaded base, entry, text_min and text_max ld = cle.Loader(app_bin) bin_code = "" base_addr = ld.main_object.sections[0].vaddr entry = ld.main_object.entry print "Program base by cle: ", hex(base_addr) print "Program entry by cle: ", hex(entry) for i in ld.main_object.sections: if i.name == ".text": text_min = i.vaddr text_max = i.vaddr + i.filesize raw_bytes = ld.memory.read_bytes(i.vaddr, i.filesize) for byte in raw_bytes: bin_code += byte break #Third, write raw binary code to file raw_bin = "." + os.path.basename(app_bin) + ".text" f = open(raw_bin, "wb") if not f: print "open file " + raw_bin + " for writing failed." sys.exit(-1) f.write(bin_code) f.close() # Now we have to recalcuate the loaded addresses for Position-independent executables if bin_type == "shared_object": text_min -= base_addr text_max -= base_addr entry -= base_addr base_addr = 0x0 base_addr = 0x555555554000 text_min += base_addr text_max += base_addr entry += base_addr bin_loaded_info = { 'base': base_addr, 'entry': entry, 'text_min': text_min, 'text_max': text_max, 'raw_bin': raw_bin } return bin_loaded_info
def test_hex(): machofile = os.path.join(TEST_BASE, 'tests', 'armel', 'i2c_master_read-arduino_mzero.hex') ld = cle.Loader(machofile, auto_load_libs=False, main_opts={'custom_arch': "ARMEL"}) nose.tools.assert_true(isinstance(ld.main_object, cle.Hex)) nose.tools.assert_equals(ld.main_object.os, 'unknown') nose.tools.assert_equals(ld.main_object.entry, 0x44cd)
def test_lifting(pth, startOverride = False, numBytes = 0x1000): ld = cle.Loader(str(os.path.join(os.path.dirname(os.path.realpath(__file__)),pth))) start = startOverride if startOverride != False else ld.main_object.entry bytes = ld.memory.read_bytes(start, numBytes) bytes=''.join(bytes) l = helpers_sh4.LifterSH4(arch_sh4.ArchSH4(), start, bytes, revBytes=False) l.irsb.pp()
def test_first_fit(): filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../binaries/tests/x86_64/cfg_0') ld = cle.Loader(filename) nose.tools.assert_less(ld.main_object.mapped_base, ld.shared_objects['libc.so.6'].mapped_base) nose.tools.assert_less( ld.shared_objects['libc.so.6'].mapped_base, ld.shared_objects['ld-linux-x86-64.so.2'].mapped_base) #[<ELF Object cfg_0, maps [0x400000:0x601047]>, # <ELF Object libc.so.6, maps [0x1000000:0x13c42bf]>, # <ELF Object ld-linux-x86-64.so.2, maps [0x2000000:0x22241c7]>, # <ELFTLSObj Object ##cle_tls##, maps [0x3000000:0x3030000]>] ld = cle.Loader(filename, lib_opts={'libc.so.6': {'base_addr': 0x1234000}}) nose.tools.assert_less( ld.main_object.mapped_base, ld.shared_objects['ld-linux-x86-64.so.2'].mapped_base) nose.tools.assert_less( ld.shared_objects['ld-linux-x86-64.so.2'].mapped_base, ld.shared_objects['libc.so.6'].mapped_base) #[<ELF Object cfg_0, maps [0x400000:0x601047]>, # <ELF Object ld-linux-x86-64.so.2, maps [0x1000000:0x12241c7]>, # <ELF Object libc.so.6, maps [0x1234000:0x15f82bf]>, # <ELFTLSObj Object ##cle_tls##, maps [0x2000000:0x2030000]>] ld = cle.Loader(filename, lib_opts={ 'libc.so.6': { 'base_addr': 0x1234000 }, 'ld-linux-x86-64.so.2': { 'base_addr': 0 } }) nose.tools.assert_less( ld.shared_objects['ld-linux-x86-64.so.2'].mapped_base, ld.main_object.mapped_base) nose.tools.assert_less(ld.main_object.mapped_base, ld.shared_objects['libc.so.6'].mapped_base)
def test_progname(): filename = os.path.join(test_location, 'x86_64', 'cat') ld = cle.Loader(filename, auto_load_libs=False) progname_ptr_symbol = ld.find_symbol('__progname') progname_ptr = ld.memory.unpack_word(progname_ptr_symbol.rebased_addr) nose.tools.assert_not_equal(progname_ptr, 0) progname = ld.memory.load(progname_ptr, 8) nose.tools.assert_equal(progname, b'program\0')
def test_remote_file_mapper(): directory_for_binaries = get_binary_directory() remote_file_mapper = lambda x: x.replace("/tmp/foobar/does-not-exist", directory_for_binaries) ld = cle.Loader(get_coredump_file(), main_opts={ "backend": "elfcore", "remote_file_mapper": remote_file_mapper }) check_objects_loaded(ld)
def run(self, inst): self._progress_callback(5) partial_ld = None try: # Try automatic loading partial_ld = cle.Loader(self.fname, perform_relocations=False, load_debug_info=False) except cle.CLECompatibilityError: pass if partial_ld is None: try: # Try loading as blob; dummy architecture (x86) required, user will select proper arch partial_ld = cle.Loader(self.fname, main_opts={ 'backend': 'blob', 'arch': 'x86' }) except cle.CLECompatibilityError: # Failed to load executable, even as blob! gui_thread_schedule(LoadBinary.binary_loading_failed, (self.fname, )) return self._progress_callback(50) load_options, cfg_args = gui_thread_schedule(LoadBinary.run, (partial_ld, )) partial_ld.close() if cfg_args is None: return proj = angr.Project(self.fname, load_options=load_options) self._progress_callback(95) def callback(): inst._reset_containers() inst.project.am_obj = proj inst.project.am_event(cfg_args=cfg_args) gui_thread_schedule(callback, ())
def hook_addr(binary, addr, asm_code=None, bin_code=b''): main_bin = io.BytesIO(binary) loader = cle.Loader(main_bin, auto_load_libs=False, perform_relocations=False) offset = loader.main_object.addr_to_offset(addr) main_bin.seek(offset) main_bin.write( loader.main_object.arch.asm(asm_code) if asm_code else bin_code) main_bin.seek(0) return main_bin.read()
def hook_entry(binary, asm_code=None, bin_code=None): main_bin = io.BytesIO(binary) b = cle.Loader(main_bin, auto_load_libs=False, perform_relocations=False, main_opts={'base_addr': 0}) start_addr = b.main_object.addr_to_offset(b.main_object.entry) main_bin.seek(start_addr) main_bin.write(b.main_object.arch.asm(asm_code) if asm_code else bin_code) main_bin.seek(0) return main_bin.read()
def check_plt_entries(filename): real_filename = os.path.join(TESTS_BASE, 'tests', filename) ld = cle.Loader(real_filename, auto_load_libs=False) if filename == os.path.join('ppc', 'libc.so.6'): # objdump can't find PLT stubs for this... nose.tools.assert_not_equal(ld.main_bin._plt, {}) sorted_keys = sorted(ld.main_bin._plt.values()) diffs = [y - x for x, y in zip(sorted_keys, sorted_keys[1:])] nose.tools.assert_equal(diffs, [4]*len(diffs)) return if filename == os.path.join('mips', 'libc.so.6'): nose.tools.assert_in('__tls_get_addr', ld.main_bin._plt) nose.tools.assert_equal(ld.main_bin._plt['__tls_get_addr'], 1331168) return if filename == os.path.join('mips', 'fauxware'): nose.tools.assert_equal(ld.main_bin._plt, {'puts': 4197264, 'read': 4197232, '__libc_start_main': 4197312, 'printf': 4197248, 'exit': 4197280, 'open': 4197296, 'strcmp': 4197216}) return if filename == os.path.join('mips64', 'libc.so.6'): nose.tools.assert_equal(ld.main_bin._plt, {'__tls_get_addr': 1458432, '_dl_find_dso_for_object': 1458448}) return if filename == os.path.join('mips64', 'test_arrays'): nose.tools.assert_equal(ld.main_bin._plt, {'__libc_start_main': 4831841456, 'puts': 4831841440}) return p1 = subprocess.Popen(['objdump', '-d', real_filename], stdout=subprocess.PIPE) p2 = subprocess.Popen(['grep', '@plt>:'], stdin=p1.stdout, stdout=subprocess.PIPE) p1.stdout.close() dat, _ = p2.communicate() lines = dat.strip().split('\n') ideal_plt = {} for line in lines: addr, ident = line.split() addr = int(addr, 16) name = ident.split('@')[0].strip('<') if '*' in name or name == '__gmon_start__': continue ideal_plt[name] = addr ld.main_bin._plt.pop('__gmon_start__', None) if filename == os.path.join('armhf', 'libc.so.6'): # objdump does these cases wrong as far as I can tell? # or maybe not wrong just... different # there's a prefix to this stub that jumps out of thumb mode # cle finds the arm stub, objdump finds the thumb prefix ideal_plt['free'] += 4 ideal_plt['malloc'] += 4 nose.tools.assert_equal(ideal_plt, ld.main_bin._plt)
def run(self, inst): self._progress_callback(5) partial_ld = cle.Loader(self.fname, perform_relocations=False, load_debug_info=False) self._progress_callback(50) load_options, cfg_args = gui_thread_schedule(LoadBinary.run, (partial_ld, )) partial_ld.close() if cfg_args is None: return proj = angr.Project(self.fname, load_options=load_options) self._progress_callback(95) inst.set_project(proj, cfg_args)