class StateHooks(unittest.TestCase): 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_linux_amd64"), policy="random") def test_state_hooks(self): @self.m.hook(0x400610, after=True) def process_hook(state: State) -> None: # We can't remove because the globally applied hooks are stored in # the Manticore class, not State self.assertFalse(state.remove_hook(0x400610, process_hook, after=True)) # We can remove this one because it was applied specifically to this # State (or its parent) self.assertTrue(state.remove_hook(None, do_nothing, after=True)) state.add_hook(None, do_nothing, after=False) state.add_hook(None, do_nothing, after=True) state.add_hook(0x400647, fin, after=True) state.add_hook(0x400647, fin, after=False) for state in self.m.ready_states: self.m.add_hook(None, do_nothing, after=True, state=state) f = io.StringIO() with redirect_stdout(f): self.m.run() self.assertIn("Reached fin callback", f.getvalue())
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 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 symbolic_execution(self, targets): log.info("Starting symbolic execution...") linux = make_linux(self.path, auto_load=False) m = Manticore(linux) m.verbosity(0) # change to 2 for debugging buf_addr = targets["buf_addr"] # reached the goal (memcpy call) def reached_goal(state): con_buf = state.solve_buffer(buf_addr, 48) with m.locked_context() as context: context["magic_values"] = con_buf m.terminate() m.add_hook(targets["goal"], reached_goal) #skip intro shit def skip_intro(state): buf = state.new_symbolic_buffer(48) # buffer we will solve state.cpu.write_bytes(buf_addr, buf) state.cpu.RIP = targets["check_start"] m.add_hook(self.binary.symbols[b"__libc_start_main"], skip_intro) # never take jumps for failed solutions def constrain_jump(state): state.constrain(state.cpu.ZF == 1) for jne_addr in targets["jnes"]: m.add_hook(jne_addr, constrain_jump) m.run(procs=1) magic_values = m.context["magic_values"] return magic_values
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 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): self.m.run(should_profile=True) 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) 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): self.m.context['x'] = 1 self.m.terminate() 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(state): self.m.context['x'] = 1 self.m.terminate() 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_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() 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)
operators.AND(ord(" ") <= argv1[i], argv1[i] <= ord("}"))) # store argv1 in global state with m.locked_context() as context: context["argv1"] = argv1 # add fail_state callback to abandon # paths we don't care about def fail_state(state): print("Fail state! Abandoning.") state.abandon() for addr in [0x400C2F, 0x400BE7, 0x400BAC]: m.add_hook(addr, fail_state) @m.hook(0x400BA6) def skip_syscalls(state): """ skip error-checking syscalls """ state.cpu.EIP = 0x400BFA @m.hook(0x400C1C) def success_state(state): """ since input is symbolicated in argv, we search in state.input_symbols to find the label """ with m.locked_context() as context: context["solution"] = state.solve_one(context["argv1"], 20) m.kill()
""" """ def je_hook(state): # print("je HOOK: Here: {}".format(hex(state.cpu.EIP))) print('constra', state.constraints) res = state.solve_one(state.cpu.read_register('EDI')) # res = state.solve_one(state.cpu.EDI) print(chr(res), res) state.cpu.BL = res """ def exit_hook(state): # print("EXIT HOOK: Here: {}".format(hex(state.cpu.EIP))) state.abandon() for index, items in enumerate(addrs): entry, je_statement, exit_call = items # m.add_hook(je_statement, je_hook) m.add_hook(exit_call, exit_hook) """ def print_ip(state): if 0x400000 < state.cpu.RIP < 0x500000: print(hex(state.cpu.RIP)) """ m.verbosity = 0 m.workers = 1 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)
global buff_addr buff_addr = state.cpu.RDI buffer = state.new_symbolic_buffer(12) state.cpu.write_bytes(buff_addr, buffer) @m.hook(0x400981) def hook(state): """ Finish all the checks, solve for the solution """ res = ''.join(map(chr, state.solve_buffer(buff_addr, 12))) print(res) # =MANTICORE== state.abandon() # Be sure to abandon and not continue execution def exit_hook(state): """ Abandon hook for each exit call """ state.abandon() """ For each exit that we found in each of the checks, add the exit_hook to that call """ for index, exit in enumerate(get_exits()): m.add_hook(exit, exit_hook) m.verbosity = 0 m.workers = 1 m.should_profile = True m.run()
def test(): from manticore.native import Manticore from subprocess import check_output import sys """ Leverages Manticore to solve the manticore challenge: https://blog.trailofbits.com/2017/05/15/magic-with-manticore/ Author: @ctfhacker python win.py =MANTICORE== real 0m52.039s user 0m50.272s sys 0m2.340s """ file = "" if __name__ == "__main__": file = "manticore_challenge" else: file = "./test_manticore_challenge/manticore_challenge" addrs = [] def get_exits(): """ Extract exit calls from each check function using objdump """ def addr(line): """ Get just the address from a line of objdump output """ return int(line.split()[0][:-1], 16) exits_disasm = check_output("objdump -d %s | grep exit" % file, shell=True) exits_disasm = exits_disasm.decode() exits = [addr(line) for line in exits_disasm.split("\n")[2:-1]] for e in exits: yield e m = Manticore(file) m.context["solved"] = False buff_addr = None @m.hook(0x4009A4) def hook(state): """ Jump over `puts` and `fgets` calls """ state.cpu.EIP = 0x4009C1 @m.hook(0x4009C8) def hook(state): """ Inject symbolic buffer instead of fgets """ with m.locked_context() as context: context["buff_addr"] = state.cpu.RDI buffer = state.new_symbolic_buffer(12) state.cpu.write_bytes(state.cpu.RDI, buffer) @m.hook(0x400981) def hook(state): """ Finish all the checks, solve for the solution """ buff_addr = "" with m.locked_context() as context: buff_addr = context["buff_addr"] res = "".join(map(chr, state.solve_buffer(buff_addr, 12))) print("solution: " + res) # =MANTICORE== with m.locked_context() as context: if "=MANTICORE" in res: context["solved"] = True state.abandon() # Be sure to abandon and not continue execution def exit_hook(state): """ Abandon hook for each exit call """ state.abandon() """ For each exit that we found in each of the checks, add the exit_hook to that call """ for index, exit in enumerate(get_exits()): m.add_hook(exit, exit_hook) m.verbosity = 0 m.workers = 1 m.should_profile = True m.run() assert m.context["solved"]
def test(): #!/usr/bin/env python3.6 """ pwnable - collision challenge $ python win.py Solves collision challenge from pwnable.kr, using symbolic execution to determine edge cases that can trigger a hash collision. """ from manticore.native import Manticore from manticore.core.smtlib import operators # initialize Manticore object with symbolic input in # argv[1]. We can eventually solve for this through # state.input_symbol file = "" if __name__ == "__main__": file = "./col" else: file = "./test_pwnable_collision/col" m = Manticore(file, ["+" * 20]) m.context["solution"] = None m.context["argv1"] = None @m.init def init(initial_state): """ define constraints for symbolic ARGV before execution """ # determine argv[1] from state.input_symbols by label name argv1 = next(sym for sym in initial_state.input_symbols if sym.name == "ARGV1") if argv1 is None: raise Exception("ARGV was not made symbolic") # apply constraint for only ASCII characters for i in range(20): initial_state.constrain( operators.AND(ord(" ") <= argv1[i], argv1[i] <= ord("}"))) # store argv1 in global state with m.locked_context() as context: context["argv1"] = argv1 # add fail_state callback to abandon # paths we don't care about def fail_state(state): print("Fail state! Abandoning.") state.abandon() for addr in [0x400C2F, 0x400BE7, 0x400BAC]: m.add_hook(addr, fail_state) @m.hook(0x400BA6) def skip_syscalls(state): """ skip error-checking syscalls """ state.cpu.EIP = 0x400BFA @m.hook(0x400C1C) def success_state(state): """ since input is symbolicated in argv, we search in state.input_symbols to find the label """ with m.locked_context() as context: context["solution"] = state.solve_one(context["argv1"], 20) m.kill() # run Manticore, and print solution m.verbosity(2) m.run() print("EDGE CASE: ", m.context["solution"]) solved = False if "/bin/cat: flag: No such file or directory" in str( check_output([file, m.context["solution"]], stderr=subprocess.STDOUT)): solved = True # print("aaaaaa") # print(check_output([file, m.context["solution"]])) # print("bbbbb") # print(type(check_output([file, m.context["solution"]]))) assert solved