Beispiel #1
0
            end_addr = last_addr + last_item_size
            if end_addr < max_addr:
                try:
                    next_addr = self.ceiling_addr(end_addr)
                except KeyError:
                    next_addr = max_addr
                if next_addr > end_addr:
                    # there is a gap
                    size = next_addr - end_addr
                    if obj is None or isinstance(obj, cle.ExternObject):
                        bytes_ = None
                    else:
                        try:
                            _l.debug("Loading bytes from object %s, section %s, segmeng %s, addresss %#x.",
                                     obj, section, segment, next_addr)
                            bytes_ = self.project.loader.memory.load(next_addr, size)
                        except KeyError:
                            # The address does not exist
                            bytes_ = None
                    self.add_obj(end_addr,
                                 Unknown(end_addr, size, bytes_=bytes_, object_=obj, segment=segment, section=section)
                                 )
                addr = next_addr
            else:
                addr = max_addr


from angr.analyses import AnalysesHub
AnalysesHub.register_default('CFB', CFBlanket)
AnalysesHub.register_default('CFBlanket', CFBlanket)
Beispiel #2
0
                                                     counter=n_counter)[-1]
                u_flags = sl.regs.flags.canonicalize(var_map=u_map,
                                                     counter=u_counter)[-1]
            if n_flags is not u_flags and sl.se.simplify(
                    n_flags) is not sr.se.simplify(u_flags):
                self._report_incongruency("Different flags!")
                return False

        return True

    def compare_paths(self, pl, pr):
        l.debug("Comparing paths...")
        if not self.compare_states(pl, pr):
            self._report_incongruency("Failed state similarity check!")
            return False

        if pr.history.block_count != pl.history.block_count:
            self._report_incongruency("Different weights!")
            return False

        if pl.addr != pr.addr:
            self._report_incongruency("Different addresses!")
            return False

        return True


from ..errors import AngrIncongruencyError
from angr.analyses import AnalysesHub
AnalysesHub.register_default('CongruencyCheck', CongruencyCheck)
Beispiel #3
0
        :return: None
        """

        register_pvs = set()
        for node in data_graph.nodes():
            if isinstance(node.variable, SimRegisterVariable) and \
                    node.variable.reg is not None and \
                    node.variable.reg < 40:
                register_pvs.add(node)

        for reg in register_pvs:
            # does it have a consumer?
            out_edges = data_graph.out_edges(reg, data=True)
            consumers = []
            killers = []
            for _, _, data in out_edges:
                if 'type' in data and data['type'] == 'kill':
                    killers.append(data)
                else:
                    consumers.append(data)

            if not consumers and killers:
                # we can remove the assignment!
                da = DeadAssignment(reg)
                self.dead_assignments.append(da)


from angr.analyses import AnalysesHub

AnalysesHub.register_default('BinaryOptimizer', BinaryOptimizer)
Beispiel #4
0
            (src, dst)
            for src, dst, data in reversed_cyclic_graph.edges(data=True)
            if data['jumpkind'] in ('Ijk_FakeRet', 'Ijk_Exit')
        ]
        reversed_cyclic_graph.remove_edges_from(fakeret_edges)

        # Perform a topological sort
        sorted_nodes = networkx.topological_sort(graph)

        nodes = [
            n for n in sorted_nodes
            if graph.in_degree(n) > 1 and n.looping_times == 0
        ]

        # Reorder nodes based on post-dominance relations
        nodes = sorted(
            nodes,
            key=cmp_to_key(lambda n1, n2: (1 if self._post_dominate(
                reversed_cyclic_graph, n1, n2) else (-1 if self._post_dominate(
                    reversed_cyclic_graph, n2, n1) else 0))))

        return [(n.addr, n.looping_times) for n in nodes]


from angr.analyses import AnalysesHub
AnalysesHub.register_default('Veritesting', Veritesting)

from ..errors import SimValueError, SimSolverModeError, SimError
from ..sim_options import BYPASS_VERITESTING_EXCEPTIONS
from claripy import ClaripyError
Beispiel #5
0
                                                     size=node.size,
                                                     opt_level=0  # disable the optimization in order to have
                                                                  # instruction-level analysis results
                                                     )
        output_states = successors.all_successors

        state.concrete_states = [ state for state in output_states if not state.ip.symbolic ]

        self._outstates[node.addr] = state

        self._node_iterations[node] += 1

        return True, state

    def _intra_analysis(self):
        pass

    def _post_analysis(self):
        # TODO: only re-assign variable names to those that are newly changed
        self.variable_manager.initialize_variable_names()

        for addr, state in self._outstates.items():
            self.variable_manager[self.function.addr].set_live_variables(addr,
                                                                         state.register_region,
                                                                         state.stack_region
                                                                         )


from angr.analyses import AnalysesHub
AnalysesHub.register_default('VariableRecovery', VariableRecovery)
Beispiel #6
0
            # This is for testing
            successors = graph.graph.successors(node)
        else:
            # Real CFGNode!
            successors = graph.model.get_successors(node)

        return successors

    def _pd_post_process(self, cfg):
        """
        Take care of those loop headers/tails where we manually broke their
        connection to the next BBL
        """
        loop_back_edges = self._cfg.get_loop_back_edges()

        for b1, b2 in loop_back_edges:
            # The edge between b1 and b2 is manually broken
            # The post dominator of b1 should be b2 (or not?)

            successors = list(self._pd_graph_successors(cfg, b1))

            if len(successors) == 0:
                if b2 in self._post_dom:
                    self._post_dom.add_edge(b1, b2)
                else:
                    _l.debug("%s is not in post dominator dict.", b2)


from angr.analyses import AnalysesHub
AnalysesHub.register_default('CDG', CDG)
Beispiel #7
0
        Search for the last branching exit, just like
        #   if (t12) { PUT(184) = 0xBADF00D:I64; exit-Boring }
        and then taint the temp variable inside if predicate
        """
        cmp_stmt_id = None
        cmp_tmp_id = None
        all_statements = len(statements)
        statements = reversed(statements)
        for stmt_rev_idx, stmt in enumerate(statements):
            stmt_idx = all_statements - stmt_rev_idx - 1
            actions = stmt.actions
            # Ugly implementation here
            has_code_action = False
            for a in actions:
                if isinstance(a, SimActionExit):
                    has_code_action = True
                    break
            if has_code_action:
                readtmp_action = next(filter(lambda r: r.type == 'tmp' and r.action == 'read', actions), None)
                if readtmp_action is not None:
                    cmp_tmp_id = readtmp_action.tmp
                    cmp_stmt_id = stmt_idx
                    break
                else:
                    raise AngrBackwardSlicingError("ReadTempAction is not found. Please report to Fish.")

        return cmp_stmt_id, cmp_tmp_id

