Ejemplo n.º 1
0
 def taintAnalysis(self, item):
     func = item.func
     if func.ircfg is None:
         func.ira = BinaryAnalysis.iraType(func.cfg.loc_db)
         func.ircfg = func.ira.new_ircfg_from_asmcfg(func.cfg)
         func.defUse = DiGraphDefUse(ReachingDefinitions(func.ircfg))
     current_block = func.ircfg.get_block(item.block.loc_key)
     index = 0
     dstArg = None
     for index, assignblk in enumerate(current_block):
         if assignblk.instr.offset == item.address:
             for dst, src in assignblk.items():
                 dstArg = dst
             break
     queue = [AssignblkNode(item.block.loc_key, index, dstArg)]
     currentPoint = 0
     endPoint = 0
     while currentPoint <= endPoint:
         node = queue[currentPoint]
         currentPoint += 1
         assign = func.ircfg.blocks[node.label][node.index]
         self.focusAddress(assign.instr.offset, False)
         for node2 in func.defUse.successors(node):
             endPoint += 1
             queue.append(node2)
Ejemplo n.º 2
0
 def _add_2_control_vars(self, primary_loc_keys, affected_lines, merging_var, done, head_vars):
     # involve cff loops containing compiler "optimization" introducing 2 control variables(
     # range(0,x,1) and range(0,x,1*y)); there are multiple due to various compiler anomalies, but
     # only one from affected_irdsts
     found = False
     for disp_loc, last_cff_locs in self.analyses.rev_back_edges.items():
         if disp_loc not in primary_loc_keys:
             continue
         for last_cff_loc in last_cff_locs:
             preds = self.asmcfg.predecessors(last_cff_loc)
             succs = self.asmcfg.successors(last_cff_loc)
             if not len(succs) > 1 and len(preds) == 1 and last_cff_loc not in affected_lines:
                 last_cff_loc = preds[0]
                 succs = self.asmcfg.successors(last_cff_loc)
             if last_cff_loc not in primary_loc_keys:
                 if len(succs) > 1:
                     primary_loc_keys.add(last_cff_loc)
                     opti_node = AssignblkNode(last_cff_loc, len(self.ircfg.blocks[last_cff_loc].assignblks) - 1,
                                               self.ir_arch.IRDst)
                     self._process_affected_irdsts({opti_node}, affected_lines, primary_loc_keys, merging_var, done,
                                                   head_vars)
                     if last_cff_loc in primary_loc_keys:
                         # otherwise last_cff_loc couldn't be determined and was removed from primaries
                         found = True
                 if last_cff_loc in affected_lines:
                     found = True
             else:
                 found = True
     if not found:
         raise RuntimeError("There must be a back-edge")
Ejemplo n.º 3
0
 def forwardTaint(self, item):
     queue = [AssignblkNode(item.block.loc_key, item.index, item.dst)]
     currentPoint = 0
     endPoint = 1
     while currentPoint < endPoint:
         node = queue[currentPoint]
         self.selectLine(node.label, node.index, node.var)
         currentPoint += 1
         for node2 in self.defUse.successors(node):
             queue.append(node2)
             endPoint += 1
Ejemplo n.º 4
0
 def _process_assignment(self, ir_block, ind, dst):
     assignblk_node = AssignblkNode(ir_block.loc_key, ind, dst)
     # loop id 0 is the default
     logger.debug("Processing %s" %
                  hex(self.asmcfg.loc_db.get_location_offset(ir_block.loc_key) or 0))
     local_affected_lines = {}
     affected_irdsts, possible_nodes = self._get_affected_ir_destinations(assignblk_node, local_affected_lines)
     result = False
     for node in self.asmcfg.walk_breadth_first_forward(LocKey(0)):
         if node in possible_nodes:
             filtered_irdsts = self._filter_sequential_loc_keys(node, affected_irdsts)
             affected_lines = {}
             result |= self._create_flattening_loop(node, filtered_irdsts, affected_lines)
     return result
