def test_resume(self): m = Manticore(ms_file, stdin_size=17) # First instruction of `main` @m.hook(0x4009AE) def serialize(state): with m.locked_context() as context: if context.get("kill", False): raise TerminateState("Abandoning...") context["kill"] = True raise SerializeState("/tmp/ms_checkpoint.pkl") m.run() self.assertEqual(m.count_terminated_states(), 1) for state in m.terminated_states: self.assertEqual(state.cpu.PC, 0x4009AE) m = Manticore.from_saved_state("/tmp/ms_checkpoint.pkl") self.assertEqual(m.count_ready_states(), 1) for st in m.ready_states: self.assertEqual(state.cpu.PC, 0x4009AE) m.run() self.assertEqual(m.count_terminated_states(), 18) self.assertTrue( any("exit status: 0" in str(st._terminated_by) for st in m.terminated_states) ) m.finalize() for st in m.terminated_states: if "exit status: 0" in str(st._terminated_by): self.assertEqual(st.solve_one(st.input_symbols[0]), b"coldlikeminisodas")
def test_symbolic(self): # Create src and dst strings # This binary is compiled using gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 # with flags: -g -static -fno-builtin BIN_PATH = os.path.join(os.path.dirname(__file__), "binaries/str_model_tests", "sym_strncpy_test") tmp_dir = tempfile.TemporaryDirectory(prefix="mcore_test_sym_") m = Manticore(BIN_PATH, stdin_size=10, workspace_url=str(tmp_dir.name)) addr_of_strncpy = 0x0400490 @m.hook(addr_of_strncpy) def strncpy_model(state): state.invoke_model(strncpy) m.run() m.finalize() # Approximate regexes for expected testcase output # Example Match above each regex # Manticore varies the hex output slightly per run expected = [ # STDIN: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' r"STDIN: b\'\\x00(\\x([0-9a-f]{2})){9}\'", # STDIN: b'\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff' r"STDIN: b\'(\\x((?!(00))([0-9a-f]{2}))){1}\\x00(\\x([0-9a-f]{2})){8}\'", # STDIN: b'\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff' r"STDIN: b\'(\\x((?!(00))([0-9a-f]{2}))){2}\\x00(\\x([0-9a-f]{2})){7}\'", # STDIN: b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' r"STDIN: b\'(\\x((?!(00))([0-9a-f]{2}))){10}\'", ] inputs = f"{str(m.workspace)}/test_*.input" # Make a list of the generated input states stdins = [] for inpt in glob(inputs): with open(inpt) as f: stdins.append(f.read()) # Check the number of input states matches the number of regexes self.assertEqual(len(stdins), len(expected)) # Assert that every regex has a matching input for e in expected: match = False for s in stdins: if re.fullmatch(e, s) == None: match = True break self.assertTrue(match)
class UnicornResumeTest(unittest.TestCase): _multiprocess_can_split_ = True MAIN = 0x402180 PRE_LOOP = 0x4022EE POST_LOOP = 0x402346 DONE = 0x4024D3 FAIL = 0x40247C def hook_main(self, state: State): print("Reached main!!") def hook_pre_loop(self, state: State): print("Resuming emulation") state.cpu.emulate_until(self.POST_LOOP) def hook_ret_good(self, state: State): print("We made it!") def hook_ret_fail(self, state: State): self.assertTrue(False, "Target binary called `lose`!") def setUp(self): dirname = os.path.dirname(__file__) self.concrete_instance = Manticore(os.path.join(dirname, "binaries", "rusticorn")) self.concrete_instance.register_plugin(ResumeUnicornPlugin()) self.concrete_instance.add_hook(self.MAIN, callback=self.hook_main) self.concrete_instance.add_hook(self.PRE_LOOP, callback=self.hook_pre_loop) self.concrete_instance.add_hook(self.DONE, callback=self.hook_ret_good) self.concrete_instance.add_hook(self.FAIL, callback=self.hook_ret_fail) def test_integration_resume(self): f = io.StringIO() with contextlib.redirect_stdout(f): self.concrete_instance.run() self.concrete_instance.finalize() output = f.getvalue() print(output) self.assertIn("Reached main!!", output) self.assertIn("Resuming emulation", output) self.assertIn("We made it!", output) path = self.concrete_instance.workspace + "/test_00000000.stdout" with open(path) as stdoutf: stdout = stdoutf.read() self.assertIn( "If we were running under Python, that would have taken a really long time!", stdout ) self.assertIn("You win!", stdout) self.assertIn("8031989549026", stdout)
def profile(program, sort="cumulative"): print(f'[*] Profiling program "{program}"') m = Manticore(program) profiler = Profiler() m.register_plugin(profiler) m.run() m.finalize() stats = profiler.get_profiling_data() print(f"[*] Loaded profiling data.") if stats is None: print(f"[*] Failed to collect stats for program {program}") return stats.sort_stats(sort) stats.print_stats()
def test_symbolic_syscall_arg() -> None: BIN_PATH = os.path.join(os.path.dirname(__file__), "binaries", "symbolic_read_count") tmp_dir = tempfile.TemporaryDirectory(prefix="mcore_test_") m = Manticore(BIN_PATH, argv=["+"], workspace_url=str(tmp_dir.name)) m.run() m.finalize() found_win_msg = False win_msg = "WIN: Read more than zero data" outs_glob = f"{str(m.workspace)}/test_*.stdout" # Search all output messages for output_p in glob(outs_glob): with open(output_p) as f: if win_msg in f.read(): found_win_msg = True break assert found_win_msg, f'Did not find win message in {outs_glob}: "{win_msg}"'
def test_symbolic_length_recv() -> None: BIN_PATH = os.path.join(os.path.dirname(__file__), "binaries", "symbolic_length_recv") tmp_dir = tempfile.TemporaryDirectory(prefix="mcore_test_") m = Manticore(BIN_PATH, workspace_url=str(tmp_dir.name)) m.run() m.finalize() found_msg = False less_len_msg = "Received less than BUFFER_SIZE" outs_glob = f"{str(m.workspace)}/test_*.stdout" # Search all output messages for output_p in glob(outs_glob): with open(output_p) as f: if less_len_msg in f.read(): found_msg = True break assert found_msg, f'Did not find our message in {outs_glob}: "{less_len_msg}"'
def test_symbolic_fork(self): # This binary is compiled using gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 # with flags: -g -static -fno-builtin BIN_PATH = os.path.join(os.path.dirname(__file__), "binaries/str_model_tests", "sym_strlen_test") tmp_dir = tempfile.TemporaryDirectory(prefix="mcore_test_sym_") m = Manticore(BIN_PATH, stdin_size=10, workspace_url=str(tmp_dir.name)) addr_of_strlen = 0x04404D0 @m.hook(addr_of_strlen) def strlen_model(state): state.invoke_model(strlen_exact) m.run() m.finalize() # Expected stdout outputs expected = { "Length of string is: 0", "Length of string is: 1", "Length of string is: 2", "Length of string is: 3", "Length of string is: 4", "Length of string is: 5", } # Make a list of the generated output states outputs = f"{str(m.workspace)}/test_*.stdout" stdouts = set() for out in glob(outputs): with open(out) as f: stdouts.add(f.read()) # Assert that every expected stdout has a matching output self.assertEqual(expected, stdouts)
class ManticoreTest(unittest.TestCase): _multiprocess_can_split_ = True def setUp(self): dirname = os.path.dirname(__file__) self.m = Manticore( os.path.join(dirname, "binaries", "arguments_linux_amd64")) def test_profiling_data(self): p = Profiler() self.m.verbosity(0) self.m.register_plugin(p) self.m.run() profile_path = os.path.join(self.m.workspace, "profiling.bin") with open(profile_path, "wb") as f: p.save_profiling_data(f) self.assertTrue(os.path.exists(profile_path)) self.assertTrue(os.path.getsize(profile_path) > 0) def test_add_hook(self): def tmp(state): pass entry = 0x00400E40 self.m.add_hook(entry, tmp) self.assertTrue(tmp in self.m._hooks[entry]) def test_hook_dec(self): entry = 0x00400E40 @self.m.hook(entry) def tmp(state): pass self.assertTrue(tmp in self.m._hooks[entry]) def test_hook(self): self.m.context["x"] = 0 @self.m.hook(None) def tmp(state): with self.m.locked_context() as ctx: ctx["x"] = 1 self.m.kill() self.m.run() self.assertEqual(self.m.context["x"], 1) def test_init_hook(self): self.m.context["x"] = 0 @self.m.init def tmp(m, _ready_states): m.context["x"] = 1 m.kill() self.m.run() self.assertEqual(self.m.context["x"], 1) def test_hook_dec_err(self): with self.assertRaises(TypeError): @self.m.hook("0x00400e40") def tmp(state): pass def test_symbol_resolution(self): dirname = os.path.dirname(__file__) self.m = Manticore( os.path.join(dirname, "binaries", "basic_linux_amd64")) self.assertTrue(self.m.resolve("sbrk"), 0x449EE0) def test_symbol_resolution_fail(self): with self.assertRaises(ValueError): self.m.resolve("does_not_exist") def test_integration_basic_stdin(self): import struct dirname = os.path.dirname(__file__) self.m = Manticore( os.path.join(dirname, "binaries", "basic_linux_amd64")) self.m.run() self.m.finalize() workspace = self.m._output.store.uri with open(os.path.join(workspace, "test_00000000.stdin"), "rb") as f: a = struct.unpack("<I", f.read())[0] with open(os.path.join(workspace, "test_00000001.stdin"), "rb") as f: b = struct.unpack("<I", f.read())[0] if a > 0x41: self.assertTrue(a > 0x41) self.assertTrue(b <= 0x41) else: self.assertTrue(a <= 0x41) self.assertTrue(b > 0x41)
class ManticornTest(unittest.TestCase): _multiprocess_can_split_ = True def setUp(self): dirname = os.path.dirname(__file__) self.m = Manticore(os.path.join(dirname, 'binaries', 'arguments_linux_amd64'), argv=['argv', 'mc', 'argface']) self.concrete_instance = Manticore(os.path.join( dirname, 'binaries', 'arguments_linux_amd64'), argv=['argv', 'mc', 'argface']) self.concrete_instance.register_plugin(ConcretePlugin()) ''' self.concrete_instance.register_plugin(RegisterCapturePlugin()) self.m.register_plugin(RegisterCapturePlugin()) ''' @unittest.skip("Registers simply not matching for now") def test_register_comparison(self): self.m.run() self.concrete_instance.run() concrete_regs = {} normal_regs = {} for st in self.m.all_states: all_regs = st.platform.current.all_registers for reg in all_regs: normal_regs[reg] = getattr(st.platform.current, reg) for st in self.concrete_instance.all_states: all_regs = st.platform.current.canonical_registers for reg in all_regs: concrete_regs[reg] = getattr(st.platform.current, reg) for reg in concrete_regs: print(reg, concrete_regs[reg], normal_regs[reg]) for reg in concrete_regs: self.assertEqual(concrete_regs[reg], normal_regs[reg]) ''' concrete_regs = self.concrete_instance.context['regs'] normal_regs = self.m.context['regs'] for reg in concrete_regs.keys(): self.assertEqual(concrete_regs[reg],normal_regs[reg]) ''' def test_integration_basic_stdin(self): self.m.run() self.concrete_instance.run() self.m.finalize() self.concrete_instance.finalize() with open(os.path.join(self.m.workspace, 'test_00000000.stdout'), 'r') as f: left = f.read().strip() with open( os.path.join(self.concrete_instance.workspace, 'test_00000000.stdout'), 'r') as f: right = f.read().strip() self.assertEqual(left, right)
class ManticornTest(unittest.TestCase): _multiprocess_can_split_ = True def setUp(self): dirname = os.path.dirname(__file__) self.m = Manticore( os.path.join(dirname, "binaries", "arguments_linux_amd64"), argv=["argv", "mc", "argface"], ) self.concrete_instance = Manticore( os.path.join(dirname, "binaries", "arguments_linux_amd64"), argv=["argv", "mc", "argface"], ) self.concrete_instance.register_plugin(ConcretePlugin()) """ self.concrete_instance.register_plugin(RegisterCapturePlugin()) self.m.register_plugin(RegisterCapturePlugin()) """ def test_register_comparison(self): self.m.run() self.concrete_instance.run() should_match = { "RAX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R12", "R13", "R14", "R15", "RIP", "CS", "DS", "ES", "SS", "FS", "GS", "AF", "CF", "DF", "IF", "OF", "SF", "FP0", "FP1", "FP2", "FP3", "FP4", "FP5", "FP6", "FP7", "FPSW", "FPCW", } concrete_regs = {} normal_regs = {} self.assertEqual(len(list(self.m.terminated_states)), len(list(self.concrete_instance.terminated_states))) self.assertGreater(len(list(self.m.terminated_states)), 0) for st in self.m.terminated_states: for reg in should_match: normal_regs[reg] = getattr(st.platform.current, reg) for st in self.concrete_instance.terminated_states: for reg in should_match: concrete_regs[reg] = getattr(st.platform.current, reg) for reg in should_match: self.assertEqual( concrete_regs[reg], normal_regs[reg], f"Mismatch in {reg}: {concrete_regs[reg]} != {normal_regs[reg]}", ) def test_integration_basic_stdout(self): self.m.run() self.concrete_instance.run() self.m.finalize() self.concrete_instance.finalize() with open(os.path.join(self.m.workspace, "test_00000000.stdout"), "r") as f: left = f.read().strip() with open( os.path.join(self.concrete_instance.workspace, "test_00000000.stdout"), "r") as f: right = f.read().strip() self.assertEqual(left, right)
class ManticoreTest(unittest.TestCase): _multiprocess_can_split_ = True def setUp(self): dirname = os.path.dirname(__file__) self.m = Manticore( os.path.join(dirname, "binaries", "arguments_linux_amd64")) def test_profiling_data(self): p = Profiler() set_verbosity(0) self.m.register_plugin(p) self.m.run() self.m.finalize() profile_path = os.path.join(self.m.workspace, "profiling.bin") self.assertTrue(os.path.exists(profile_path)) self.assertTrue(os.path.getsize(profile_path) > 0) profile_path_2 = os.path.join(self.m.workspace, "profiling_2.bin") with open(profile_path_2, "wb") as f: p.save_profiling_data(f) self.assertTrue(os.path.exists(profile_path_2)) self.assertTrue(os.path.getsize(profile_path_2) > 0) self.assertTrue(filecmp.cmp(profile_path, profile_path_2)) def test_add_hook(self): def tmp(state): pass entry = 0x00400E40 self.m.add_hook(entry, tmp) self.assertTrue(tmp in self.m._hooks[entry]) def test_hook_dec(self): entry = 0x00400E40 @self.m.hook(entry) def tmp(state): pass self.assertTrue(tmp in self.m._hooks[entry]) def test_hook(self): self.m.context["x"] = 0 @self.m.hook(None) def tmp(state): with self.m.locked_context() as ctx: ctx["x"] = 1 self.m.kill() self.m.run() self.assertEqual(self.m.context["x"], 1) def test_add_hook_after(self): def tmp(state): pass entry = 0x00400E40 self.m.add_hook(entry, tmp, after=True) assert tmp in self.m._after_hooks[entry] def test_hook_after_dec(self): entry = 0x00400E40 @self.m.hook(entry, after=True) def tmp(state): # Make sure we've executed the instruction at entry and we're at # the next one (but before it executes). assert state.cpu.PC == 0x00400E42 self.m.kill() self.m.run() assert tmp in self.m._after_hooks[entry] def test_add_sys_hook(self): name = "sys_brk" index = 12 def tmp(state): assert state._platformn._syscall_abi.syscall_number() == index self.m.kill() self.m.add_hook(name, tmp, syscall=True) self.assertTrue(tmp in self.m._sys_hooks[index]) def test_sys_hook_dec(self): index = 12 @self.m.hook(index, syscall=True) def tmp(state): assert state._platformn._syscall_abi.syscall_number() == index self.m.kill() self.assertTrue(tmp in self.m._sys_hooks[index]) def test_sys_hook(self): self.m.context["x"] = 0 @self.m.hook(None, syscall=True) def tmp(state): with self.m.locked_context() as ctx: ctx["x"] = 1 self.m.kill() self.m.run() self.assertEqual(self.m.context["x"], 1) def test_add_sys_hook_after(self): def tmp(state): pass index = 12 self.m.add_hook(index, tmp, after=True, syscall=True) assert tmp in self.m._sys_after_hooks[index] def test_sys_hook_after_dec(self): name = "sys_mmap" index = 9 @self.m.hook(name, after=True, syscall=True) def tmp(state): pass self.m.run() assert tmp in self.m._sys_after_hooks[index] def test_init_hook(self): self.m.context["x"] = 0 @self.m.init def tmp(_state): self.m.context["x"] = 1 self.m.kill() self.m.run() self.assertEqual(self.m.context["x"], 1) def test_hook_dec_err(self): with self.assertRaises(TypeError): @self.m.hook("0x00400e40") def tmp(state): pass def test_symbol_resolution(self): dirname = os.path.dirname(__file__) self.m = Manticore( os.path.join(dirname, "binaries", "basic_linux_amd64")) self.assertTrue(self.m.resolve("sbrk"), 0x449EE0) def test_symbol_resolution_fail(self): with self.assertRaises(ValueError): self.m.resolve("does_not_exist") def test_integration_basic_stdin(self): import struct dirname = os.path.dirname(__file__) self.m = Manticore( os.path.join(dirname, "binaries", "basic_linux_amd64")) self.m.run() self.m.finalize() workspace = self.m._output.store.uri with open(os.path.join(workspace, "test_00000000.stdin"), "rb") as f: a = struct.unpack("<I", f.read())[0] with open(os.path.join(workspace, "test_00000001.stdin"), "rb") as f: b = struct.unpack("<I", f.read())[0] if a > 0x41: self.assertTrue(a > 0x41) self.assertTrue(b <= 0x41) else: self.assertTrue(a <= 0x41) self.assertTrue(b > 0x41)