Пример #1
0
    def _analyze(self, methods_it):
        ''' 
        Analyze the assembler file.
        
        Parameters
        ----------
        methods_it: iterator<dict<int, string>>
        '''
        start = time.time()
        AsmAnalyzerBase.__check_dont_skip_exception(
            setting_for_key(SETTINGS_DONT_SKIP_EXCEPTION))

        output_filepath = setting_for_key(SETTINGS_OUTPUT_FILEPATH)
        graph_filepath = setting_for_key(SETTINGS_GRAPH_FILEPATH)
        if output_filepath:
            clilog.info('writing messages to %s' % abspath(output_filepath))
        if graph_filepath is not None:
            clilog.info('writing graph to %s\n' % abspath(graph_filepath))

        cnt_filtered_messages = cnt_total_messages = 0

        # base classes cannot be resolved
        if not self.superclass_dict:
            log.critical(
                'No information about superclasses given/read!\n Messages to super cannot be resolved! %s will be assumed as superclass!'
                % ObjcClass.nsobject)

        # create cpu
        cpu = None
        if is_x86():
            cpu = Cpu_x86(self.superclass_dict)
        elif is_x86_64():
            cpu = Cpu_x86_64(self.superclass_dict)
        elif is_arm():
            cpu = Cpu_arm(self.superclass_dict)

        try:
            for method_dict in methods_it:
                try:
                    (cnt1, cnt2) = self.__analyze_inner(cpu, method_dict)
                    cnt_total_messages += cnt1
                    cnt_filtered_messages += cnt2
                except (CpuException, RuntimeError) as e:
                    log.exception(e)
                finally:
                    # reset cpu to read next method implementation
                    cpu.reset()
        except Exception:
            raise
        finally:
            if self.filtering_enabled():
                self.__write_filter_results()
            # close file
            if self.output_file is not None:
                self.output_file.flush()
                self.output_file.close()
            GraphUtil.write_gexf(self.graph, graph_filepath)

            # print infos
            self._print_info(start, cnt_filtered_messages, cnt_total_messages)
Пример #2
0
    def __init__(self, superclass_dict=None):
        if superclass_dict is None:
            superclass_dict = {}
        self._superclass_dict = superclass_dict
        output_file = None
        output_filepath = setting_for_key(SETTINGS_OUTPUT_FILEPATH)
        if output_filepath:
            output_file = open(output_filepath, 'w')
        self._output_file = output_file
        self._graph = Graph()

        # do not forget to set `MethodCall` later
        filters = setting_for_key(SETTINGS_FILTERS)
        self._security_analyzer = SecurityAnalyzer(methodcall=None,
                                                   filters=filters)
Пример #3
0
 def analyze(self):
     '''
     Analyze the assembler file.
     '''
     methods_it = None
     selected_method_only = setting_for_key(SETTINGS_READ_SINGLE_PROCEDURE)
     if selected_method_only:
         methods_it = AsmReader.single_method_it(self.asmline_list)
     else:
         read_all_methods = setting_for_key(SETTINGS_READ_ALL_METHODS)
         self.log_n_read_superclasses()
         section_it = AsmReader.sections_it(self.asmline_list,
                                            [SEGMENT_TEXT])
         methods_it = AsmReader.methods_it(
             section_it, read_all_procedures=read_all_methods)
     self._analyze(methods_it)
Пример #4
0
    def create_gephi_attr_dicts(self, asm_lines, filtered_methodcall = None):    
        '''
        Construct the attribute dictionary describing the graph style.
        Use the created dictionaries with the `add_to_graph` method.
        
        The attributes are:
        Calling Method:
            assembler code
            the method calls (filtered or not)
        Method:
            line number in the asm file
            address in the asm file
            surrounding lines
            
        Parameters
        ----------
        asm_lines: string
            the assembler method as string
        filtered_methodcall: MethodCall, optional (default is None)
            the filtered `MethodCall`
        
        Returns
        -------
        methodcall_sender_attr_dict: dict
        methodcall_calls_attr_list_dict: dict
        '''
        method_lines_list = [str(methodcallitem) for methodcallitem in self.calls]

        if filtered_methodcall is None:
            filtered_methodcall = self
            
        # construct calls attribute dictionary
        methodcall_calls_attr_list_dict = []
        cnt_surrounding_lines = setting_for_key(SETTINGS_CNT_SURROUNDING_LINES)
        if cnt_surrounding_lines >= 0:
            for i, methodcallitem in enumerate(filtered_methodcall.calls):
                # construct leading and trailing lines
                # index of the current line (filtered `MethodCall`) in the list of method lines 
                current_line = str(filtered_methodcall.calls[i].call)
                linenr = methodcallitem.linenr
                idx_line = self.idx_methodcallitem(linenr)
                # idx_line = method_lines_list.index(current_line)
                lines_before, lines_after = Util.surrounding_elements_from_list(method_lines_list, idx_line, cnt_surrounding_lines)
                
                surrounding_lines = NodeAttributes.NPATTERN_SURROUND_LINES % (Util.strlist_to_str(lines_before), current_line, Util.strlist_to_str(lines_after))
                methodcall_attr_dict = {NodeAttributes.NATTR_METHOD_SURROUNDING_LINES % cnt_surrounding_lines : surrounding_lines}
                
                methodcall_attr_dict.update(methodcallitem.get_gexf_viz_attr_dict())
                
                methodcall_calls_attr_list_dict.append(methodcall_attr_dict)
        
        # add method signature to list of method lines 
        method_lines_list.insert(0, filtered_methodcall.format_head() + ":\n")
        
        # construct sender attribute dictionary
        method_lines = Util.strlist_to_str(method_lines_list)
        methodcall_sender_attr_dict = {NodeAttributes.NATTR_METHOD : method_lines, NodeAttributes.NATTR_ASM_CODE : asm_lines}
        
        return (methodcall_sender_attr_dict, methodcall_calls_attr_list_dict)