from angr.analyses import AnalysesHub
AnalysesHub.register_default('BackwardSlice', BackwardSlice)
Beispiel #8
0
                n_flags = sr.regs.eflags.canonicalize(var_map=n_map, counter=n_counter)[-1]
                u_flags = sl.regs.eflags.canonicalize(var_map=u_map, counter=u_counter)[-1]
            else:
                n_flags = sr.regs.flags.canonicalize(var_map=n_map, counter=n_counter)[-1]
                u_flags = sl.regs.flags.canonicalize(var_map=u_map, counter=u_counter)[-1]
            if n_flags is not u_flags and sl.se.simplify(n_flags) is not sr.se.simplify(u_flags):
                self._report_incongruency("Different flags!")
                return False

        return True

    def compare_paths(self, pl, pr):
        l.debug("Comparing paths...")
        if not self.compare_states(pl, pr):
            self._report_incongruency("Failed state similarity check!")
            return False

        if pr.history.block_count != pl.history.block_count:
            self._report_incongruency("Different weights!")
            return False

        if pl.addr != pr.addr:
            self._report_incongruency("Different addresses!")
            return False

        return True

from ..errors import AngrIncongruencyError
from angr.analyses import AnalysesHub
AnalysesHub.register_default('CongruencyCheck', CongruencyCheck)
Beispiel #9
0
             entry_edges,
             break_edges,
             continue_edges,
             loop_body_nodes,
             subg,
             tops[:])
        return me, [me] + alls

    def _parse_loops_from_graph(self, graph):
        """
        Return all Loop instances that can be extracted from a graph.

        :param graph:   The graph to analyze.

        :return:        A list of all the Loop instances that were found in the graph.
        """
        outtop = []
        outall = []
        for subg in networkx.strongly_connected_component_subgraphs(graph):
            if len(subg.nodes()) == 1:
                if len(list(subg.successors(list(subg.nodes())[0]))) == 0:
                    continue
            thisloop, allloops = self._parse_loop_graph(subg, graph)
            if thisloop is not None:
                outall += allloops
                outtop.append(thisloop)
        return outtop, outall

from angr.analyses import AnalysesHub
AnalysesHub.register_default('LoopFinder', LoopFinder)
Beispiel #10
0
    #

    def _process_block(self, state, block):  # pylint:disable=no-self-use
        """
        Scan through all statements and perform the following tasks:
        - Find stack pointers and the VEX temporary variable storing stack pointers
        - Selectively calculate VEX statements
        - Track memory loading and mark stack and global variables accordingly

        :param angr.Block block:
        :return:
        """

        l.debug('Processing block %#x.', block.addr)

        processor = self._ail_engine if isinstance(block, ailment.Block) else self._vex_engine
        processor.process(state, block=block, fail_fast=self._fail_fast)

        # readjusting sp at the end for blocks that end in a call
        if block.addr in self._node_to_cc:
            cc = self._node_to_cc[block.addr]
            if cc is not None:
                state.processor_state.sp_adjustment += cc.sp_delta
                state.processor_state.sp_adjusted = True
                l.debug('Adjusting stack pointer at end of block %#x with offset %+#x.',
                        block.addr, state.processor_state.sp_adjustment)


