def _get_new_kb_with_cfgs_and_functions(project, kb): new_kb = KnowledgeBase(project) new_kb.cfgs = kb.cfgs.copy() new_kb.functions = kb.functions.copy() new_kb.labels = kb.labels.copy() new_kb.resolved_indirect_jumps = kb.resolved_indirect_jumps.copy() new_kb.unresolved_indirect_jumps = kb.unresolved_indirect_jumps.copy() return new_kb
def function_check(self, function): """ Check if the specific function returns any value outside of the predefined scope. :param angr.knowledge.Function function: The function to check. :return: True if the policy is respected, False otherwise. :rtype: bool """ if function.addr != self.function_address: # skip this function raise PolicySkipFunctionNotice() # the temporary knowledge base tmp_kb = KnowledgeBase(self.project, self.project.loader.main_bin) cfg = self.project.analyses.CFGAccurate( starts=(function.addr, ), keep_state=True, call_depth=0, kb=tmp_kb, ) # generate the data dependence graph on the function dep_graph = self.project.analyses.DataDependencyAnalysis(cfg, kb=tmp_kb) # perform a return value analysis ret_val = self.project.analyses.ReturnValueAnalysis( function, dep_graph) result = True # check the return values for r in ret_val.return_values: # type: ConstantReturnValue if r.value not in self.return_values: l.warning( 'Policy violation: return value %s not found in predefined set of return values specified by ' 'the policy.', r.value) cr = CheckResult(self, False, function=function, unexpected_value=r.value) self._add_result(cr) result = False if self._failfast: return result if result is True: cr = CheckResult(self, True, function=function) self._add_result(cr) return True
def _analyze(self): # Generate a CFG of the current function with the base graph cfg = self.project.analyses.CFGAccurate( kb=KnowledgeBase(self.project, self.project.loader.main_object), starts=(self.function.addr, ), keep_state=True, base_graph=self.function.graph, iropt_level=0, ) self.ddg = self.project.analyses.DDG(cfg)
def function_check(self, function): if isinstance(function, (int, long)): function = self.kb.functions.get(function, None) if function is None: # the function is not found raise FunctionNotFoundError( 'The function specified is not found. Please make sure the function you ' 'specified is correct, and the correct knowledge base with function ' 'information is passed in.') # create a temporary knowledgebase so that the new CFG does not overwrite the existing global CFG tmp_kb = KnowledgeBase(self.project, self.kb.obj) # create an accurate control flow graph for this function cfg = self.project.analyses.CFGAccurate(kb=tmp_kb, base_graph=function) import ipdb ipdb.set_trace()
def function_check(self, function): """ :param angr.knowledge.Function function: The function to be checked against. :return: True if the policy is respected, False otherwise. :rtype: bool """ if function.returning is False: l.warning('Function %#x does not return.', function.addr) return True # find all places where the function is called cfg = self._fast_cfg function_node = cfg.get_any_node(function.addr) if not function_node: # the function is not found l.warning('Function %#x is not found in the control flow graph.', function.addr) return True # find all predecessors, which are callers to this function predecessors = cfg.get_all_predecessors(function_node) if not predecessors: # the function is not called from anywhere, or we cannot resolve the caller l.warning( 'Function %#x is not called by any node throughout the control flow graph.', function.addr) return True # for each function that the caller is in, generate a data dependency graph for pred in predecessors: # type: angr.analyses.cfg_node.CFGNode func_addr = pred.function_address if func_addr is None: continue caller_func = cfg.functions.get( func_addr, None) # type: angr.knowledge.Function if caller_func is None: continue tmp_kb = KnowledgeBase(self.project, self.project.loader.main_bin) caller_func_cfg = self.project.analyses.CFGAccurate( call_depth=0, base_graph=caller_func.graph, keep_state=True, ) dep_graph = self.project.analyses.DataDependencyAnalysis( caller_func_cfg, kb=tmp_kb, ) # analyze on dep_graph ret_val_reg = ReturnValueAnalysis.RETURN_VALUE_REGISTERS[ self.project.arch.name] ret_val_reg_offset, ret_val_reg_size = self.project.arch.registers[ ret_val_reg] ret_var = SimRegisterVariable(ret_val_reg_offset, ret_val_reg_size * 8) # return site return_site_addr = pred.addr + pred.size ret_var_def = ProgramVariable(ret_var, CodeLocation(return_site_addr, -1)) # TODO: add return value nodes in DataDependencyAnalysis consumers = dep_graph.find_consumers(ret_var_def) if not consumers: l.warning( 'Return value of function %#x is not checked at calling site %#x.', function.addr, pred.addr) return False return True