Beispiel #1
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.Runner(self.binary, input=self.crash)
        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()
Beispiel #2
0
def test_unicorn():
    p = angr.Project(
        os.path.join(test_location,
                     'binaries-private/cgc_qualifier_event/cgc/99c22c01_01'))

    s_unicorn = p.factory.entry_state(
        add_options=so.unicorn
        | {so.CGC_NO_SYMBOLIC_RECEIVE_LENGTH, so.STRICT_PAGE_ACCESS},
        remove_options={so.LAZY_SOLVES})  # unicorn
    s_angr = p.factory.entry_state(add_options={
        so.CGC_NO_SYMBOLIC_RECEIVE_LENGTH, so.INITIALIZE_ZERO_REGISTERS,
        so.STRICT_PAGE_ACCESS
    },
                                   remove_options={so.LAZY_SOLVES
                                                   })  # pure angr

    pg_unicorn = p.factory.path_group(s_unicorn)
    pg_angr = p.factory.path_group(s_angr)

    # input = 'x\n\0\0\0\0'
    inp = 'L\x0alaehdamfeg\x0a10\x2f28\x2f2014\x0a-2147483647:-2147483647:-2147483647\x0ajfifloiblk\x0a126\x0a63\x0a47\x0a31\x0a3141\x0a719\x0a'

    stdin = s_unicorn.posix.get_file(0)
    stdin.write(inp, len(inp))
    stdin.seek(0)
    stdin.size = len(inp)

    stdin = s_angr.posix.get_file(0)
    stdin.write(inp, len(inp))
    stdin.seek(0)
    stdin.size = len(inp)

    t = tracer.Runner(p.filename, inp, record_trace=True)
    t.dynamic_trace()
    real_trace = t.trace

    pg_unicorn.run()
    uc_trace = pg_unicorn.one_errored.addr_trace.hardcopy + [
        pg_unicorn.one_errored.addr
    ]
    pg_angr.run()
    angr_trace = pg_angr.one_errored.addr_trace.hardcopy + [
        pg_angr.one_errored.addr
    ]
    uc_trace_filtered = [
        a for a in uc_trace if not p._extern_obj.contains_addr(a)
        and not p._syscall_obj.contains_addr(a)
    ]

    # not assert_equal because it tries to use a fancy algorithm that blows up on long lists
    nose.tools.assert_true(uc_trace_filtered == real_trace)
    nose.tools.assert_true(uc_trace == angr_trace)
    nose.tools.assert_equal(pg_angr.one_errored.error.addr,
                            pg_unicorn.one_errored.error.addr)

    uc_calltrace = _get_calltrace(pg_unicorn.one_errored)
    angr_calltrace = _get_calltrace(pg_angr.one_errored)
    nose.tools.assert_true(uc_calltrace == angr_calltrace)
Beispiel #3
0
def _get_reg_vals(binary_input_byte):
    binary, test_input, c = binary_input_byte
    r = tracer.Runner(binary, input=test_input)
    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]
Beispiel #4
0
    def _concrete_leak_info(self, seed=None):

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

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

        return (r1.stdout, r1.magic)
Beispiel #5
0
    def __init__(self, binary, crash=None, ids_rules=None, time_limit=None):
        """
        :param binary: path to the binary which crashed (or list of binaries)
        :param crash: string of input which crashed the binary
        :param ids_rules: the string ids rules
        :param time_limit: the max time in seconds
        """

        if isinstance(binary, (list, tuple)):
            self.binaries = binary
        else:
            self.binaries = [binary]

        self.crash = crash
        global glob_ids_rules
        glob_ids_rules = ids_rules
        self.ids_rules = ids_rules

        # verify it actually crashes the binary
        if USE_ANGR:
            #	    print('use_angr: ',USE_ANGR)
            if len(self.binaries) > 0:
                #		print('binary length: ',len(self.binaries))
                raise ValueError("No support for MultiCBs with USE_ANGR=True")
            r = tracer.Runner(self.binaries[0], input=self.crash)
        else:
            #	    print('not use angr: ',len(self.binaries))
            r = CustomRunner(self.binaries,
                             payload=self.crash,
                             ids_rules=glob_ids_rules)
        if not r.crash_mode:
            raise CrashFuzzerException("input did not crash the 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()
        time_limit = time_limit if time_limit is not None else 2000
        self._end_time = time.time() + time_limit

        self.make_bases()
        self.run()
def _get_reg_vals(binary_input_byte):
    global glob_ids_rules
    binary, test_input, c = binary_input_byte
    try:
        if USE_ANGR:
            r = tracer.Runner(binary, input=test_input)
        else:
            r = CustomRunner(binary,
                             payload=test_input,
                             ids_rules=glob_ids_rules)
        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]
    except Exception as e:
        print e
        return [c, None]