Ejemplo n.º 5
0
 def backwardTaint(self, item):
     arg = item.args[self.lastClickIndex]
     line = self.findAssign(arg)
     self.selectionModel().select(self.model.indexFromItem(line), QItemSelectionModel.Select)
     queue = [AssignblkNode(line.block.loc_key, line.index, line.dst)]
     currentPoint = 0
     endPoint = 1
     while currentPoint < endPoint:
         node = queue[currentPoint]
         if currentPoint != 0:
             self.selectLine(node.label, node.index, node.var)
         currentPoint += 1
         for node2 in self.defUse.predecessors(node):
             queue.append(node2)
             endPoint += 1
Ejemplo n.º 6
0
    def _track_exprs(self, state, assignblk, line_nb):
        """Track pending expression in an assignblock"""
        if self.incorrect:
            return
        future_pending = {}
        node_resolved = set()
        for dst, src in assignblk.items():
            assignblk_node = AssignblkNode(state.loc_key, line_nb, dst)
            # Only track pending
            if dst not in state.pending:
                if type(src) in [ExprId, ExprOp, ExprCompose] and any(
                        src in i for i in state.pending):
                    if assignblk_node in self.defuse_edges:
                        # targets function arguments such as lea eax, var; push eax since constant propagation doesn't
                        # work correctly in miasm; https://github.com/cea-sec/miasm/issues/1197;
                        # https://github.com/cea-sec/miasm/issues/1218; https://github.com/cea-sec/miasm/issues/1259;
                        # TODO when constant propagation is fixed, rework this; elaborate on 1259
                        for assignblk_node in self.defuse_edges[
                                assignblk_node]:
                            if is_local_variable(assignblk_node.var, self.ir, self.mn) \
                                    and assignblk_node not in self.defuse_edges:
                                break
                        else:
                            continue
                    elif not is_local_variable(dst, self.ir, self.mn):
                        continue

                    if is_push_param(self.recognizer, assignblk_node.label,
                                     assignblk_node.index):
                        # prevents FPs in weird code such as push    [ebp+var_18]; call ...; add     esp, 4
                        # where [ebp+var_18] is not param and it's just pushed
                        self.incorrect = True
                        return
                continue
            # Track IRDst in implicit mode only
            if dst == self._ircfg.IRDst and not self._implicit:
                continue
            assert dst not in node_resolved
            node_resolved.add(dst)
            dependencies = self._follow_apply_cb(src)

            state.link_element(dst, line_nb)
            state.link_dependencies(dst, line_nb, dependencies, future_pending)

        # Update pending nodes
        state.remove_pendings(node_resolved)
        state.add_pendings(future_pending)
Ejemplo n.º 7
0
    def _recognize(self, max_loop_num):
        symb_engine = SymbolicExecutionEngine(self.ir_arch, regs.regs_init)
        todo = [(LocKey(0), symb_engine.get_state())]
        done_loc = set()
        if not max_loop_num:
            max_loop_num = float('inf')
        found_loops_num = 0
        while todo:
            loc_key, symb_state = todo.pop()
            if loc_key in done_loc or loc_key not in self.ircfg.blocks:
                continue
            done_loc.add(loc_key)
            ir_block = self.ircfg.blocks[loc_key]
            symb_engine.set_state(symb_state)
            for ind, assignblk in enumerate(ir_block.assignblks):
                for dst, src in assignblk.items():
                    if max_loop_num < found_loops_num:
                        return
                    if src.is_int() and int(src) in self.func_addresses:
                        assignblk_node = AssignblkNode(ir_block.loc_key, ind,
                                                       dst)
                        # no uses
                        if assignblk_node not in self.analyses.defuse_edges or not \
                                self.analyses.defuse_edges[assignblk_node]:
                            # possible virtual table initialization
                            self.possible_merge_funcs.add(
                                (int(src), frozenset(), loc_key))
                    elif src.is_op("call_func_stack"):
                        self._process_call(src, dst, symb_engine, assignblk,
                                           loc_key)
                    elif (expr_simp(src).is_int() and not is_bad_expr(dst)) \
                            or (ir_block.loc_key == LocKey(0) and dst == src and
                                (not self._merging_var_candidates or dst in self._merging_var_candidates)):
                        if self._process_assignment(ir_block, ind, dst):
                            self._merging_var_candidates = None
                            found_loops_num += 1
                symb_engine.eval_updt_assignblk(assignblk)

            for succ in self.ircfg.successors(loc_key):
                todo.append((succ, symb_engine.get_state()))