예제 #1
0
    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")
예제 #2
0
    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)
예제 #3
0
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)
예제 #4
0
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()
예제 #5
0
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}"'
예제 #6
0
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}"'
예제 #7
0
    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)
예제 #8
0
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)
예제 #9
0
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)
예제 #10
0
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)
예제 #11
0
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)