from angr.analyses import AnalysesHub
AnalysesHub.register_default('VariableRecoveryFast', VariableRecoveryFast)
Beispiel #11
0
        initial_state.options.discard(options.CGC_ZERO_FILL_UNCONSTRAINED_MEMORY)
        initial_state.options.update({options.TRACK_REGISTER_ACTIONS, options.TRACK_MEMORY_ACTIONS,
                                      options.TRACK_JMP_ACTIONS, options.TRACK_CONSTRAINT_ACTIONS})
        symbolic_stack = initial_state.se.BVS("symbolic_stack", project.arch.bits * stack_length)
        initial_state.memory.store(initial_state.regs.sp, symbolic_stack)
        if initial_state.arch.bp_offset != initial_state.arch.sp_offset:
            initial_state.regs.bp = initial_state.regs.sp + 20 * initial_state.arch.bytes
        initial_state.se._solver.timeout = 500  # only solve for half a second at most
        return initial_state

    @staticmethod
    def make_symbolic_state(project, reg_list, stack_length=80):
        """
        converts an input state into a state with symbolic registers
        :return: the symbolic state
        """
        input_state = Identifier.make_initial_state(project, stack_length)
        symbolic_state = input_state.copy()
        # overwrite all registers
        for reg in reg_list:
            symbolic_state.registers.store(reg, symbolic_state.se.BVS("sreg_" + reg + "-", project.arch.bits))
        # restore sp
        symbolic_state.regs.sp = input_state.regs.sp
        # restore bp
        symbolic_state.regs.bp = input_state.regs.bp
        return symbolic_state


from angr.analyses import AnalysesHub
AnalysesHub.register_default('Identifier', Identifier)
        else:
            return method

    def resolve_invoke(self, invoke_expr, method, container):
        # Generic method to resolve invoke
        # Given an invoke expression it figures out which "technique" should be applied
        invoke_type = str(type(invoke_expr))
        cls = self.project.loader.main_object.classes[method.class_name]

        if 'VirtualInvokeExpr' in invoke_type:
            targets = self.resolve_abstract_dispatch(cls, method)

        elif 'DynamicInvokeExpr' in invoke_type:
            targets = self.resolve_abstract_dispatch(cls, method)

        elif 'InterfaceInvokeExpr' in invoke_type:
            targets = self.resolve_abstract_dispatch(cls, method)

        elif 'SpecialInvokeExpr' in invoke_type:
            t = self.resolve_special_dispatch(method, container)
            targets = [t]

        elif 'StaticInvokeExpr' in invoke_type:
            targets = [method]

        return targets


from angr.analyses import AnalysesHub
AnalysesHub.register_default('SootClassHierarchy', SootClassHierarchy)
Beispiel #13
0
                    elif exprs[0].tag == 'Iex_Const':
                        dfg.add_edge(exprs[0], stmt_node)
                    putsnodes[stmt.offset] = stmt_node

                elif stmt.tag == 'Ist_Exit':
                    if exprs[0].tag == 'Iex_RdTmp':
                        dfg.add_edge(tmpsnodes[exprs[0].tmp], stmt_node)

                elif stmt.tag == 'Ist_Dirty':
                    tmpsnodes[stmt.tmp] = stmt_node
                elif stmt.tag == 'Ist_CAS':
                    tmpsnodes[stmt.oldLo] = stmt_node

                else:
                    for e in stmt.expressions:
                        if e.tag == 'Iex_RdTmp':
                            dfg.add_edge(tmpsnodes[e.tmp], stmt_node)
                        else:
                            dfg.add_edge(e, stmt_node)

            for vtx in list(dfg.nodes()):
                if dfg.degree(vtx) == 0:
                    dfg.remove_node(vtx)

            if dfg.size() > 0:
                dfgs[node.addr] = dfg
        return dfgs

from angr.analyses import AnalysesHub
AnalysesHub.register_default('DFG', DFG)
Beispiel #14
0
            opt_level=0  # disable the optimization in order to have
            # instruction-level analysis results
        )
        output_states = successors.all_successors

        state.concrete_states = [
            state for state in output_states if not state.ip.symbolic
        ]

        self._node_to_state[node.addr] = state

        self._node_iterations[node] += 1

        return True, state

    def _intra_analysis(self):
        pass

    def _post_analysis(self):
        # TODO: only re-assign variable names to those that are newly changed
        self.variable_manager.initialize_variable_names()

        for addr, state in self._node_to_state.items():
            self.variable_manager[self.function.addr].set_live_variables(
                addr, state.register_region, state.stack_region)


from angr.analyses import AnalysesHub

