def _ltp_run(self, bin_path, timeout=3): z = Zelos(path.join(DATA_DIR, bin_path), log="ERROR") z.internal_engine.plugins.trace.set_verbose(False) z.internal_engine.plugins.trace.threads_to_print.add("none") stdout = z.internal_engine.handles.get(1) buffer = bytearray() def write_override(data): buffer.extend(data) stdout.write = write_override z.internal_engine.start(timeout=timeout) # All threads should exit successfully self.assertTrue( all([ t.state == ThreadState.SUCCESS for t in z.internal_engine.processes.get_all_threads() ]), msg=z.internal_engine.processes.__str__(), ) return buffer
def test_memory_search(self): z = Zelos(None) z.memory.map(0x1000, 0x1000) z.memory.write(0x1000, b"\x00\x01\x02\x03\x00\x01\x02\x00\x01\x01\x01") self.assertEqual([0x1000, 0x1004, 0x1007], z.memory.search(b"\x00\x01")) self.assertEqual([0x1008], z.memory.search(b"\x01\x01"))
def test_sandbox(self): folder = tempfile.TemporaryDirectory() z = Zelos(None, sandbox=folder.name) file_system = z.internal_engine.files self.assertFalse(path.exists(path.join(folder.name, "test_file1"))) _ = file_system.create_file("test_file1") self.assertTrue(path.exists(path.join(folder.name, "test_file1")))
def test_mount_file(self): real_path = path.join(DATA_DIR, "static_elf_helloworld") z = Zelos(None, mount=f"x86,/home/data/sample_file,{real_path}", log="debug") file = z.internal_engine.files.open_library("/home/data/sample_file") self.assertIsNotNone(file)
def test_many_prefixes(self): # These two instructions need to fail, since they are too long. w = Zelos(None) uc = w.internal_engine.emu uc.mem_map(0, 0x2000) uc.mem_write( 0x1000, b"\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\xA1\xF0\x10" b"\x00\x00", ) try: uc.emu_start(0x1000, 0x1010) self.assertEqual(1, 0) except Exception: pass # self.assertEqual(uc.getIP(), 0x1010) uc.mem_write( 0x1100, b"\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E\x3E" b"\x3E\x3E\xA1\xF0\x10\x00\x00", ) try: uc.emu_start(0x1100, 0x1114) self.assertEqual(1, 0) except Exception: pass
def test_what_executes_when_switching_eip(self): record = [] def hook(uc, address, size, userdata): record.append(address) if address == 0x1002: uc.reg_write(UC_X86_REG_EIP, 0x1006) w = Zelos(None) w.internal_engine.interrupt_handler.disable() uc = w.internal_engine.emu uc.mem_map(0, 0x2000) # Push 1, Push 2, push 3... that way you can tell what # instructions have actually executed # by investigating the stack uc.mem_write(0x1000, b"\x6A\x01\x6A\x02\x6A\x03\x6A\x04\x6A\x05") w.internal_engine.emu.setSP(0x100) uc.hook_add(UC_HOOK_CODE, hook) # FIXME: the interrupt hook is not being deleted prior to # emu_start in the disable() call above. It only deletes # after a run. Change in Unicorn impl.? For now we do a quick # fix by calling start one extra time. uc.emu_start(0x1000, 0x1008) uc.emu_start(0x1000, 0x1008) self.assertListEqual(record, [0x1000, 0x1002, 0x1006]) self.assertEqual(0xF8, w.internal_engine.emu.getSP()) self.assertEqual(4, w.internal_engine.emu.getstack(0)) self.assertEqual(1, w.internal_engine.emu.getstack(1)) self.assertEqual(0, w.internal_engine.emu.getstack(2))
def test_memory_failure(self): z = Zelos(None) mm = z.internal_engine.memory z.internal_engine.thread_manager.logger.warning("Testing logging") with self.assertRaises(OutOfMemoryException): mm.map(0x1000, 1024 * 1024 * 1024 * 10)
def test_save_after_edit(self): z = Zelos(path.join(DATA_DIR, "static_elf_helloworld")) tman = z.internal_engine.thread_manager tman.swap_with_next_thread() self.assertIsNotNone(tman.current_thread) self.assertEqual(1, tman.num_active_threads()) self.assertEqual(tman.current_thread.state, ThreadState.RUNNING) data = tman._save_state() tman.pause_current_thread() self.assertEqual(0, tman.num_active_threads()) tman._load_state(data) self.assertIsNotNone(tman.current_thread) self.assertEqual(1, tman.num_active_threads()) self.assertEqual(tman.current_thread.state, ThreadState.RUNNING) tman.pause_current_thread() self.assertEqual(0, tman.num_active_threads()) tman._load_state(data) self.assertIsNotNone(tman.current_thread) self.assertEqual(1, tman.num_active_threads()) self.assertEqual(tman.current_thread.state, ThreadState.RUNNING)
def test_offsets(self): z = Zelos(None, log="debug") file_system = z.internal_engine.files handle_num = file_system.create_file("test_file1") h = z.internal_engine.handles.get(handle_num) self.assertEqual(0, h._file.tell()) h.seek(100) self.assertEqual(100, h._file.tell())
def test_temp_hook_at(self): z = Zelos(path.join(DATA_DIR, "static_elf_arm_helloworld")) action = Mock() z.hook_execution( HookType.EXEC.INST, action, ip_low=0x2B3C4, ip_high=0x2B3C4, end_condition=lambda: True, ) z.internal_engine.plugins.runner.stop_at(0x2B3C8) z.internal_engine.start() action.assert_called_once() action.reset_mock() z.internal_engine.plugins.runner.run_to_addr(0x2B3C8) action.assert_not_called()
def test_alloc(self): z = Zelos(None) heap = z.internal_engine.memory.heap addr1 = heap.alloc(0x10, name="obj1") addr2 = heap.alloc(0x10, name="obj2") self.assertLessEqual(addr1 + 0x10, addr2) self.assertEqual(2, len(heap.heap_objects))
def test_static_elf_verbose(self): z = Zelos(path.join(DATA_DIR, "static_elf_arm_helloworld")) z.internal_engine.set_verbose(True) z.internal_engine.trace.threads_to_print.add("none") z.internal_engine.start(timeout=3) self.assertEqual( 1, len(z.internal_engine.thread_manager.completed_threads))
def test_run_to_next_write(self): z = Zelos(path.join(DATA_DIR, "static_elf_helloworld")) z.internal_engine.thread_manager.swap_with_thread("main") z.plugins.runner.next_write(0xFF08EDD0) t = z.thread self.assertEqual(t.getIP(), 0x8135778, f"IP is 0x{t.getIP():x} vs. 0x8135778")
def test_overlay_functions(self): z = Zelos( path.join(DATA_DIR, "static_elf_helloworld"), verbosity=1, fasttrace=True, ) z.start() output = StringIO() z.plugins.overlay.export(output, funcs=True) output.seek(0) data = output.read()[len("DISAS\n") :] memdump = json.loads(data) self.assertEqual(len(memdump["functions"]), 239)
def test_syscall_breakpoint(self): z = Zelos(path.join(DATA_DIR, "static_elf_helloworld")) z.set_syscall_breakpoint("brk") z.start() brk = 0x0815B575 self.assertEqual(z.thread.getIP(), brk) z.remove_syscall_breakpoint("brk") z.start() self.assertEqual( 1, len(z.internal_engine.thread_manager.completed_threads))
def test_syscall_override(self): z = Zelos(None) sm = X86SyscallManager(z.internal_engine) sm.register_overrides({"getuid": [1, 2]}) sys_func = sm._name2syscall_func["getuid"] p = Mock() self.assertEqual(1, sys_func(sm, p)) self.assertEqual(2, sys_func(sm, p)) sys_func(sm, p)
def test_binary_paths(self): z = Zelos(None) self.assertIsNone(z.main_binary) self.assertIsNone(z.main_binary_path) z = Zelos(path.join(DATA_DIR, "static_elf_helloworld")) self.assertIsNotNone(z.main_binary) self.assertEqual(path.basename(z.main_binary_path), "static_elf_helloworld") self.assertEqual(path.basename(z.target_binary_path), "static_elf_helloworld") z = Zelos(path.join(DATA_DIR, "dynamic_elf_helloworld")) self.assertIsNotNone(z.main_binary) self.assertNotEqual(path.basename(z.main_binary_path), "dynamic_elf_helloworld") self.assertEqual(path.basename(z.target_binary_path), "dynamic_elf_helloworld")
def test_socket_elf(self): z = Zelos(path.join(DATA_DIR, "static-socket-x86-musl")) z.internal_engine.trace.threads_to_print.add("none") z.internal_engine.set_hook_granularity(HookType.EXEC.BLOCK) z.internal_engine.network.disable_whitelist() z.internal_engine.start(timeout=5) self.assertEqual( 1, len(z.internal_engine.thread_manager.completed_threads))
def test_run_to_ret(self): z = Zelos(path.join(DATA_DIR, "static_elf_helloworld")) z.internal_engine.thread_manager.swap_with_thread("main") z.internal_engine.step() z.internal_engine.plugins.runner.next_ret() self.assertEqual( str(z.internal_engine.current_thread.getIP()), str(0x08048B80) )
def test_get_module_base(self): z = Zelos(None) m = z.internal_engine.memory m.map(0x40000, 0x1000, module_name="test") m.map(0x30000, 0x1000, module_name="test") m.map(0x20000, 0x1000, module_name="other") self.assertEqual(0x30000, m.get_module_base("test")) self.assertEqual(None, m.get_module_base("not_present"))
def test_static_elf_eb(self): if os.name == "nt": raise unittest.SkipTest( "Skipping `test_static_elf_eb`: Windows lief fails to parse") z = Zelos(path.join(DATA_DIR, "static_elf_mipseb_mti_helloworld")) z.internal_engine.start(timeout=10) self.assertEqual( 1, len(z.internal_engine.thread_manager.completed_threads))
def test_read_writeint(self): z = Zelos(None) m = z.internal_engine.memory address1 = m.map_anywhere(0x1000, name="name1", kind="size1") m.write_int(address1, 10) self.assertEqual(10, z.internal_engine.memory.read_int(address1)) self.assertEqual(10, m.read_int(address1))
def test_add_multiple_hooks(self): z = Zelos(path.join(DATA_DIR, "static_elf_arm_helloworld")) action1 = Mock(name="action1") z.hook_execution(HookType.EXEC.INST, action1, name="test_hook") action2 = Mock(name="action2") z.hook_execution(HookType.EXEC.INST, action2, name="test_hook") z.step() action1.assert_called() action2.assert_called()
def test_zml_hook(self): z = Zelos(path.join(DATA_DIR, "dynamic_elf_heap_overflow")) malloc_addrs = [] def malloc_hook1(): malloc_addrs.append((z.thread.getIP(), "hook1")) def malloc_hook2(): malloc_addrs.append((z.thread.getIP(), "hook2")) z.internal_engine.hook_manager.register_zml_hook( "func=malloc,n=1", malloc_hook1) z.internal_engine.hook_manager.register_zml_hook( "func=malloc,n=2", malloc_hook2) z.start() self.assertEqual(malloc_addrs, [(2728048, "hook1"), (2728048, "hook2")])
def test_reverse_taint(self): z = Zelos( path.join(DATA_DIR, "test_example_1"), taint=True, ) z.start() taint_graph = z.plugins.dataflow.reverse_taint(0x1606) expected_taint_path = { # 0x1606: [(0x1606, -1, -1)], 0x1602: [(0x1606, "rax", "0x0")], 0x15FE: [(0x1602, 0x7F000008EC50, "0x0")], 0x1627: [(0x15FE, "rdi", "0x0")], 0x1623: [(0x1627, "rax", "0x0")], 0x161F: [(0x1623, 0x7F000008EC78, "0x0")], 0x161B: [(0x161F, "rax", "0x0")], 0x1617: [(0x161B, 0x7F000008EC68, "0x0")], 0x1646: [(0x1617, "rdi", "0x0")], 0x1642: [(0x1646, "rax", "0x0")], 0x163A: [(0x1642, 0x7F000008EC98, "0x0")], } for idx, flow_targets in expected_taint_path.items(): taint_path = taint_graph._reduced_path flow_idx = flow_targets[0][0] flow_use = flow_targets[0][1] flow_val = flow_targets[0][2] self.assertIn(idx, taint_path, msg=f"{idx} {flow_targets}") self.assertIn(flow_idx, taint_path[idx], msg=f"{idx} {flow_targets}") taint_node = taint_path[idx][flow_idx] # self.assertEqual( # flow_idx, taint_node.idx, msg=f"{flow_idx} {taint_node}" # ) self.assertEqual(flow_use, taint_node.use, msg=f"{flow_use} {taint_node}") self.assertEqual(flow_val, taint_node.val, msg=f"{flow_val} {taint_node}")
def test_dynamic_elf(self): z = Zelos(path.join(DATA_DIR, "ld-linux.so"), "./dynamic_elf_helloworld") z.internal_engine.plugins.trace.threads_to_print.add("none") z.internal_engine.files.add_file( path.join(DATA_DIR, "dynamic_elf_helloworld")) z.internal_engine.start(timeout=3) self.assertEqual( 1, len(z.internal_engine.thread_manager.completed_threads))
def test_get_region(self): z = Zelos(None) self.assertEqual(len(z.memory.get_regions()), 2) z.memory.map(0x1000, 0x1000) reg = z.memory.get_region(0x1000) self.assertIsNotNone(reg) self.assertEqual(len(z.memory.get_regions()), 3) z.memory.map(0x2000, 0x1000) reg = z.memory.get_region(0x2000) self.assertIsNotNone(reg) self.assertEqual(len(z.memory.get_regions()), 4)
def test_offsets(self): z = Zelos(None) file_system = z.internal_engine.files handle_num = file_system.create_file("test_file1") h = z.internal_engine.handles.get(handle_num) self.assertEqual(0, h.Offset) h.Offset = 100 h = z.internal_engine.handles.get(handle_num) self.assertEqual(100, h.Offset)
def test_get_thread_by_name(self): z = Zelos(None) tman = z.internal_engine.thread_manager tman.new_thread(0x1000, 0x1234, name="thread_1", priority=1) tman.new_thread(0x2000, 0x1235, name="thread_2", priority=2) t = tman.get_thread_by_name("thread_1") self.assertIsNotNone(t) self.assertEqual(t.priority, 1) t = tman.get_thread_by_name("thread_3") self.assertIsNone(t)
def test_read_int(self): z = Zelos(None) m = z.internal_engine.memory m.map(0x88880000, 0x1000) m.write(0x88880000, b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a") self.assertEqual(m.read_int(0x88880000, 1), 0x01) self.assertEqual(m.read_int(0x88880000, 2), 0x0201) self.assertEqual(m.read_int(0x88880000, 4), 0x04030201) self.assertEqual(m.read_int(0x88880000, 8), 0x0807060504030201) self.assertRaises(Exception, m.read_int, 0x88880000, 3)