class StateMergeTest(unittest.TestCase): # Need to add a plugin that counts the number of states in did_fork_state, and records the max # Then, when we hit class StateCounter(Plugin): def did_fork_state_callback(self, *_args, **_kwargs): self.max_states = max( self.max_states, self.manticore.count_busy_states() + self.manticore.count_ready_states() + self.manticore.count_killed_states() + self.manticore.count_terminated_states(), ) @property def max_states(self): with self.manticore.locked_context() as ctx: return ctx.setdefault("max_states", 0) @max_states.setter def max_states(self, new_val): with self.manticore.locked_context() as ctx: ctx["max_states"] = new_val def setUp(self): core = config.get_group("core") core.seed = 61 core.mprocessing = core.mprocessing.single dirname = os.path.dirname(__file__) self.m = Manticore( os.path.join(dirname, "binaries", "basic_state_merging"), policy="random" ) self.plugin = self.StateCounter() self.m.register_plugin(Merger()) self.m.register_plugin(self.plugin) def test_state_merging(self): @self.m.hook(0x40065D) def hook_post_merge(*_args, **_kwargs): with self.m.locked_context() as ctx: ctx["state_count"] = ( self.m.count_busy_states() + self.m.count_ready_states() + self.m.count_killed_states() + self.m.count_terminated_states() ) self.m.run() s = config.get_group("core").seed self.assertLess( self.m.context["state_count"], self.plugin.max_states, f"State merging failed with seed: {s}", )
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 executeDirected(program, pathsObject, args=[]): workplace_url = "/tmp/mcore_tmp" m = Manticore(program, argv=args, workspace_url=workplace_url, pure_symbolic=False) consts = config.get_group("core") consts.__setattr__("procs", 1) #Store variables in global context to ensure that we can communicate them to the callback function with m.locked_context() as context: context['paths'] = pathsObject context['targets'] = dict() #Register hook to have each executed instruction's RIP logged m.add_hook(None, log_rip) m.register_plugin(DirectedExtractorPlugin()) #Output the set of paths for i in pathsObject.paths: l = [hex(j) for j in i.path] logger.debug(",".join(l)) #Execute the directed symbolic execution m.run() #Obtain the dictionary of control flow edges from Manticore with m.locked_context() as context: targets = context['targets'] #Output results logger.debug("--Results Sorted by Pathlen--") sortedPaths = sorted(pathsObject.paths, key=lambda x: x.pathLen, reverse=False) for i in range(pathsObject.pathsLen): pathID = sortedPaths[i].pathID if pathID in targets.keys(): logger.debug("Path " + str(pathID) + "[len=" + str(sortedPaths[i].pathLen) + "] ending with " + hex( pathsObject.lastAddresses[pathID]) + " has the following successors " + ",".join([str(i) for i in targets[pathID]])) else: logger.debug("Path " + str(pathID) + "[len=" + str(sortedPaths[i].pathLen) + "]" + " is infeasible") return targets
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() for reg in self.concrete_instance.context: self.assertEqual(self.concrete_instance.context[reg], self.m.context[reg]) def test_integration_basic_stdin(self): self.m.run() self.concrete_instance.run() 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() 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)
import sys from manticore.native.plugins import Merger from manticore.utils import config from manticore.native import Manticore from manticore import set_verbosity """ Demonstrates the ability to do state merging on a simple program by merging states with id 2, 4 that happen to be at the same program location 0x40060d. This script uses the Merger plugin to apply opportunistic state merging. """ if __name__ == "__main__": config.get_group("core").seed = 2 config.get_group("core").mprocessing = config.get_group( "core").mprocessing.single path = sys.argv[1] m = Manticore(path, policy="random") def will_load_state_callback(_mc, state_id): print("about to load state_id = " + str(state_id)) def did_load_state_callback(_mc, state): print("loaded state_id = " + str(state.id) + " at cpu = " + hex(state.cpu.PC)) m.subscribe("will_load_state", will_load_state_callback) m.subscribe("did_load_state", did_load_state_callback) m.register_plugin(Merger()) m.run()
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)