AnalysesHub.register_default('VariableRecovery', VariableRecovery)
Beispiel #15
0
                r = re.compile(ins_regex)
                regexes.add(r)

            for start_, data in self.project.loader.main_object.memory.backers():
                for regex in regexes:
                    # Match them!
                    for mo in regex.finditer(data):
                        position = mo.start() + start_
                        if position % arch.instruction_alignment == 0:
                            votes[(arch.name, arch.memory_endness)] += 1

            l.debug("%s %s hits %d times", arch.name, arch.memory_endness,
                    votes[(arch.name, arch.memory_endness)])

        arch_name, endianness, hits = sorted([(k[0], k[1], v) for k, v in votes.items()], key=lambda x: x[2], reverse=True)[0]

        if hits < self.cookiesize * 2:
        # this cannot possibly be code
            arch_name = "DATA"
            endianness = ""

        self.arch = arch_name
        self.endianness = endianness
        # Save it as well for debugging
        self.votes = votes

        l.debug("The architecture should be %s with %s", self.arch, self.endianness)

from angr.analyses import AnalysesHub
AnalysesHub.register_default('BoyScout', BoyScout)
Beispiel #16
0
            return stmt_idx

        if stmt_idx == DEFAULT_STATEMENT:
            vex_block = self.project.factory.block(block_addr).vex
            return len(vex_block.statements)

        raise AngrBackwardSlicingError('Unsupported statement ID "%s"' % stmt_idx)

    @staticmethod
    def _last_branching_statement(statements):
        """
        Search for the last branching exit, just like
        #   if (t12) { PUT(184) = 0xBADF00D:I64; exit-Boring }
        and then taint the temp variable inside if predicate
        """
        cmp_stmt_id = None
        cmp_tmp_id = None
        total_stmts = len(statements)
        statements = reversed(statements)
        for stmt_rev_idx, stmt in enumerate(statements):
            if isinstance(stmt, pyvex.IRStmt.Exit):
                stmt_idx = total_stmts - stmt_rev_idx - 1
                cmp_stmt_id = stmt_idx
                cmp_tmp_id = stmt.guard.tmp

        return cmp_stmt_id, cmp_tmp_id


from angr.analyses import AnalysesHub
AnalysesHub.register_default('BackwardSlice', BackwardSlice)
Beispiel #17
0
                cs = self.project.arch.capstone_thumb
            else:
                aligned_block_addr = block.addr
                cs = self.project.arch.capstone
            if block.bytestr is None:
                bytestr = ''.join(self.project.loader.memory.read_bytes(aligned_block_addr, block.size))
            else:
                bytestr = block.bytestr
            self.block_to_insn_addrs[block.addr] = []
            for cs_insn in cs.disasm(bytestr, block.addr):
                if cs_insn.address in self.kb.labels:
                    label = Label(cs_insn.address, self.kb.labels[cs_insn.address])
                    self.raw_result.append(label)
                    self.raw_result_map['labels'][label.addr] = label
                if cs_insn.address in self.kb.comments:
                    comment = Comment(cs_insn.address, self.kb.comments[cs_insn.address])
                    self.raw_result.append(comment)
                    self.raw_result_map['comments'][comment.addr] = comment
                instruction = Instruction(CapstoneInsn(cs_insn), bs)
                self.raw_result.append(instruction)
                self.raw_result_map['instructions'][instruction.addr] = instruction
                self.block_to_insn_addrs[block.addr].append(cs_insn.address)

    def render(self, formatting=None):
        if formatting is None: formatting = {}
        return '\n'.join(sum((x.render(formatting) for x in self.raw_result), []))


from angr.analyses import AnalysesHub
AnalysesHub.register_default('Disassembly', Disassembly)
Beispiel #18
0
            ailment.Stmt.Call: _handle_Call,
        }
        expr_handlers = {
            ailment.Stmt.Call: _handle_CallExpr,
        }

        block_walker = AILBlockWalker(stmt_handlers=stmt_handlers,
                                      expr_handlers=expr_handlers)

        def _graph_walker_handler(node):
            block_walker.walk(node)

        AILGraphWalker(ail_graph, _graph_walker_handler,
                       replace_nodes=False).walk()

        # add strings references that are not used in function calls
        self._process_strings(func,
                              proxi_nodes,
                              exclude_string_refs=string_refs)

        # add it to the graph
        graph.add_node(func_proxi_node)
        for pn in proxi_nodes:
            graph.add_edge(func_proxi_node, pn)

        return to_expand