def _get_reg_vals(binary_input_byte):
    global glob_ids_rules
    binaries, test_input, c = binary_input_byte
    try:
        if USE_ANGR:
            if len(binaries) > 1:
                raise ValueError("No support for MultiCB with USE_ANGR=True")
            r = tracer.Runner(binaries[0], input=test_input)
        else:
            r = CustomRunner(binaries,
                             payload=test_input,
                             ids_rules=glob_ids_rules)
        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]
    except Exception as e:
        print e
        return [c, None]
Beispiel #8
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.Runner(self.binary, input=self.crash, record_stdout=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"]
            p = self._p.factory.path(s)
            p.step(num_inst=1)
            all_succ = p.successors + p.unconstrained_successors
            if len(all_succ) == 0:
                raise CannotExploit("no successors")
            succ = all_succ[0]
            for a in succ.actions.hardcopy:
                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()
Beispiel #9
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],
                initial=0)
            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.Runner(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
Beispiel #10
0
    def _quick_triage(self, binary, crash):

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

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

        self.bb_count = len(r.trace)

        if not r.crash_mode:

            # try again to catch bad args
            r = tracer.Runner(binary, crash, report_bad_args=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)

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

        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
Beispiel #11
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.pov_file = pov_file
        self.constrained_addrs = [] if constrained_addrs is None else constrained_addrs
        self.hooks = 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)

        # 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
            }

            # faster place to check for non-crashing inputs

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

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

            self._tracer = tracer.Tracer(binary,
                                         input=self.crash,
                                         pov_file=self.pov_file,
                                         resiliency=False,
                                         hooks=self.hooks,
                                         add_options=add_options,
                                         remove_options=remove_options,
                                         keep_predecessors=2)
            ChallRespInfo.prep_tracer(self._tracer, format_infos)
            ZenPlugin.prep_tracer(self._tracer)
            prev, crash_state = self._tracer.run(constrained_addrs)

            # if there was no crash we'll have to use the previous path's state
            if crash_state is None:
                self.state = prev
            else:
                # the state at crash time
                self.state = crash_state

            zp = self.state.get_plugin('zen_plugin')
            if crash_state is None 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")
            # a path leading up to the crashing basic block
            self.prev = prev

        else:
            self.state = crash_state
            self.prev = prev_path
            self._tracer = 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()
    def __init__(self, binary, crash=None, ids_rules=None, time_limit=None):
        """
        :param binary: path to the binary which crashed (or list of binaries)
        :param crash: string of input which crashed the binary
        :param ids_rules: the string ids rules
        :param time_limit: the max time in seconds
        """

        if isinstance(binary, (list, tuple)):
            self.binaries = binary
        else:
            self.binaries = [binary]

        self.crash = crash
        global glob_ids_rules
        glob_ids_rules = ids_rules
        self.ids_rules = ids_rules

        # verify it actually crashes the binary
        if USE_ANGR:
            if len(self.binaries) > 0:
                raise ValueError("No support for MultiCBs with USE_ANGR=True")
            r = tracer.Runner(self.binaries,
                              input=self.crash,
                              record_stdout=True)
        else:
            r = CustomRunner(self.binaries,
                             payload=self.crash,
                             record_stdout=True,
                             ids_rules=glob_ids_rules)
        if not r.crash_mode:
            raise CrashFuzzerException("input did not crash the binary")

        self.orig_stdout = r.stdout
        self.orig_regs = r.reg_vals

        self.addr_eqn = self._get_reg_eqn()
        self.orig_regs = self._fix_reg_vals(self.orig_regs)

        if self.addr_eqn is None:
            raise CrashFuzzerException("couldnt get eqn")
        l.debug("crashing read eqn is %s", self.addr_eqn)
        self.reg_deps = set(r for r in CGC_GENERAL_REGS if r in self.addr_eqn)
        self.reg_deps.add("AST")
        l.debug("reg deps: %s", self.reg_deps)

        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
        time_limit = time_limit if time_limit is not None else 2000
        self._end_time = time.time() + time_limit

        self.make_bases()
        self.run()
        self.post_filter()
        self.post_analysis()