Пример #5
0
 def filter_method_call(self, function):
     has_format_string = util.mc_has_format_string(function)
     # only check for exploitable sql statement if the argument of the c function are available
     if setting_for_key(SETTINGS_C_FUNC_HEURISTIC):
         is_sqlite_func = util.mc_c_function_has_any_name(
             function, ['sqlite3_prepare'], search_substring=True)
         return is_sqlite_func and has_format_string
     # check for any sqlite3 call
     is_sqlite_func = util.mc_c_function_has_any_name(function, ['sqlite3'],
                                                      search_substring=True)
     return is_sqlite_func
Пример #6
0
    def __init__(self,
                 assignment_matching_system,
                 parse_util,
                 _register_class,
                 superclass_dict=None,
                 objc_runtime=None):
        self.__assignment_matching_system = assignment_matching_system
        self._parse_util = parse_util
        self._register_class = _register_class

        self._memory = Memory(self)
        # use standard objective-c runtime if nothing else given
        if objc_runtime is None:
            objc_runtime = ObjectiveCRuntime(self, superclass_dict)
        self._objc_runtime = objc_runtime

        self._c_func_heuristic = setting_for_key(SETTINGS_C_FUNC_HEURISTIC)
        self.__init_resetable_stuff()
Пример #7
0
 def __init__(self, asmline_list, superclass_dict=None):
     AsmAnalyzerBase.__init__(self, superclass_dict)
     self.__asmline_list = asmline_list
     selected_method_only = setting_for_key(SETTINGS_READ_SINGLE_PROCEDURE)
     if selected_method_only:
         clilog.info('Only analyzing the selected lines!')
Пример #8
0
    def __analyze_inner(self, cpu, method_dict):
        cnt_filtered_messages = cnt_total_messages = 0
        dont_skip_exception = setting_for_key(SETTINGS_DONT_SKIP_EXCEPTION)
        hopper_annotater = hopanno
        hopanno.reset()
        for linenr, line in sorted(method_dict.items()):
            try:
                cpu.read_line(line, linenr)
                if hopper_annotater is not None and hopper_annotater.cur_meth_impl_start is None and cpu.address is not None:
                    hopper_annotater.cur_meth_impl_start = cpu.address
            except (CpuException, RuntimeError) as e:
                # annotate exception
                hopanno.annotate(cpu.address, (HOPANNO_EXCEPTION_STR +
                                               (' <- %s: %s ...' %
                                                (e.__class__.__name__, str(e)))
                                               )[:HOPPER_EXCEPTION_LENGTH])
                log.exception(e)
                if not dont_skip_exception:
                    raise
        methodcall = cpu.get_method_call()
        cnt_total_messages += len(methodcall.calls)

        sa = self.security_analyzer
        sa.set_methodcall(methodcall)

        filtered_methodcall = methodcall

        # build a list of method lines
        if self.filtering_enabled():
            # apply filters
            # do this after building the list of method lines,
            # because the lines before and after refer to the unfiltered lines
            filtered_methodcall = sa.apply_filters()

        # method as assembler code (string)
        lines_str_list = list(Util.sorted_dict_values_it(method_dict))
        asm_lines = Util.strlist_to_str(lines_str_list)

        # create attribute dictionaries
        methodcall_sender_attr_dict, methodcall_calls_attr_list_dict = methodcall.create_gephi_attr_dicts(
            asm_lines, filtered_methodcall)

        # add to graph
        if self.filtering_enabled():
            sa.add_to_graph(self.graph,
                            methodcall_sender_attr_dict,
                            methodcall_calls_attr_list_dict,
                            sender_methodcall_edge_attr_dict=None)
        else:
            methodcall_sender_attr_dict.update(GraphUtil.viz_dict(size=50.0))
            methodcall.add_to_graph(self.graph,
                                    methodcall_sender_attr_dict,
                                    methodcall_calls_attr_list_dict,
                                    sender_methodcall_edge_attr_dict=None)

        cnt_filtered_messages += len(filtered_methodcall.calls)

        # write `MethodCall` to file
        if not self.filtering_enabled():
            self.__write_methodcall(filtered_methodcall)

        # annotate hopper
        if hopper_annotater is not None:
            hopper_annotater.annotate_from_methodcall(filtered_methodcall)
            hopper_annotater.reset()

        return (cnt_total_messages, cnt_filtered_messages)
Пример #9
0
 def __init__(self, cpu, parse_util):
     self._cpu = cpu
     self._parse_util = parse_util 
     self.__init_defaults()
     self.clear_usage_since_last_call()
     self._c_func_heuristic = setting_for_key(SETTINGS_C_FUNC_HEURISTIC)