Beispiel #1
0
    def _prep_challenge_response(self, format_infos=None):

        # need to re-trace the binary with stdin symbolic

        remove_options = {so.SUPPORT_FLOATING_POINT}

        p = angr.Project(self.binary)
        p._simos.syscall_library.update(angr.SIM_LIBRARIES['cgcabi_tracer'])
        s = p.factory.tracer_state(input_content=self.payload,
                                   magic_content=self._runner.magic,
                                   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)

        ChallRespInfo.prep_tracer(s, format_infos)

        assert self.causes_leak(), "challenge did not cause leak when trying to recover challenge-response"

        return self.attempt_pov(enabled_chall_resp=True)
Beispiel #2
0
    def _prep_challenge_response(self, format_infos=None):
        """
        Set up the internal tracer for challenge-response analysis

        :param format_infos: a list of atoi FormatInfo objects that should be used when analyzing the crash
        """

        # need to re-trace the binary with stdin symbolic

        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(
            add_options=add_options, remove_options=remove_options)

        # Make our own special posix
        state.register_plugin(
            'posix',
            SimSystemPosix(
                stdin=SimFileStream(
                    'stdin', ident='aeg_input_stdin'
                ),  # we do tests against the name of the variable...
                stdout=SimFileStream('stdout'),
                stderr=SimFileStream('stderr')))

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

        # Set up zen
        ZenPlugin.prep_tracer(state)
        ChallRespInfo.prep_tracer(state, format_infos)

        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())

        assert self.causes_leak(
        ), "challenge did not cause leak when trying to recover challenge-response"

        return self.attempt_pov(enabled_chall_resp=True)
Beispiel #3
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()
Beispiel #4
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()
Beispiel #5
0
    def _trace(self, pov_file=None, format_infos=None):
        """
        Symbolically trace the target program with the given input. A NonCrashingInput exception will be raised if the
        target program does not crash with the given input.

        :param pov_file:        CGC-specific setting.
        :param format_infos:    CGC-specific setting.
        :return:                None.
        """

        # sanity check
        if pov_file is None and self.crash is None:
            raise ValueError("Must specify either 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 a crash.")

        # faster place to check for non-crashing inputs
        if self.is_cgc:
            cgc_flag_page_magic = self._cgc_get_flag_page_magic()
        else:
            cgc_flag_page_magic = None

        # Prepare the initial state

        if pov_file is not None:
            test_case = TracerPoV(pov_file)
            channel = None
        else:
            input_data = self.crash
            channel = self.input_type_to_channel_type(self.input_type)
            if channel != "stdio":
                channel += ":0"
            test_case = input_data

        # collect a concrete trace
        save_core = True
        if isinstance(self.tracer_bow, archr.arsenal.RRTracerBow):
            save_core = False
        r = self.tracer_bow.fire(testcase=test_case, channel=channel, save_core=save_core)

        if save_core:
            # if a coredump is available, save a copy of all registers in the coredump for future references
            if r.core_path and os.path.isfile(r.core_path):
                tiny_core = TinyCore(r.core_path)
                self.core_registers = tiny_core.registers
            else:
                l.error("Cannot find core file (path: %s). Maybe the target process did not crash?",
                        r.core_path)

        if self.initial_state is None:
            self.initial_state = self._create_initial_state(input_data, cgc_flag_page_magic=cgc_flag_page_magic)

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

        # trace symbolically!
        self._t = r.tracer_technique(keep_predecessors=2, copy_states=False, mode=TracingMode.Strict)
        simgr.use_technique(self._t)
        simgr.use_technique(angr.exploration_techniques.Oppologist())
        if self.is_cgc:
            s = simgr.one_active
            ChallRespInfo.prep_tracer(s, format_infos)
            ZenPlugin.prep_tracer(s)
        simgr.run()

        # tracing completed
        # 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 self.is_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.")
Beispiel #6
0
    def _trace(self, pov_file=None, format_infos=None):

        # faster place to check for non-crashing inputs

        # optimized crash check
        if self.os == 'cgc':
            r = self.tracer_bow.fire(save_core=True,
                                     record_magic=True,
                                     testcase=self.crash)
            if not r.crashed:
                if not self.tracer_bow.fire(save_core=True,
                                            testcase=self.crash,
                                            report_bad_args=True).crashed:
                    l.warning("input did not cause a crash")
                    raise NonCrashingInput
            cgc_flag_page_magic = r.magic_contents
        else:
            cgc_flag_page_magic = None

        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

        nf = None
        stdin_data = None
        if self.input_type == CrashInputType.TCP:
            # Feed input to the QEMURunner
            if isinstance(self.target, archr.targets.DockerImageTarget):
                ip_address = self.target.ipv4_address
            elif isinstance(self.target, archr.targets.LocalTarget):
                ip_address = "localhost"
            else:
                raise NotImplementedError()
            nf = NetworkFeeder("tcp", ip_address, self.target_port, input_data)
        elif self.input_type == CrashInputType.UDP:
            raise NotImplementedError('UDP is not supported yet.')
        elif self.input_type == CrashInputType.STDIN:
            stdin_data = input_data
        else:
            raise NotImplementedError('Input type %s is not supported yet.' %
                                      self.input_type)

        # who the f**k do you think you are I am!!!
        #if not self.core_registers:
        #    with archr.arsenal.CoreBow(self.target).fire_context(timeout=self.trace_timeout, aslr=False,
        #                                                         **tracer_args) as r:
        #        # Fire it once to get a core on the native target
        #        if nf is not None:
        #            thread_id = nf.fire()
        #            nf.join(thread_id)
        #        if stdin_data is not None:
        #            r.p.stdin.write(stdin_data)
        #            r.p.stdin.close()
        #        # Now it's done

        #    # If a coredump is available, save a copy of all registers in the coredump for future references
        #    if os.path.isfile(r.local_core_path):
        #        tiny_core = tracer.TinyCore(r.local_core_path)
        #        self.core_registers = tiny_core.registers
        #    else:
        #        l.error("Cannot find core file (path: %s). Maybe the target process did not crash?",
        #                r.local_core_path)

        thread_id = None
        if nf is not None:
            thread_id = nf.fire()
        r = self.tracer_bow.fire(testcase=input_data, save_core=False)
        if nf is not None:
            nf.join(thread_id)

        if self.initial_state is None:
            self.initial_state = self._create_initial_state(
                input_data, cgc_flag_page_magic=cgc_flag_page_magic)

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

        self._t = r.tracer_technique(keep_predecessors=2)
        simgr.use_technique(self._t)
        simgr.use_technique(angr.exploration_techniques.Oppologist())

        if self.is_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 self.is_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")