Exemple #1
0
    def __check_dont_skip_exception(dont_skip_exception):
        ''' Check if option is turned on and warn user '''
        if dont_skip_exception:
            clilog.info('''"dont_skip_exception" is turned on.
This might lead to wrong results!
If any exception occurs while analyzing a method, the process will be continued!'''
                        )
Exemple #2
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)
Exemple #3
0
 def log_n_read_superclasses(self):
     ''' Read and log the superclass information '''
     # reading superclasses is only supported for x86_64
     if is_x86_64():
         clilog.info('reading superclasses')
         self.superclass_dict = self.read_superclasses()
         log_info(
             Util.format_dict_as_table(self.superclass_dict, 'subclass',
                                       'base class'))
         clilog.info('')
Exemple #4
0
 def _read_superclasses(self, section_it):
     '''
     Helper method for `read_superclasses`.
     
     Parameters
     ----------
     section_it: iterator<tuple<int, string>>
         iterator over the sections where the superclass infos are stored
     '''
     segments = Segments.SEGMENTS_SUPERCLASS_INFOS
     clilog.info('reading from segments %s' % segments)
     superclazz_dict = AsmAnalyzerBase.__read_superclasses_from_sections(
         section_it)
     return superclazz_dict
Exemple #5
0
    def _print_info(self, start, cnt_filtered_messages, cnt_total_messages):
        ''' Print some statistics after the file has been analyzed '''
        duration = time.time() - start
        clilog.info("\nfiltered function calls: %d" % cnt_filtered_messages)
        clilog.info("total number of function calls read: %d" %
                    cnt_total_messages)

        clilog.info('took: %dm, %fs' % (duration / 60, duration % 60))
        clilog.info('done')
Exemple #6
0
def __load_filters(filtername_list, use_all_std_filters, arch):
    ''' 
    Load all standard filters as well as the user supplied ones.
    They are assumed to be in the directory where the `SecurityFilter` class is located.
    
    Parameters
    ----------
    filtername_list: list<str>
        list of filter names
    use_all_std_filters: boolean
        load all standard filters
    arch_str: string (see `Archs`)
        architecture    
    Returns
    -------
    installed_filters: list<SecurityFilter>
        all loaded filters
    []
        if no filter has been loaded
    '''
    flist = []
    if filtername_list:
        flist = []
        for f in filtername_list:
            base_fqn = SecurityFilter.__package__
            f = '%s.%s' % (base_fqn, Util.remove_py_extension(f))
            try:
                clazz = Util.class_for_fqn_mod_eq_class(f)
                fclass = clazz()
                flist.append(fclass)
            except (ImportError, ModuleNotSameClassNameException) as e:
                raise CLIError(str(e)), None, sys.exc_info()[2]
    if use_all_std_filters:
        # use all standard filters
        # do not take duplicates
        flist = list(
            set(
                map(lambda f: f(), SecurityFilters.security_filters(arch)) +
                flist))
    fnames = map(lambda f: f.name, flist)
    if not fnames:
        clilog.info('no filters enabled')
    else:
        clilog.info('installed filters: %s' % ', '.join(fnames))
    return flist
Exemple #7
0
def run_hopper(asmfile_iterator, superclass_dict=None):
    '''
    Use this method to run VizAsm from Hopper.
    
    Parameters
    ----------
    asmfile_iterator: iterator<tuple<int, string>>
        iterator over the lines
    superclass_dict: dict<ObjcClass, ObjcClass>, optional (default is {})
        a dictionary holding the base classes as values
    '''
    # run program
    asm_ana = AsmAnalyzerHopper(asmfile_iterator,
                                superclass_dict=superclass_dict)
    clilog.info(
        'Hopper reads the whole asm file into memory first and freezes while its doing this. So do not wonder!'
    )
    asm_ana.analyze()