from angr.analyses import AnalysesHub
AnalysesHub.register_default('Proximity', ProximityGraphAnalysis)
Beispiel #19
0
    context-sensitivity, and state keeping) only exist in CFGAccurate, which is when you want to use CFGAccurate
    instead.
    """
    def __init__(self, **kwargs):
        outdated_exception = "CFG is now an alias to CFGFast."
        outdated_message = "CFG is now an alias to CFGFast. Please switch to CFGAccurate if you need functionalities " \
                           "that only exist there. For most cases, your code should be fine by changing \"CFG(...)\" " \
                           "to \"CFGAccurate(...)\". Sorry for breaking your code with this giant change."

        cfgaccurate_params = {
            'context_sensitivity_level', 'avoid_runs', 'enable_function_hints',
            'call_depth', 'call_tracing_filter', 'initial_state', 'starts',
            'keep_state', 'enable_advanced_backward_slicing',
            'enable_symbolic_back_traversal', 'additional_edges',
            'no_construct'
        }

        # Sanity check to make sure the user only wants to use CFGFast

        for p in cfgaccurate_params:
            if kwargs.get(p, None) is not None:
                sys.stderr.write(outdated_message + "\n")
                raise OutdatedError(outdated_exception)

        # Now initializes CFGFast :-)
        CFGFast.__init__(self, **kwargs)


from angr.analyses import AnalysesHub
AnalysesHub.register_default('CFG', CFG)
Beispiel #20
0
            if data['jumpkind'] in ('Ijk_FakeRet', 'Ijk_Exit')
        ]
        graph.remove_edges_from(fakeret_edges)

        # Remove all "FakeRet" edges from cyclic_graph as well
        fakeret_edges = [
            (src, dst) for src, dst, data in reversed_cyclic_graph.edges(data=True)
            if data['jumpkind'] in ('Ijk_FakeRet', 'Ijk_Exit')
        ]
        reversed_cyclic_graph.remove_edges_from(fakeret_edges)

        # Perform a topological sort
        sorted_nodes = networkx.topological_sort(graph)

        nodes = [ n for n in sorted_nodes if graph.in_degree(n) > 1 and n.looping_times == 0 ]

        # Reorder nodes based on post-dominance relations
        nodes = sorted(nodes, key=cmp_to_key(lambda n1, n2: (
            1 if self._post_dominate(reversed_cyclic_graph, n1, n2)
            else (-1 if self._post_dominate(reversed_cyclic_graph, n2, n1) else 0)
        )))

        return [ (n.addr, n.looping_times) for n in nodes ]

from angr.analyses import AnalysesHub
AnalysesHub.register_default('Veritesting', Veritesting)

from ..errors import SimValueError, SimSolverModeError, SimError
from ..sim_options import BYPASS_VERITESTING_EXCEPTIONS
from claripy import ClaripyError
Beispiel #21
0
                    # Match them!
                    for mo in regex.finditer(data):
                        position = mo.start() + start_
                        if position % arch.instruction_alignment == 0:
                            votes[(arch.name, arch.memory_endness)] += 1

            l.debug("%s %s hits %d times", arch.name, arch.memory_endness,
                    votes[(arch.name, arch.memory_endness)])

        arch_name, endianness, hits = sorted([(k[0], k[1], v)
                                              for k, v in votes.iteritems()],
                                             key=lambda x: x[2],
                                             reverse=True)[0]

        if hits < self.cookiesize * 2:
            # this cannot possibly be code
            arch_name = "DATA"
            endianness = ""

        self.arch = arch_name
        self.endianness = endianness
        # Save it as well for debugging
        self.votes = votes

        l.debug("The architecture should be %s with %s", self.arch,
                self.endianness)


from angr.analyses import AnalysesHub
AnalysesHub.register_default('BoyScout', BoyScout)
Beispiel #22
0
                            edges_by_line.add((f, t))

            # Render block edges, to a reference buffer for tracking and output buffer for display
            edge_buf = ['' for _ in buf]
            ref_buf = ['' for _ in buf]
            edge_col = col('edge')
            for f, t in sorted(edges_by_line, key=lambda e: abs(e[0] - e[1])):
                add_edge_to_buffer(edge_buf,
                                   ref_buf,
                                   f,
                                   t,
                                   lambda s: ansi_color(s, edge_col),
                                   ascii_only=ascii_only)
                add_edge_to_buffer(ref_buf,
                                   ref_buf,
                                   f,
                                   t,
                                   ascii_only=ascii_only)
            max_edge_depth = max(map(len, ref_buf))

            # Justify edge and combine with disassembly
            for i, line in enumerate(buf):
                buf[i] = ' ' * (max_edge_depth -
                                len(ref_buf[i])) + edge_buf[i] + line

        return '\n'.join(buf)


from angr.analyses import AnalysesHub
AnalysesHub.register_default('Disassembly', Disassembly)
Beispiel #23
0
        :param angr.knowledge.Function function:
        :param networkx.MultiDiGraph data_graph:
        :return: None
        """

        register_pvs = set()
        for node in data_graph.nodes():
            if isinstance(node.variable, SimRegisterVariable) and \
                    node.variable.reg is not None and \
                    node.variable.reg < 40:
                register_pvs.add(node)

        for reg in register_pvs:
            # does it have a consumer?
            out_edges = data_graph.out_edges(reg, data=True)
            consumers = [ ]
            killers = [ ]
            for _, _, data in out_edges:
                if 'type' in data and data['type'] == 'kill':
                    killers.append(data)
                else:
                    consumers.append(data)

            if not consumers and killers:
                # we can remove the assignment!
                da = DeadAssignment(reg)
                self.dead_assignments.append(da)

