Ejemplo n.º 1
0
def test_cgc_se1_palindrome_raw():
    b = os.path.join(bin_location, "tests/cgc/sc1_0b32aa01_01")
    # test a valid palindrome
    r = tracer.QEMURunner(binary=b, input="racecar\n")
    p = angr.make_tracer_project(binary=b)
    s = p.factory.tracer_state(input_content="racecar\n",
                               magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()

    # make sure the heap base is correct and hasn't been altered from the default
    nose.tools.assert_true('traced' in simgr.stashes)
    nose.tools.assert_equal(simgr.traced[0].cgc.allocation_base, 0xb8000000)

    # make sure there is no crash state
    nose.tools.assert_true('crashed' not in simgr.stashes)

    # make sure angr modeled the correct output
    stdout_dump = simgr.traced[0].posix.dumps(1)
    nose.tools.assert_true(
        stdout_dump.startswith("\nWelcome to Palindrome Finder\n\n"
                               "\tPlease enter a possible palindrome: "
                               "\t\tYes, that's a palindrome!\n\n"
                               "\tPlease enter a possible palindrome: "))
    # make sure there were no 'Nope's from non-palindromes
    nose.tools.assert_false("Nope" in stdout_dump)

    # now test crashing input
    r = tracer.QEMURunner(binary=b, input="A" * 129)
    s = p.factory.tracer_state(input_content="A" * 129, magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()

    nose.tools.assert_true('crashed' in simgr.stashes)
Ejemplo n.º 2
0
def test_cache_stall():
    # test a valid palindrome
    b = os.path.join(bin_location, "tests/cgc/CROMU_00071")
    blob = "0c0c492a53acacacacacacacacacacacacac000100800a0b690e0aef6503697d660a0059e20afc0a0a332f7d66660a0059e20afc0a0a332f7fffffff16fb1616162516161616161616166a7dffffff7b0e0a0a6603697d660a0059e21c".decode(
        'hex')
    r = tracer.QEMURunner(binary=b, input=blob)
    p = angr.make_tracer_project(binary=b)
    s = p.factory.tracer_state(input_content=blob, magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    rex.trace_additions.ZenPlugin.prep_tracer(s)
    simgr.run()

    crash_path = t.predecessors[-1]
    crash_state = simgr.crashed[0]

    nose.tools.assert_not_equal(crash_path, None)
    nose.tools.assert_not_equal(crash_state, None)

    # load it again
    r = tracer.QEMURunner(binary=b, input=blob)
    s = p.factory.tracer_state(input_content=blob, magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    rex.trace_additions.ZenPlugin.prep_tracer(s)
    simgr.run()

    crash_path = t.predecessors[-1]
    crash_state = simgr.one_crashed

    nose.tools.assert_not_equal(crash_path, None)
    nose.tools.assert_not_equal(crash_state, None)
Ejemplo n.º 3
0
    def __init__(self, binary, crash=None):
        """
        :param binary: path to the binary which crashed
        :param crash: string of input which crashed the binary
        """

        self.binary = binary
        self.crash = crash

        # verify it actually crashes the binary
        r = tracer.QEMURunner(self.binary, input=self.crash, record_core=True)
        if not r.crash_mode:
            raise CrashFuzzerException("input did not crash the binary")

        self._p = angr.Project(self.binary)

        self.orig_regs = r.reg_vals

        self.pool = None
        self.byte_analysis = dict()
        self._bases = dict()
        self.skip_bytes = set()
        self.skip_sets = set()
        self.regs_to_numbers = dict()
        self.used_bytes = set()
        self.byte_translation_funcs = list()
        self.byte_translation_calls = dict()
        self._bit_patterns = dict()

        self.make_bases()
        self.run()
Ejemplo n.º 4
0
def do_trace(proj, test_name, input_data, **kwargs):
    """
    trace, magic, crash_mode, crash_addr = load_cached_trace(proj, "test_blurble")
    """
    fname = os.path.join(
        bin_location,
        "tests_data",
        "runner_traces",
        "%s_%s_%s.p" %
        (test_name, os.path.basename(proj.filename), proj.arch.name),
    )

    if os.path.isfile(fname):
        try:
            with open(fname, "rb") as f:
                r = pickle.load(f)
                if type(r) is tuple and len(r) == 2 and r[1] == TRACE_VERSION:
                    return r[0]
        except (pickle.UnpicklingError, UnicodeDecodeError):
            print("Can't unpickle trace - rerunning")

    if tracer is None:
        raise Exception(
            "Tracer is not installed and cached data is not present - cannot run test"
        )

    runner = tracer.QEMURunner(project=proj, input=input_data, **kwargs)
    r = (runner.trace, runner.magic, runner.crash_mode, runner.crash_addr)
    with open(fname, "wb") as f:
        pickle.dump((r, TRACE_VERSION), f, -1)
    return r
Ejemplo n.º 5
0
    def _concrete_leak_info(self, seed=None):

        if seed is None:
            seed = random.randint(0, 2**32)

        r1 = tracer.QEMURunner(self.binary, input=self.payload, record_magic=True, record_stdout=True, seed=seed)

        return (r1.stdout, r1.magic)
Ejemplo n.º 6
0
    def __init__(self, bin_input):
        """bin_input == concrete input to trace execution from."""
        self.input = bin_input

        self._tracer = tracer.QEMURunner(binary=GlobalConfig.target,
                                         input=self.input,
                                         argv=GlobalConfig.argv,
                                         record_stdout=True)
Ejemplo n.º 7
0
def _get_reg_vals(binary_input_byte):
    binary, test_input, c = binary_input_byte
    r = tracer.QEMURunner(binary, input=test_input, record_core=True)
    if not r.crash_mode:
        return [c, None]
    else:
        reg_vals = dict()
        for reg in CGC_GENERAL_REGS + ["eip"]:
            reg_vals[reg] = r.reg_vals[reg]
        return [c, r.reg_vals]
Ejemplo n.º 8
0
def test_symbolic_sized_receives():
    b = os.path.join(bin_location, "tests/cgc/CROMU_00070")
    r = tracer.QEMURunner(binary=b, input="hello")
    p = angr.make_tracer_project(binary=b)
    s = p.factory.tracer_state(input_content="hello", magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()

    # will except if failed
    nose.tools.assert_true('crashed' not in simgr.stashes)
    nose.tools.assert_true('traced' in simgr.stashes)

    r = tracer.QEMURunner(binary=b, input="\x00" * 20)
    s = p.factory.tracer_state(input_content="\x00" * 20)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()

    # will except if failed
    nose.tools.assert_true('crashed' not in simgr.stashes)
    nose.tools.assert_true('traced' in simgr.stashes)
Ejemplo n.º 9
0
    def __init__(self, binary, payload, format_infos=None):
        """
        :param binary: path to the binary which is suspect of leaking
        :param payload: concrete input string to feed to the binary
        :param format_infos: a list of atoi FormatInfo objects that should be used when analyzing the crash
        """

        self.binary = binary
        self.payload = payload

        if not os.access(self.binary, os.X_OK):
            raise ValueError("\"%s\" binary does not exist or is not executable" % self.binary)

        # will be set by causes_leak
        self._leak_path = None

        remove_options = {so.SUPPORT_FLOATING_POINT}
        self._runner = tracer.QEMURunner(binary=binary, input=payload)

        p = angr.Project(binary)
        p.simos.syscall_library.update(angr.SIM_LIBRARIES['cgcabi_tracer'])
        s = p.factory.tracer_state(input_content=payload,
                                   magic_content=self._runner.magic,
                                   preconstrain_input=False,
                                   remove_options=remove_options)

        self._simgr = p.factory.simgr(s, save_unsat=True, hierarchy=False, save_unconstrained=self._runner.crash_mode)
        self._t = angr.exploration_techniques.Tracer(trace=self._runner.trace)
        c = angr.exploration_techniques.CrashMonitor(trace=self._runner.trace,
                                                     crash_mode=self._runner.crash_mode,
                                                     crash_addr=self._runner.crash_addr)
        self._simgr.use_technique(c)
        self._simgr.use_technique(self._t)
        self._simgr.use_technique(angr.exploration_techniques.Oppologist())

        s = self._simgr.one_active

        ZenPlugin.prep_tracer(s)

        backing = SimSymbolicMemory(memory_id='file_colorguard')
        backing.set_state(s)
        backing.store(0, s.se.BVV(payload))

        s.posix.files[0] = SimFile('/dev/stdin', 'r', content=backing, size=len(payload))

        # will be overwritten by _concrete_difference if the input was filtered
        # this attributed is used exclusively for testing at the moment
        self._no_concrete_difference = not self._concrete_difference()

        self.leak_ast = None
Ejemplo n.º 10
0
 def set_input(self, arg):
     self.arg1 = self.make_symbolic_char_args(arg)
     self.initial_state = self.project.factory.entry_state(
         args=[self.exe, self.arg1],
         add_options=angr.options.unicorn,
         remove_options=angr.options.simplification)
     self.constrain_input_chars(self.initial_state, self.arg1a, arg)
     self.string_terminate(self.initial_state, self.arg1a, arg)
     self.simgr = self.project.factory.simgr(self.initial_state,
                                             mode='tracing')
     self.runner = tracer.QEMURunner(binary=self.exe,
                                     input=b'',
                                     project=self.project,
                                     argv=[self.exe, arg])
     self.simgr.use_technique(
         angr.exploration_techniques.Tracer(trace=self.runner.trace))
     self.seen = {}
     self.reset_comparisons()
Ejemplo n.º 11
0
def do_trace(proj, test_name, input_data):
    """
    trace, magic, crash_mode, crash_addr = load_cached_trace(proj, "test_blurble")
    """
    fname = os.path.join(bin_location, 'tests_data', 'runner_traces', '%s_%s_%s.p' % (test_name, os.path.basename(proj.filename), proj.arch.name))

    if os.path.isfile(fname):
        with open(fname, 'rb') as f:
            r = pickle.load(f)
            assert type(r) is tuple and len(r) == 4
            return r

    if tracer is None:
        raise Exception("Tracer is not installed and cached data is not present - cannot run test")

    runner = tracer.QEMURunner(project=proj, input=input_data)
    r = (runner.trace, runner.magic, runner.crash_mode, runner.crash_addr)
    with open(fname, 'wb') as f:
        pickle.dump(r, f, -1)
    return r
Ejemplo n.º 12
0
def test_fauxware():
    b = os.path.join(bin_location, "tests/x86_64/fauxware")
    r = tracer.QEMURunner(binary=b, input="A")
    p = angr.make_tracer_project(binary=b)
    s = p.factory.tracer_state(input_content="A", magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()

    nose.tools.assert_true('traced' in simgr.stashes)
Ejemplo n.º 13
0
def test_manual_recursion():
    b = os.path.join(bin_location, "tests/cgc", "CROMU_00071")

    blob = open(os.path.join(bin_location, 'tests_data/', 'crash2731')).read()
    r = tracer.QEMURunner(binary=b, input=blob)
    p = angr.make_tracer_project(binary=b)
    s = p.factory.tracer_state(input_content=blob, magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()
    print simgr.stashes, c.last_state, t.predecessors[0]
Ejemplo n.º 14
0
def test_crash_addr_detection():
    b = os.path.join(bin_location, "tests/i386/call_symbolic")
    r = tracer.QEMURunner(binary=b, input="A" * 700)
    p = angr.make_tracer_project(binary=b)
    s = p.factory.tracer_state(input_content="A" * 700, magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()

    nose.tools.assert_true('crashed' in simgr.stashes)
    nose.tools.assert_true(simgr.crashed[0].se.symbolic(
        simgr.crashed[0].regs.ip))
Ejemplo n.º 15
0
def test_allocation_base_continuity():
    correct_out = 'prepare for a challenge\nb7fff000\nb7ffe000\nb7ffd000\nb7ffc000\nb7ffb000\nb7ffa000\nb7ff9000\nb7ff8000\nb7ff7000\nb7ff6000\nb7ff5000\nb7ff4000\nb7ff3000\nb7ff2000\nb7ff1000\nb7ff0000\nb7fef000\nb7fee000\nb7fed000\nb7fec000\ndeallocating b7ffa000\na: b7ffb000\nb: b7fff000\nc: b7ff5000\nd: b7feb000\ne: b7fe8000\ne: b7fa8000\na: b7ffe000\nb: b7ffd000\nc: b7ff7000\nd: b7ff6000\ne: b7ff3000\ne: b7f68000\nallocate: 3\na: b7fef000\n'

    b = os.path.join(bin_location, "tests/i386/cgc_allocations")
    r = tracer.QEMURunner(binary=b, input="")
    p = angr.make_tracer_project(binary=b)
    s = p.factory.tracer_state(input_content="", magic_content=r.magic)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()

    nose.tools.assert_equal(simgr.traced[0].posix.dumps(1), correct_out)
Ejemplo n.º 16
0
def test_recursion():
    blob = "00aadd114000000000000000200000001d0000000005000000aadd2a1100001d0000000001e8030000aadd21118611b3b3b3b3b3e3b1b1b1adb1b1b1b1b1b1118611981d8611".decode(
        'hex')
    b = os.path.join(os.path.dirname(__file__),
                     "../../binaries/tests/cgc/NRFIN_00075")
    r = tracer.QEMURunner(binary=b, input=blob)
    p = angr.make_tracer_project(binary=b)
    s = p.factory.tracer_state(input_content=blob)
    simgr = p.factory.simgr(s,
                            save_unsat=True,
                            hierarchy=False,
                            save_unconstrained=r.crash_mode)
    t = angr.exploration_techniques.Tracer(trace=r.trace)
    c = angr.exploration_techniques.CrashMonitor(trace=r.trace,
                                                 crash_mode=r.crash_mode,
                                                 crash_addr=r.crash_addr)
    simgr.use_technique(c)
    simgr.use_technique(t)
    simgr.use_technique(angr.exploration_techniques.Oppologist())

    simgr.run()

    print simgr.stashes, c.last_state, t.predecessors[0]
Ejemplo n.º 17
0
from angr.storage.file import SimFileStream

import logging
logging.getLogger('angr.exploration_techniques').setLevel('DEBUG')

path = '/home/kylebot/src/angr-dev/binaries/tests/cgc/cfe_CADET_00003'
inp = b'A'*0x80

proj = angr.Project(path)

input_file = SimFileStream(name='stdin', ident='aeg_stdin')
state = proj.factory.full_init_state(stdin=input_file)
state.preconstrainer.preconstrain_file(inp, input_file, set_length=True)
#通过插件指定预约束,执行指定的输入
simgr = proj.factory.simgr(state)
runner = tracer.QEMURunner(path, inp)
#通过qemu获取执行的tracer块地址
tracer_tech = angr.exploration_techniques.Tracer(trace=runner.trace, crash_addr=runner.crash_addr)
#通过使用angr的tracer插件,不断记录angr在预约束下的路径是否与qemu相同
simgr.use_technique(tracer_tech)

simgr.run()
#获取指定state后通过添加约束找到新的路径或者crash内容
found = simgr.traced[0]

print('preconstraint:', len(found.preconstrainer.preconstraints))
print('before simplification:', len(found.solver.constraints))
found.solver.simplify()
print('after simplification:', len(found.solver.constraints))
found.preconstrainer.remove_preconstraints()
print('after remove preconstraints:', len(found.solver.constraints))
Ejemplo n.º 18
0
    def post_analysis(self):
        regs_to_check = []
        if "AST" in self.orig_regs:
            regs_to_check.append("AST")
        else:
            regs_to_check = CGC_GENERAL_REGS

        for reg in regs_to_check:
            flag_bits = CGC_FLAG_PAGE >> 12

            # shouldn't unset any already good bits
            orig_bits = self.orig_regs[reg] >> 12
            orig_matching_bits = (~(flag_bits ^ orig_bits)) & 0xfffff

            curr_best_matches = []

            for i in self.byte_analysis:
                ast_vals = [x["AST"] for x in self.byte_analysis[i].reg_vals.values()]
                for a in ast_vals:
                    bits = a >> 12
                    matching_bits = ~(flag_bits ^ bits) & 0xfffff
                    if matching_bits & orig_matching_bits != orig_matching_bits:
                        continue
                    else:
                        is_better_than_curr = True
                        for b in list(curr_best_matches):
                            matching_bits_b = ~(flag_bits ^ b) & 0xfffff
                            if matching_bits & matching_bits_b == matching_bits:
                                is_better_than_curr = False
                            elif matching_bits & matching_bits_b == matching_bits_b:
                                curr_best_matches.remove(b)
                        if is_better_than_curr:
                            curr_best_matches.append(bits)

            # verify it can be pointed at flag page
            all_bits = reduce(operator.__or__, [~(x ^ flag_bits) & 0xfffff for x in curr_best_matches])
            if bin(all_bits).count("1") < 20:
                continue

            match_dict = defaultdict(set)
            # now get all bytes that match each best
            for i in self.byte_analysis:
                for b in self.byte_analysis[i].reg_vals:
                    a = self.byte_analysis[i].reg_vals[b][reg]
                    bits = a >> 12
                    if bits in curr_best_matches:
                        match_dict[bits].add((i, b))

            # now pick a random from each set, dump an input and see if we get more output
            choices = []
            for bits in match_dict:
                choices.append(random.choice(list(match_dict[bits])))

            new_input = self.crash
            for index, b in choices:
                new_input = self._replace_indices(new_input, b, [index])

            r = tracer.QEMURunner(self.binary, input=new_input, record_stdout=True, record_magic=True)
            new_stdout = r.stdout
            if len(new_stdout) > len(self.orig_stdout):
                # okay we have a leak
                # now we should try to guess what we leaked
                leak_idx = None
                for i in range(len(new_stdout)):
                    if new_stdout[i:i+4] in r.magic:
                        leak_idx = i
                        break
                if leak_idx is None:
                    # need to send to colorguard...
                    l.warning("need to send to colorguard but not implemented")
                    self._raw_payload = new_input
                else:
                    self._raw_payload = new_input
                    self.output_leak_idx = leak_idx
                    num_good = 0
                    if self.test_binary(enable_randomness=False):
                        num_good +=1
                        l.warning("works with no randomness")
                    for i in range(5):
                        if self.test_binary(enable_randomness=True):
                            num_good += 1
                    l.warning("worked %d/6 times", num_good)

                    if num_good > 0:
                        break
            return None
Ejemplo n.º 19
0
    def __init__(self,
                 binary,
                 crash=None,
                 pov_file=None,
                 aslr=None,
                 constrained_addrs=None,
                 crash_state=None,
                 prev_path=None,
                 hooks=None,
                 format_infos=None,
                 rop_cache_tuple=None,
                 use_rop=True,
                 explore_steps=0,
                 angrop_object=None):
        '''
        :param binary: path to the binary which crashed
        :param crash: string of input which crashed the binary
        :param pov_file: CGC PoV describing a crash
        :param aslr: analyze the crash with aslr on or off
        :param constrained_addrs: list of addrs which have been constrained during exploration
        :param crash_state: an already traced crash state
        :param prev_path: path leading up to the crashing block
        :param hooks: dictionary of simprocedure hooks, addresses to simprocedures
        :param format_infos: a list of atoi FormatInfo objects that should be used when analyzing the crash
        :param rop_cache_tuple: a angrop tuple to load from
        :param use_rop: whether or not to use rop
        :param explore_steps: number of steps which have already been explored, should only set by exploration methods
        :param angrop_object: an angrop object, should only be set by exploration methods
        '''

        self.binary = binary
        self.crash = crash
        self.constrained_addrs = [] if constrained_addrs is None else constrained_addrs
        self.hooks = {} if hooks is None else hooks
        self.explore_steps = explore_steps

        if self.explore_steps > 10:
            raise CannotExploit(
                "Too many steps taken during crash exploration")

        self.project = angr.Project(binary)
        for addr, proc in self.hooks.iteritems():
            self.project.hook(addr, proc)
            l.debug("Hooking %#x -> %s...", addr, proc.display_name)

        if self.project.loader.main_object.os == 'cgc':
            self.project._simos.syscall_library.update(
                angr.SIM_LIBRARIES['cgcabi_tracer'])

        # we search for ROP gadgets now to avoid the memory exhaustion bug in pypy
        # hash binary contents for rop cache name
        binhash = hashlib.md5(open(self.binary).read()).hexdigest()
        rop_cache_path = os.path.join(
            "/tmp", "%s-%s-rop" % (os.path.basename(self.binary), binhash))

        if use_rop:
            if angrop_object is not None:
                self.rop = angrop_object
            else:
                self.rop = self.project.analyses.ROP()
                if rop_cache_tuple is not None:
                    l.info("loading rop gadgets from cache tuple")
                    self.rop._load_cache_tuple(rop_cache_tuple)
                elif os.path.exists(rop_cache_path):
                    l.info("loading rop gadgets from cache '%s'",
                           rop_cache_path)
                    self.rop.load_gadgets(rop_cache_path)
                else:
                    self.rop.find_gadgets(show_progress=False)
                    self.rop.save_gadgets(rop_cache_path)
        else:
            self.rop = None

        self.os = self.project.loader.main_object.os

        # determine the aslr of a given os and arch
        if aslr is None:
            if self.os == "cgc":  # cgc has no ASLR, but we don't assume a stackbase
                self.aslr = False
            else:  # we assume linux is going to enfore stackbased aslr
                self.aslr = True
        else:
            self.aslr = aslr

        if crash_state is None:
            # run the tracer, grabbing the crash state
            remove_options = {
                so.TRACK_REGISTER_ACTIONS, so.TRACK_TMP_ACTIONS,
                so.TRACK_JMP_ACTIONS, so.ACTION_DEPS,
                so.TRACK_CONSTRAINT_ACTIONS, so.LAZY_SOLVES
            }
            add_options = {
                so.MEMORY_SYMBOLIC_BYTES_MAP, so.TRACK_ACTION_HISTORY,
                so.CONCRETIZE_SYMBOLIC_WRITE_SIZES,
                so.CONCRETIZE_SYMBOLIC_FILE_READ_SIZES, so.TRACK_MEMORY_ACTIONS
            }

            # faster place to check for non-crashing inputs

            # optimized crash check
            if self.project.loader.main_object.os == 'cgc':

                if not tracer.QEMURunner(binary, input=self.crash).crash_mode:
                    if not tracer.QEMURunner(binary,
                                             input=self.crash,
                                             report_bad_args=True).crash_mode:
                        l.warning("input did not cause a crash")
                        raise NonCrashingInput

            if pov_file is None and self.crash is None:
                raise ValueError("must specify crash or pov_file")

            if pov_file is not None and self.crash is not None:
                raise ValueError("cannot specify both a pov_file and an crash")

            if pov_file is not None:
                input = TracerPoV(pov_file)
            else:
                input = self.crash

            r = tracer.QEMURunner(binary=binary, input=input)

            s = self.project.factory.tracer_state(
                input_content=input,
                magic_content=r.magic,
                add_options=add_options,
                remove_options=remove_options,
                constrained_addrs=self.constrained_addrs)

            simgr = self.project.factory.simgr(s,
                                               save_unsat=True,
                                               hierarchy=False,
                                               save_unconstrained=r.crash_mode)

            self._t = angr.exploration_techniques.Tracer(trace=r.trace,
                                                         resiliency=False,
                                                         keep_predecessors=2)
            self._c = angr.exploration_techniques.CrashMonitor(
                trace=r.trace,
                crash_mode=r.crash_mode,
                crash_addr=r.crash_addr)
            simgr.use_technique(self._c)
            simgr.use_technique(self._t)
            simgr.use_technique(angr.exploration_techniques.Oppologist())

            s = simgr.one_active
            ChallRespInfo.prep_tracer(s, format_infos)
            ZenPlugin.prep_tracer(s)

            simgr.run()

            # if there was no crash we'll have to use the previous path's state
            if 'crashed' in simgr.stashes:
                # the state at crash time
                self.state = simgr.crashed[0]
                # a path leading up to the crashing basic block
                self.prev = self._t.predecessors[-1]
            else:
                self.state = simgr.traced[0]
                self.prev = self.state

            zp = self.state.get_plugin('zen_plugin')
            if 'crashed' not in simgr.stashes and (zp is not None and len(
                    zp.controlled_transmits) == 0):
                l.warning("input did not cause a crash")
                raise NonCrashingInput

            l.debug("done tracing input")

        else:
            self.state = crash_state
            self.prev = prev_path
            self._t = None
            self._c = None

        # list of actions added during exploitation, probably better object for this attribute to belong to
        self.added_actions = []

        # hacky trick to get all bytes
        #memory_writes = [ ]
        #for var in self.state.memory.mem._name_mapping.keys():
        #    memory_writes.extend(self.state.memory.addrs_for_name(var))

        memory_writes = sorted(self.state.memory.mem.get_symbolic_addrs())
        l.debug("filtering writes")
        memory_writes = [m for m in memory_writes if m / 0x1000 != 0x4347c]
        user_writes = [
            m for m in memory_writes if any(
                "stdin" in v for v in self.state.memory.load(m, 1).variables)
        ]
        flag_writes = [
            m for m in memory_writes if any(
                v.startswith("cgc-flag")
                for v in self.state.memory.load(m, 1).variables)
        ]
        l.debug("done filtering writes")

        self.symbolic_mem = self._segment(user_writes)
        self.flag_mem = self._segment(flag_writes)

        # crash type
        self.crash_types = []
        # action (in case of a bad write or read) which caused the crash
        self.violating_action = None

        l.debug("triaging crash")
        self._triage_crash()
Ejemplo n.º 20
0
    def __init__(self,
                 binary,
                 crash=None,
                 pov_file=None,
                 aslr=None,
                 constrained_addrs=None,
                 crash_state=None,
                 prev_path=None,
                 hooks=None,
                 format_infos=None,
                 rop_cache_tuple=None,
                 use_rop=True,
                 fast_mode=False,
                 explore_steps=0,
                 angrop_object=None,
                 argv=None,
                 concrete_fs=False,
                 chroot=None,
                 rop_cache_path=None,
                 trace_timeout=10,
                 input_type=CrashInputType.STDIN,
                 port=None,
                 use_crash_input=False,
                 tracer_args=None,
                 initial_state=None):
        """
        :param binary:              Path to the binary which crashed.
        :param crash:               String of input which crashed the binary.
        :param pov_file:            CGC PoV describing a crash.
        :param aslr:                Analyze the crash with aslr on or off.
        :param constrained_addrs:   List of addrs which have been constrained
                                    during exploration.
        :param crash_state:         An already traced crash state.
        :param prev_path:           Path leading up to the crashing block.
        :param hooks:               Dictionary of simprocedure hooks, addresses
                                    to simprocedures.
        :param format_infos:        A list of atoi FormatInfo objects that should
                                    be used when analyzing the crash.
        :param rop_cache_tuple:     A angrop tuple to load from.
        :param use_rop:             Whether or not to use rop.
        :param explore_steps:       Number of steps which have already been explored, should
                                    only set by exploration methods.
        :param angrop_object:       An angrop object, should only be set by
                                    exploration methods.
        :param argv:                Optionally specify argv params (i,e,: ['./calc', 'parm1']).
        :param concrete_fs:         Use the host's filesystem for analysis
        :param chroot:              For concrete_fs: use this host directory as the guest root
        :param trace_timeout:       Time the tracing operation out after this number of seconds
        """

        self.binary = binary
        self.crash = crash
        self.constrained_addrs = [] if constrained_addrs is None else constrained_addrs
        self.hooks = {} if hooks is None else hooks
        self.explore_steps = explore_steps
        self.use_crash_input = use_crash_input
        self.input_type = input_type
        self.initial_state = initial_state

        if tracer_args is None:
            tracer_args = {}

        if self.explore_steps > 10:
            raise CannotExploit(
                "Too many steps taken during crash exploration")

        self.project = angr.Project(binary)
        for addr, proc in self.hooks.items():
            self.project.hook(addr, proc)
            l.debug("Hooking %#x -> %s...", addr, proc.display_name)

        # we search for ROP gadgets now to avoid the memory exhaustion bug in pypy
        # hash binary contents for rop cache name
        binhash = hashlib.md5(open(self.binary, 'rb').read()).hexdigest()
        if not rop_cache_path:
            rop_cache_path = os.path.join(
                "/tmp", "%s-%s-rop" % (os.path.basename(self.binary), binhash))

        if use_rop:
            if angrop_object is not None:
                self.rop = angrop_object
            else:
                self.rop = self.project.analyses.ROP(fast_mode=fast_mode)
                if rop_cache_tuple is not None:
                    l.info("loading rop gadgets from cache tuple")
                    self.rop._load_cache_tuple(rop_cache_tuple)
                elif os.path.exists(rop_cache_path):
                    l.info("loading rop gadgets from cache '%s'",
                           rop_cache_path)
                    self.rop.load_gadgets(rop_cache_path)
                else:
                    if angr.misc.testing.is_testing:
                        self.rop.find_gadgets_single_threaded(
                            show_progress=False)
                    else:
                        self.rop.find_gadgets(show_progress=False)
                    self.rop.save_gadgets(rop_cache_path)
        else:
            self.rop = None

        if self.project.loader.main_object.os == 'cgc':
            self.project.simos.syscall_library.update(
                angr.SIM_LIBRARIES['cgcabi_tracer'])

        self.os = self.project.loader.main_object.os
        if self.os.startswith('UNIX'):
            self.os = 'unix'

        # determine the aslr of a given os and arch
        if aslr is None:
            if self.os == "cgc":  # cgc has no ASLR, but we don't assume a stackbase
                self.aslr = False
            else:  # we assume linux is going to enforce stack-based ASLR
                self.aslr = True
        else:
            self.aslr = aslr

        if crash_state is None:
            # run the tracer, grabbing the crash state
            remove_options = {
                so.TRACK_REGISTER_ACTIONS, so.TRACK_TMP_ACTIONS,
                so.TRACK_JMP_ACTIONS, so.ACTION_DEPS,
                so.TRACK_CONSTRAINT_ACTIONS, so.LAZY_SOLVES,
                so.SIMPLIFY_MEMORY_WRITES, so.ALL_FILES_EXIST
            }
            add_options = {
                so.MEMORY_SYMBOLIC_BYTES_MAP, so.TRACK_ACTION_HISTORY,
                so.CONCRETIZE_SYMBOLIC_WRITE_SIZES,
                so.CONCRETIZE_SYMBOLIC_FILE_READ_SIZES, so.TRACK_MEMORY_ACTIONS
            }

            # faster place to check for non-crashing inputs

            # optimized crash check
            if self.os == 'cgc':
                if not tracer.QEMURunner(
                        binary, input=self.crash, **tracer_args).crash_mode:
                    if not tracer.QEMURunner(binary,
                                             input=self.crash,
                                             report_bad_args=True,
                                             **tracer_args).crash_mode:
                        l.warning("input did not cause a crash")
                        raise NonCrashingInput

            if pov_file is None and self.crash is None:
                raise ValueError("must specify crash or pov_file")

            if pov_file is not None and self.crash is not None:
                raise ValueError("cannot specify both a pov_file and an crash")

            if pov_file is not None:
                input_data = TracerPoV(pov_file)
            else:
                input_data = self.crash

            if input_type == CrashInputType.TCP:
                # Feed input to the QEMURunner
                _ = NetworkFeeder("tcp", "localhost", port, input_data)
            elif input_type == CrashInputType.UDP:
                raise NotImplementedError()

            r = tracer.QEMURunner(binary=binary,
                                  input=input_data,
                                  argv=argv,
                                  trace_timeout=trace_timeout,
                                  **tracer_args)

            kwargs = {}
            if self.project.loader.main_object.os == 'cgc':
                cgc = True
            elif self.project.loader.main_object.os.startswith('UNIX'):
                if argv is None:
                    argv = ['./binary']
                kwargs['args'] = argv
                cgc = False

                kwargs['concrete_fs'] = concrete_fs
                kwargs['chroot'] = chroot
            else:
                raise ValueError("Can't analyze binary for OS %s" %
                                 self.project.loader.main_object.os)

            socket_queue = None
            stdin_file = None  # the file that will be fd 0
            input_file = None  # the file that we want to preconstrain

            if input_type == CrashInputType.TCP:
                input_file = input_sock = SimFileStream(name="aeg_tcp_in",
                                                        ident='aeg_stdin')
                output_sock = SimFileStream(name="aeg_tcp_out")
                socket_queue = [None, None, None, (input_sock, output_sock)
                                ]  # FIXME THIS IS A HACK
            else:
                input_file = stdin_file = SimFileStream(name='stdin',
                                                        ident='aeg_stdin')

            if initial_state is None:
                initial_state = self.project.factory.full_init_state(
                    mode='tracing',
                    add_options=add_options,
                    remove_options=remove_options,
                    **kwargs)
                initial_state.register_plugin(
                    'posix',
                    SimSystemPosix(
                        stdin=stdin_file,
                        stdout=SimFileStream(name='stdout'),
                        stderr=SimFileStream(name='stderr'),
                        argc=initial_state.posix.argc,
                        argv=initial_state.posix.argv,
                        environ=initial_state.posix.environ,
                        auxv=initial_state.posix.auxv,
                        socket_queue=socket_queue,
                    ))

                initial_state.register_plugin(
                    'preconstrainer',
                    SimStatePreconstrainer(self.constrained_addrs))
                initial_state.preconstrainer.preconstrain_file(input_data,
                                                               input_file,
                                                               set_length=True)
                if cgc:
                    initial_state.preconstrainer.preconstrain_flag_page(
                        r.magic)

                # Loosen certain libc limits on symbolic input
                initial_state.libc.buf_symbolic_bytes = 3000
                initial_state.libc.max_symbolic_strchr = 3000
                initial_state.libc.max_str_len = 3000
                initial_state.libc.max_buffer_size = 16384

            simgr = self.project.factory.simulation_manager(
                initial_state,
                save_unsat=False,
                hierarchy=False,
                save_unconstrained=r.crash_mode)

            self.initial_state = initial_state

            self._t = angr.exploration_techniques.Tracer(
                trace=r.trace,
                resiliency=False,
                keep_predecessors=2,
                crash_addr=r.crash_addr)
            simgr.use_technique(self._t)
            simgr.use_technique(angr.exploration_techniques.Oppologist())

            if cgc:
                s = simgr.one_active
                ChallRespInfo.prep_tracer(s, format_infos)
                ZenPlugin.prep_tracer(s)

            simgr.run()

            # if there was no crash we'll have to use the previous path's state
            if 'crashed' in simgr.stashes:
                # the state at crash time
                self.state = simgr.crashed[0]
                # a path leading up to the crashing basic block
                self.prev = self._t.predecessors[-1]
            else:
                self.state = simgr.traced[0]
                self.prev = self.state

            zp = self.state.get_plugin('zen_plugin') if cgc else None
            if 'crashed' not in simgr.stashes and zp is not None and len(
                    zp.controlled_transmits) == 0:
                l.warning("input did not cause a crash")
                raise NonCrashingInput

            l.debug("done tracing input")

        else:
            self.state = crash_state
            self.prev = prev_path
            self._t = None

        # list of actions added during exploitation, probably better object for this attribute to belong to
        self.added_actions = []

        # hacky trick to get all bytes
        #memory_writes = [ ]
        #for var in self.state.memory.mem._name_mapping.keys():
        #    memory_writes.extend(self.state.memory.addrs_for_name(var))

        memory_writes = sorted(self.state.memory.mem.get_symbolic_addrs())
        l.debug("filtering writes")
        memory_writes = [m for m in memory_writes if m // 0x1000 != 0x4347c]
        user_writes = [
            m for m in memory_writes
            if any("aeg_stdin" in v
                   for v in self.state.memory.load(m, 1).variables)
        ]
        flag_writes = [
            m for m in memory_writes if any(
                v.startswith("cgc-flag")
                for v in self.state.memory.load(m, 1).variables)
        ]
        l.debug("done filtering writes")

        self.symbolic_mem = self._segment(user_writes)
        self.flag_mem = self._segment(flag_writes)

        # crash type
        self.crash_types = []
        # action (in case of a bad write or read) which caused the crash
        self.violating_action = None

        l.debug("triaging crash")
        self._triage_crash()
Ejemplo n.º 21
0
    def __init__(self, binary, crash=None):
        """
        :param binary: path to the binary which crashed
        :param crash: string of input which crashed the binary
        """

        self.binary = binary
        self.crash = crash

        # verify it actually crashes the binary
        r = tracer.QEMURunner(self.binary, input=self.crash, record_stdout=True, record_core=True)
        if not r.crash_mode:
            raise CrashFuzzerException("input did not crash the binary")

        self.orig_stdout = r.stdout

        self.addr_ast = None
        try:
            self._p = angr.Project(self.binary)

            self.orig_regs = r.reg_vals
            s = rop_utils.make_symbolic_state(self._p, reg_list=CGC_GENERAL_REGS)
            self._reg_asts = dict()
            for r in CGC_GENERAL_REGS:
                ast = s.se.BVS(r, 32, explicit_name=True)
                self._reg_asts[r] = ast
                s.registers.store(r, ast)
            s.ip = self.orig_regs["eip"]
            all_succ = self._p.factory.successors(s, num_inst=1).all_successors
            if len(all_succ) == 0:
                raise CannotExploit("no successors")
            succ = all_succ[0]
            for a in succ.history.recent_actions:
                if a.type == "mem" and a.action == "read":
                    dependencies = a.addr.ast.variables
                    self.addr_ast = a.addr.ast
                    self.reg_deps = dependencies | {"AST"}

            self.orig_regs = self._fix_reg_vals(self.orig_regs)

            l.debug("REG DEPS: %s", self.reg_deps)
        except CLEError as e:
            l.warning("CLEError: %s", e)
            pass

        if self.addr_ast is None:
            self.reg_deps = set(CGC_GENERAL_REGS)
            l.warning("couldn't find read addr depenency")

        self.pool = None
        self.byte_analysis = dict()
        self._bases = dict()
        self.skip_bytes = set()
        self.skip_sets = set()
        self.regs_to_numbers = dict()
        self.used_bytes = set()
        self.byte_translation_funcs = list()
        self.byte_translation_calls = dict()
        self._bit_patterns = dict()
        self._raw_payload = None
        self.output_leak_idx = None
        self.cgc_type = 2

        self.make_bases()
        self.run()
        self.post_filter()
        self.post_analysis()
Ejemplo n.º 22
0
    def _quick_triage(self, binary, crash):

        l.debug("quick triaging crash against '%s'", binary)

        arbitrary_syscall_arg = False
        r = tracer.QEMURunner(binary,
                              crash,
                              record_trace=True,
                              use_tiny_core=True,
                              record_core=True)

        self.bb_count = len(r.trace)

        if not r.crash_mode:

            # try again to catch bad args
            r = tracer.QEMURunner(binary,
                                  crash,
                                  report_bad_args=True,
                                  record_core=True)
            arbitrary_syscall_arg = True
            if not r.crash_mode:
                raise NonCrashingInput("input did not cause a crash")

            l.debug("detected an arbitrary transmit or receive")

        if r.os != "cgc":
            raise ValueError("QuickCrash is only available for CGC binaries")

        if r.is_multicb:
            project = angr.Project(binary[r.crashed_binary])
        else:
            project = angr.Project(binary)

        # triage the crash based of the register values and memory at crashtime
        # look for the most valuable crashes first

        pc = r.reg_vals['eip']
        l.debug('crash occured at %#x', pc)

        if arbitrary_syscall_arg:
            l.debug("checking which system call had bad args")

            syscall_num = r.reg_vals['eax']
            vulns = {2: Vulnerability.ARBITRARY_TRANSMIT, \
                     3: Vulnerability.ARBITRARY_RECEIVE}

            # shouldn't ever happen but in case it does
            if syscall_num not in vulns:
                return pc, None

            return pc, vulns[syscall_num]

        l.debug("checking if ip is null")
        if pc < 0x1000:
            return pc, Vulnerability.NULL_DEREFERENCE

        l.debug("checking if ip register points to executable memory")

        start_state = project.factory.entry_state(
            addr=pc, add_options={so.TRACK_MEMORY_ACTIONS})

        # was ip mapped?
        ip_overwritten = False
        try:
            perms = start_state.memory.permissions(pc)
            # check if the execute bit is marked, this is an AST
            l.debug("ip points to mapped memory")
            if not perms.symbolic and not ((perms & 4) == 4).args[0]:
                l.debug("ip appears to be uncontrolled")
                return pc, Vulnerability.UNCONTROLLED_IP_OVERWRITE

        except angr.SimMemoryError:
            ip_overwritten = True

        if ip_overwritten:
            # let's see if we can classify it as a partial overwrite
            # this is done by seeing if the most signifigant bytes of
            # pc could be a mapping
            cgc_object = project.loader.all_elf_objects[0]
            base = cgc_object.min_addr & 0xff000000
            while base < cgc_object.max_addr:
                if pc & 0xff000000 == base:
                    l.debug("ip appears to only be partially controlled")
                    return pc, Vulnerability.PARTIAL_IP_OVERWRITE
                base += 0x01000000

            l.debug("ip appears to be completely controlled")
            return pc, Vulnerability.IP_OVERWRITE

        # wasn't an ip overwrite, check reads and writes
        l.debug("checking if a read or write caused the crash")

        # set registers
        start_state.regs.eax = r.reg_vals['eax']
        start_state.regs.ebx = r.reg_vals['ebx']
        start_state.regs.ecx = r.reg_vals['ecx']
        start_state.regs.edx = r.reg_vals['edx']
        start_state.regs.esi = r.reg_vals['esi']
        start_state.regs.edi = r.reg_vals['edi']
        start_state.regs.esp = r.reg_vals['esp']
        start_state.regs.ebp = r.reg_vals['ebp']

        next_pth = project.factory.successors(start_state,
                                              num_inst=1).successors[0]

        posit = None
        for a in next_pth.history.recent_actions:
            if a.type == 'mem':

                target_addr = start_state.se.eval(a.addr)
                if target_addr < 0x1000:
                    l.debug("attempt to write or read to address of NULL")
                    return pc, Vulnerability.NULL_DEREFERENCE

                # we will take the last memory action, so things like an `add` instruction
                # are triaged as a 'write' opposed to a 'read'
                if a.action == 'write':
                    l.debug("write detected")
                    posit = Vulnerability.WRITE_WHAT_WHERE
                    # if it's trying to write to a non-writeable address which is mapped
                    # it's most likely uncontrolled
                    if target_addr & 0xfff00000 == 0:
                        l.debug(
                            "write attempt at a suspiciously small address, assuming uncontrolled"
                        )
                        return pc, Vulnerability.UNCONTROLLED_WRITE

                    try:
                        perms = start_state.memory.permissions(target_addr)
                        if not perms.symbolic and not (
                            (perms & 2) == 2).args[0]:
                            l.debug(
                                "write attempt at a read-only page, assuming uncontrolled"
                            )
                            return pc, Vulnerability.UNCONTROLLED_WRITE

                    except angr.SimMemoryError:
                        pass

                elif a.action == 'read':
                    l.debug("read detected")
                    posit = Vulnerability.ARBITRARY_READ
                else:
                    # sanity checking
                    raise ValueError(
                        "unrecognized memory action encountered %s" % a.action)

        if posit is None:
            l.debug("crash was not able to be triaged")
            posit = 'unknown'

        # returning 'unknown' if crash does not fall into one of our obvious categories
        return pc, posit
Ejemplo n.º 23
0
    def __init__(self, binary, payload):
        """
        :param binary: path to the binary which is suspect of leaking
        :param payload: concrete input string to feed to the binary
        """

        self.binary = binary
        self.payload = payload

        if not os.access(self.binary, os.X_OK):
            raise ValueError(
                "\"%s\" binary does not exist or is not executable" %
                self.binary)

        # will be set by causes_leak
        self._leak_path = None

        self._runner = tracer.QEMURunner(binary=binary, input=payload)

        # load the binary
        self.project = angr.Project(binary)
        self.project.simos.syscall_library.update(
            angr.SIM_LIBRARIES['cgcabi_tracer'])

        # set up the state for analysis
        remove_options = {angr.options.SUPPORT_FLOATING_POINT}
        add_options = angr.options.unicorn | {
            angr.options.CGC_NO_SYMBOLIC_RECEIVE_LENGTH,
            angr.options.UNICORN_THRESHOLD_CONCRETIZATION,
            angr.options.REPLACEMENT_SOLVER
        }
        state = self.project.factory.full_init_state(
            remove_options=remove_options, add_options=add_options)

        # Make our own special posix
        state.register_plugin(
            'posix',
            SimSystemPosix(stdin=SimFileStream('stdin', content=payload),
                           stdout=SimFileStream('stdout'),
                           stderr=SimFileStream('stderr')))

        # Create the preconstrainer plugin
        state.register_plugin('preconstrainer', SimStatePreconstrainer())
        state.preconstrainer.preconstrain_flag_page(self._runner.magic)

        # Set up zen
        ZenPlugin.prep_tracer(state)

        # Make the simulation manager
        self._simgr = self.project.factory.simulation_manager(
            state,
            save_unsat=True,
            hierarchy=False,
            save_unconstrained=self._runner.crash_mode)
        self._t = angr.exploration_techniques.Tracer(trace=self._runner.trace,
                                                     resiliency=False)
        self._simgr.use_technique(self._t)
        self._simgr.use_technique(angr.exploration_techniques.Oppologist())

        # will be overwritten by _concrete_difference if the input was filtered
        # this attributed is used exclusively for testing at the moment
        self._no_concrete_difference = not self._concrete_difference()

        self.leak_ast = None