Exemple #8
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!')
Exemple #9
0
def main(argv=None):  # IGNORE:C0111
    '''Command line options.'''

    if argv is None:
        argv = sys.argv
    else:
        sys.argv.extend(argv)

    program_version = "v%s" % __version__
    program_build_date = str(__updated__)
    program_version_message = '%%(prog)s %s (%s)' % (program_version,
                                                     program_build_date)
    program_license = '''
Copyright 2013 Nils Schmidt

This file is part of VizAsm.

VizAsm is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

VizAsm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with VizAsm.  If not, see <http://www.gnu.org/licenses/>.
'''

    try:
        # Setup argument parser
        action_parser = __create_action_parser()

        action_args, _ = action_parser.parse_known_args()

        # None value indicates to list filters but real value is arch
        list_filters_arch = action_args.list_filters
        if action_args.list_filters is not None:
            print SecurityFilters.format_available_filters(list_filters_arch)
        else:
            parser = __create_argument_parser(program_license,
                                              program_version_message)
            # process arguments
            args = parser.parse_args()

            arch_str = args.arch

            filters = init(arch_str, args.filters, args.all_filters,
                           args.verbosity, args.quiet, args.graph, args.vlog,
                           parser)
            # store settings
            asmfile = args.asmfile
            SETTINGS = {
                SETTINGS_ASM_FILEPATH: asmfile,
                SETTINGS_OUTPUT_FILEPATH: args.output,
                SETTINGS_GRAPH_FILEPATH: args.graph,
                SETTINGS_ARCHITECTURE: arch_str,
                SETTINGS_C_FUNC_HEURISTIC: args.c_func_heuristic,
                SETTINGS_CNT_SURROUNDING_LINES: args.surrounding_lines,
                SETTINGS_FILTERS: filters,
                SETTINGS_READ_ALL_METHODS: args.read_all_methods,
                SETTINGS_READ_SINGLE_PROCEDURE: args.read_single_procedure,
                SETTINGS_DONT_SKIP_EXCEPTION: args.dont_skip_exception
            }
            set_defaul_settings(SETTINGS)
            if DEBUG:
                print Util.pretty_format_dict(SETTINGS)

            # run program
            clilog.info('architecture: %s' % arch_str)
            clilog.info('analyzing file %s ...\n' % asmfile)

            asm_ana = AsmAnalyzerCli()
            asm_ana.analyze()
        return 0
    except KeyboardInterrupt:
        ### handle keyboard interrupt ###
        return 0
    except CLIError as e:
        clilog.exception(e)
    except Exception, e:
        log.exception(e)
        clilog.exception(e)
        return 2
Exemple #10
0
    def _read_meth_impl(self, asmline):
        ''' Read a line like e.g. "methImpl_AppDelegate_applicationDidFinishLaunching_"
        and detect the current class (AppDelegate) as well as the current method (applicationDidFinishLaunching_)
        
        If the `Cpu` does not fetch all of its arguments from stack, 
        self and _cmd will be set to the `Register`s defined by `CallingConventionsInterface`.
        
        Otherwise implement `store_self_cmd_for_stack_fetching_cpu` in your `Cpu`.
        
        Raises
        ------
        CpuCouldNotGetSelfref
            raised if the self reference could not be detected
        SelectorOverloadedException
            raised if the selector has more arguments than it needs
        SelectorUnderloadedException
            raised if the selector has less arguments than it needs 
            '''
        method_implementation, match = self.parse_util.parse_any_method_implementation(
            asmline)
        is_meth_impl, is_own_c_method_def, is_c_method, is_category = method_implementation

        method_impl = None
        if any([is_meth_impl, is_category]):
            method_impl = match
            selector = match.fst_selector()
            objc_class = match.msg_receiver

            if not self.fetches_all_arguments_from_stack():
                selfref_reg = self.destination_register()
                if selfref_reg is not None:
                    # store class for self reference
                    self.set_selfref_reg_value(objc_class)
                else:
                    raise CpuCouldNotGetSelfref(
                        self, selfref_reg, '%s.%s' % (objc_class, selector))
            else:
                # set self and _cmd for cpu fetching its args from stack
                self.objc_runtime.store_self_cmd_for_stack_fetching_cpu(
                    objc_class, selector)

            self.objc_runtime.create_and_store_method_selector_arguments(
                selector)
            # set method to use it in _try_log_reading_meth_impl
            self.method = method_impl

            # log method
            self._try_log_reading_meth_impl(selector)

            self.set_method_selector_reg_value(selector)

        elif is_c_method or is_own_c_method_def:
            log.debug('reading method: %s', match)
            method_impl = match
            self.create_and_store_c_func_arguments(method_impl)

        if any(method_implementation):
            clilog.info('reading method: %s', method_impl)
            # set method and sender for `MethodCall`
            self.method = method_impl
            self.method_call.sender = method_impl