from angr.analyses import AnalysesHub
AnalysesHub.register_default('BinaryOptimizer', BinaryOptimizer)
Beispiel #24
0
                    # there is a gap
                    size = next_addr - end_addr
                    if obj is None or isinstance(obj, cle.ExternObject):
                        bytes_ = None
                    else:
                        try:
                            _l.debug(
                                "Loading bytes from object %s, section %s, segmeng %s, addresss %#x.",
                                obj, section, segment, next_addr)
                            bytes_ = self.project.loader.memory.load(
                                next_addr, size)
                        except KeyError:
                            # The address does not exist
                            bytes_ = None
                    self.add_obj(
                        end_addr,
                        Unknown(end_addr,
                                size,
                                bytes_=bytes_,
                                object_=obj,
                                segment=segment,
                                section=section))
                addr = next_addr
            else:
                addr = max_addr


from angr.analyses import AnalysesHub
AnalysesHub.register_default('CFB', CFBlanket)
AnalysesHub.register_default('CFBlanket', CFBlanket)
Beispiel #25
0
        initial_state.memory.store(initial_state.regs.sp, symbolic_stack)
        if initial_state.arch.bp_offset != initial_state.arch.sp_offset:
            initial_state.regs.bp = initial_state.regs.sp + 20 * initial_state.arch.bytes
        initial_state.solver._solver.timeout = 500  # only solve for half a second at most
        return initial_state

    @staticmethod
    def make_symbolic_state(project, reg_list, stack_length=80):
        """
        converts an input state into a state with symbolic registers
        :return: the symbolic state
        """
        input_state = Identifier.make_initial_state(project, stack_length)
        symbolic_state = input_state.copy()
        # overwrite all registers
        for reg in reg_list:
            symbolic_state.registers.store(
                reg,
                symbolic_state.solver.BVS("sreg_" + reg + "-",
                                          project.arch.bits))
        # restore sp
        symbolic_state.regs.sp = input_state.regs.sp
        # restore bp
        symbolic_state.regs.bp = input_state.regs.bp
        return symbolic_state


from angr.analyses import AnalysesHub

AnalysesHub.register_default('Identifier', Identifier)
Beispiel #26
0
        :return:
        """

        l.debug('Processing block %#x.', block.addr)

        processor = self._ail_engine if isinstance(
            block, ailment.Block) else self._vex_engine
        processor.process(state, block=block, fail_fast=self._fail_fast)

        if self._track_sp and block.addr in self._node_to_cc:
            # readjusting sp at the end for blocks that end in a call
            cc = self._node_to_cc[block.addr]
            state.processor_state.sp_adjusted = False

            if cc is not None and cc.sp_delta is not None:
                state.processor_state.sp_adjustment += cc.sp_delta
                state.processor_state.sp_adjusted = True
                l.debug(
                    'Adjusting stack pointer at end of block %#x with offset %+#x.',
                    block.addr, state.processor_state.sp_adjustment)
            else:
                # make a guess
                # of course, this will fail miserably if the function called is not cdecl
                if self.project.arch.call_pushes_ret:
                    state.processor_state.sp_adjustment += self.project.arch.bytes
                    state.processor_state.sp_adjusted = True


from angr.analyses import AnalysesHub
AnalysesHub.register_default('VariableRecoveryFast', VariableRecoveryFast)
Beispiel #27
0
            raise AngrGirlScoutError('Please generate the call graph first.')

        f = open(filepath, "wb")

        for src, dst in graph.edges():
            f.write("0x%x\tDirectEdge\t0x%x\n" % (src, dst))

        f.close()

    def generate_code_cover(self):
        """
        Generate a list of all recovered basic blocks.
        """

        lst = [ ]
        for irsb_addr in self.cfg.nodes():
            if irsb_addr not in self._block_size:
                continue
            irsb_size = self._block_size[irsb_addr]
            lst.append((irsb_addr, irsb_size))

        lst = sorted(lst, key=lambda x: x[0])

        return lst

from angr.analyses import AnalysesHub
AnalysesHub.register_default('GirlScout', GirlScout)

from ..blade import Blade
from ..errors import AngrGirlScoutError
Beispiel #28
0
        # Case 2: a is a subset of the original address
        # Case 3: a is a superset of the original address

        live_defs[variable] = { code_loc }
        l.debug("XX CodeLoc %s kills variable %s", code_loc, variable)

    def _add_edge(self, s_a, s_b, **edge_labels):
        """
        Add an edge in the graph from `s_a` to statement `s_b`, where `s_a` and `s_b` are tuples of statements of the
        form (irsb_addr, stmt_idx).
        """
        # Is that edge already in the graph ?
        # If at least one is new, then we are not redoing the same path again
        if (s_a, s_b) not in self.graph.edges():
            self.graph.add_edge(s_a, s_b, **edge_labels)
            self._new = True
            l.info("New edge: %s --> %s", s_a, s_b)

    def get_all_nodes(self, simrun_addr, stmt_idx):
        """
        Get all DDG nodes matching the given basic block address and statement index.
        """
        nodes=[]
        for n in self.graph.nodes():
            if n.simrun_addr == simrun_addr and n.stmt_idx == stmt_idx:
                nodes.add(n)
        return nodes

from angr.analyses import AnalysesHub
AnalysesHub.register_default('VSA_DDG', VSA_DDG)
        todo = [addr]

        while todo:
            addr = todo.pop(0)
            seen.add(addr)
            irsb = self.project.factory.block(addr, opt_level=0).vex
            if irsb.jumpkind == 'Ijk_Ret':
                # got it!
                for stmt in reversed(irsb.statements):
                    if stmt.tag == 'Ist_IMark':
                        l.error("VERY strange return instruction at %#x...",
                                addr)
                        break
                    if stmt.tag == 'Ist_WrTmp':
                        if stmt.data.tag == 'Iex_Binop':
                            if stmt.data.op.startswith('Iop_Add'):
                                return stmt.data.args[
                                    1].con.value - self.project.arch.bytes
            elif irsb.jumpkind == 'Ijk_Call':
                if addr + irsb.size not in seen:
                    todo.append(addr + irsb.size)
            else:
                todo.extend(irsb.constant_jump_targets - seen)

        return None


from angr.analyses import AnalysesHub

AnalysesHub.register_default('CalleeCleanupFinder', CalleeCleanupFinder)
Beispiel #30
0
                        lambda g: entry_node in g.nodes(),
                        networkx.weakly_connected_component_subgraphs(subg)))

        me = Loop(entry_node, entry_edges, break_edges, continue_edges,
                  loop_body_nodes, subg, tops[:])
        return me, [me] + alls

    def _parse_loops_from_graph(self, graph):
        """
        Return all Loop instances that can be extracted from a graph.

        :param graph:   The graph to analyze.

        :return:        A list of all the Loop instances that were found in the graph.
        """
        outtop = []
        outall = []
        for subg in networkx.strongly_connected_component_subgraphs(graph):
            if len(subg.nodes()) == 1:
                if len(list(subg.successors(list(subg.nodes())[0]))) == 0:
                    continue
            thisloop, allloops = self._parse_loop_graph(subg, graph)
            if thisloop is not None:
                outall += allloops
                outtop.append(thisloop)
        return outtop, outall


from angr.analyses import AnalysesHub
AnalysesHub.register_default('LoopFinder', LoopFinder)
Beispiel #31
0
        self.results = {}
        try:
            lib = SIM_LIBRARIES[library]
        except KeyError:
            raise AngrValueError("No such library %s" % library)

        if binary is None:
            binary = self.project.loader.main_object

        for func in binary.symbols:
            if not func.is_function:
                continue

            if self.project.is_hooked(func.rebased_addr):
                l.debug("Skipping %s at %#x, already hooked", func.name, func.rebased_addr)
                continue

            if lib.has_implementation(func.name):
                proc = lib.get(func.name, self.project.arch)
                self.results[func.rebased_addr] = proc
                if self.project.is_hooked(func.rebased_addr):
                    l.debug("Skipping %s at %#x, already hooked", func.name, func.rebased_addr)
                else:
                    self.project.hook(func.rebased_addr, proc)
                    l.info("Hooked %s at %#x", func.name, func.rebased_addr)
            else:
                l.debug("Failed to hook %s at %#x", func.name, func.rebased_addr)

from angr.analyses import AnalysesHub
AnalysesHub.register_default('StaticHooker', StaticHooker)
Beispiel #32
0
                self.project.hook(addr, SIM_PROCEDURES['stubs']['ReturnUnconstrained'](cc=cc, display_name=name, library_name=libname, is_stub=True))

    def analyze(self, addr):
        seen = set()
        todo = [addr]

        while todo:
            addr = todo.pop(0)
            seen.add(addr)
            irsb = self.project.factory.block(addr, opt_level=0).vex
            if irsb.jumpkind == 'Ijk_Ret':
                # got it!
                for stmt in reversed(irsb.statements):
                    if stmt.tag == 'Ist_IMark':
                        l.error("VERY strange return instruction at %#x...", addr)
                        break
                    if stmt.tag == 'Ist_WrTmp':
                        if stmt.data.tag == 'Iex_Binop':
                            if stmt.data.op.startswith('Iop_Add'):
                                return stmt.data.args[1].con.value - self.project.arch.bytes
            elif irsb.jumpkind == 'Ijk_Call':
                if addr + irsb.size not in seen:
                    todo.append(addr + irsb.size)
            else:
                todo.extend(irsb.constant_jump_targets - seen)

        return None

from angr.analyses import AnalysesHub
AnalysesHub.register_default('CalleeCleanupFinder', CalleeCleanupFinder)
Beispiel #33
0
        self.results = {}
        try:
            lib = SIM_LIBRARIES[library]
        except KeyError:
            raise AngrValueError("No such library %s" % library)

        if binary is None:
            binary = self.project.loader.main_object

        for func in binary._symbol_cache.values():
            if not func.is_function:
                continue

            if self.project.is_hooked(func.rebased_addr):
                l.debug("Skipping %s at %#x, already hooked", func.name, func.rebased_addr)
                continue

            if lib.has_implementation(func.name):
                proc = lib.get(func.name, self.project.arch)
                self.results[func.rebased_addr] = proc
                if self.project.is_hooked(func.rebased_addr):
                    l.debug("Skipping %s at %#x, already hooked", func.name, func.rebased_addr)
                else:
                    self.project.hook(func.rebased_addr, proc)
                    l.info("Hooked %s at %#x", func.name, func.rebased_addr)
            else:
                l.debug("Failed to hook %s at %#x", func.name, func.rebased_addr)

from angr.analyses import AnalysesHub
AnalysesHub.register_default('StaticHooker', StaticHooker)
Beispiel #34
0
            # This is for testing
            successors = graph.graph.successors(node)
        else:
            # Real CFGNode!
            successors = graph.get_successors(node)

        return successors

    def _pd_post_process(self, cfg):
        """
        Take care of those loop headers/tails where we manually broke their
        connection to the next BBL
        """
        loop_back_edges = self._cfg.get_loop_back_edges()

        for b1, b2 in loop_back_edges:
            # The edge between b1 and b2 is manually broken
            # The post dominator of b1 should be b2 (or not?)

            successors = list(self._pd_graph_successors(cfg, b1))

            if len(successors) == 0:
                if b2 in self._post_dom:
                    self._post_dom.add_edge(b1, b2)
                else:
                    _l.debug("%s is not in post dominator dict.", b2)


from angr.analyses import AnalysesHub
AnalysesHub.register_default('CDG', CDG)
Beispiel #35
0
        f = open(filepath, "wb")

        for src, dst in graph.edges():
            f.write("0x%x\tDirectEdge\t0x%x\n" % (src, dst))

        f.close()

    def generate_code_cover(self):
        """
        Generate a list of all recovered basic blocks.
        """

        lst = []
        for irsb_addr in self.cfg.nodes():
            if irsb_addr not in self._block_size:
                continue
            irsb_size = self._block_size[irsb_addr]
            lst.append((irsb_addr, irsb_size))

        lst = sorted(lst, key=lambda x: x[0])

        return lst


from angr.analyses import AnalysesHub

AnalysesHub.register_default('GirlScout', GirlScout)

from ..blade import Blade
from ..errors import AngrGirlScoutError
Beispiel #36
0
        live_defs[variable] = {code_loc}
        l.debug("XX CodeLoc %s kills variable %s", code_loc, variable)

    def _add_edge(self, s_a, s_b, **edge_labels):
        """
        Add an edge in the graph from `s_a` to statement `s_b`, where `s_a` and `s_b` are tuples of statements of the
        form (irsb_addr, stmt_idx).
        """
        # Is that edge already in the graph ?
        # If at least one is new, then we are not redoing the same path again
        if (s_a, s_b) not in self.graph.edges():
            self.graph.add_edge(s_a, s_b, **edge_labels)
            self._new = True
            l.info("New edge: %s --> %s", s_a, s_b)

    def get_all_nodes(self, simrun_addr, stmt_idx):
        """
        Get all DDG nodes matching the given basic block address and statement index.
        """
        nodes = []
        for n in self.graph.nodes():
            if n.simrun_addr == simrun_addr and n.stmt_idx == stmt_idx:
                nodes.add(n)
        return nodes


from angr.analyses import AnalysesHub

AnalysesHub.register_default('VSA_DDG', VSA_DDG)
Beispiel #37
0
    - In the near future, this wrapper class will be removed completely, and CFG will be a simple alias to CFGFast.

    We expect most interfaces are the same between CFGFast and CFGAccurate. Apparently some functionalities (like
    context-sensitivity, and state keeping) only exist in CFGAccurate, which is when you want to use CFGAccurate
    instead.
    """
    def __init__(self, **kwargs):
        outdated_exception = "CFG is now an alias to CFGFast."
        outdated_message = "CFG is now an alias to CFGFast. Please switch to CFGAccurate if you need functionalities " \
                           "that only exist there. For most cases, your code should be fine by changing \"CFG(...)\" " \
                           "to \"CFGAccurate(...)\". Sorry for breaking your code with this giant change."

        cfgaccurate_params = {'context_sensitivity_level', 'avoid_runs', 'enable_function_hints', 'call_depth',
                              'call_tracing_filter', 'initial_state', 'starts', 'keep_state',
                              'enable_advanced_backward_slicing', 'enable_symbolic_back_traversal', 'additional_edges',
                              'no_construct'
                              }

        # Sanity check to make sure the user only wants to use CFGFast

        for p in cfgaccurate_params:
            if kwargs.get(p, None) is not None:
                sys.stderr.write(outdated_message + "\n")
                raise OutdatedError(outdated_exception)

        # Now initializes CFGFast :-)
        CFGFast.__init__(self, **kwargs)

from angr.analyses import AnalysesHub
AnalysesHub.register_default('CFG', CFG)