Ejemplo n.º 1
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)
Ejemplo n.º 2
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
Ejemplo n.º 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('')
Ejemplo n.º 4
0
 def is_method_implementation(asmline):
     ''' Indicates if a line is a `CategoryClass` or method implementation.
     See `AsmRegEx.RE_CATEGORY` and `AsmRegEx.RE_METH_IMPL`.
     '''
     funcs = [
         AsmRegEx.compiled_vre(AsmRegEx.RE_CATEGORY),
         AsmRegEx.compiled_vre(AsmRegEx.RE_METH_IMPL)
     ]
     return Util.get_fst_not_none(
         imap(lambda f: getattr(f, 'search')(asmline), funcs))
Ejemplo n.º 5
0
 def _check(iterable, func, steps = None, cur_steps = 0):
     if one_func_matches(iterable):
         return True 
     if Util.is_iterable_no_string(iterable):
         for arg in iterable:
             # got given number of steps into iterable structure 
             if steps is None or (steps is not None and cur_steps < steps): 
                 if _check(arg, func, steps, cur_steps + 1):
                     return True
             if one_func_matches(arg):
                 return True
     return one_func_matches(iterable)
Ejemplo n.º 6
0
 def get_fst_match(asmline, functionlist):
     '''
     Get the first function (lazy) that matches on the given input argument.
      
     Parameters
     ----------
     asmline: string
         the argument to apply on the functions
     functionlist: list<functionrefs>
         the functions on which to apply the input argument 
     '''
     return Util.get_fst_not_none(imap(lambda x: x(asmline), functionlist))
Ejemplo n.º 7
0
 def create_and_store_remaining_method_selector_arguments(
         self, start_addr, method_selector):
     '''
     Create and store the remaining arguments for the `method_selector`.
     There will be as many arguments created as the `Selector` still needs
     and stored as `StackVar`.
     
     Parameters
     ----------
     start_addr: int
         the suffix for the first `StackVar` argument (e.g. arg_4) 
     method_selector: Selector
         the `Selector` describing the method that is currently being read by the `Cpu`
     
     Raises
     ------
     SelectorOverloadedException
         if selector has more arguments than it needs
     '''
     cpu = self.cpu
     if method_selector is not None:
         STACKVAR_PREFIX = 'arg'
         addr = start_addr
         start = method_selector.cnt_has_arguments() + 1
         for i in range(start, method_selector.cnt_needs_arguments() + 1):
             method_sel_arg = ObjectiveCRuntime.create_method_selector_arg(
                 i)
             # cut off the 0x prefix and use upper case for rest of address
             stackvar_name = '%s_%s' % (
                 STACKVAR_PREFIX, Util.hex_string_without_0x(addr).upper())
             # save argument as StackVar
             stackvar = StackVar(stackvar_name)
             cpu.memory.registers.set_value_for_register_ann_method_ead(
                 stackvar, method_sel_arg)
             method_selector.add_argument(method_sel_arg)
             log.debug('method_selector arg %s = %s', method_sel_arg,
                       stackvar)
             addr += cpu.pointer_size()
Ejemplo n.º 8
0
 def parse_register(self, register):
     '''
     Parse a register.
     
     Parameters
     ----------
     register: string
     
     Returns
     --------
     register: `register_type`
         the register wrapped in `register_type` 
     None
         if regular expression did not classify as register  
     '''
     register_match = regexp.compiled_vre(
         regexp.RE_REGISTER).search(register)
     if register_match is not None:
         ds_reg = register_match.group(regexp.RE_REGISTER_GR_DS_REG)
         reg = register_match.group(regexp.RE_REGISTER_GR_REG)
         qword_reg = register_match.group(regexp.RE_REGISTER_GR_QWORD_REG)
         return self.register_class(
             Util.filter_not_none((ds_reg, reg, qword_reg))[0])
     return None
Ejemplo n.º 9
0
def ut_search_string(string,
                     ut_search_string,
                     search_substring=False,
                     ignore_case=True):
    '''
    Check if `string` is equal to `ut_search_string` or
    if `search_substring` `string` contains `search_substring`.
    
    Parameters
    ----------
    string: string
    ut_search_string: string
    search_substring: bool (default is False)
        If True match even if just substring found (`find`).
        Otherwise check for exact equality via `==`.    
    ignore_case: bool
        ignore case if enabled
    '''
    if ignore_case:
        return Util.ignore_case_find(
            string, ut_search_string) if search_substring else str(
                string).upper() == ut_search_string.upper()
    return string.find(search_substring) != -1 if search_substring else str(
        string) == ut_search_string
Ejemplo n.º 10
0
 def parse_stack_access(self, asmline):
     ''' Parse a stack access like e.g. "[sp, #0x8]" or "[r7, #0x8]" or "[sp] or "[sp], #0x4".
     The latter leads to an address of 0x0.
     
     Returns
     -------
     tuple<string, string>
         Return the stack pointer name as well as the stack address as hex string.
     '''
     cpu = self.cpu
     frame_reg, stack_reg = cpu.stack_pointer_register(
     ).register, cpu.frame_pointer_register().register
     stack_access_match = regexp.compiled_re_stack(
         frame_reg, stack_reg).search(asmline)
     if stack_access_match is not None:
         stack_addr = Util.get_fst_not_none(
             (stack_access_match.group(regexp.RE_STACK_GR_ADDRESS),
              stack_access_match.group(regexp.RE_STACK_GR_OFFSET)))
         stack_pointer_name = stack_access_match.group(
             regexp.RE_STACK_GR_STACK_POINTER)
         if stack_addr is None:
             stack_addr = '0x0'
         return stack_pointer_name, stack_addr
     return None
Ejemplo n.º 11
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
Ejemplo n.º 12
0
 def __repr__(self):
     return '%s(%s)' % (self.__class__.__name__, Util.pretty_format_dict(self.stack, True))
Ejemplo n.º 13
0
 def __repr__(self):
     return '%s: %s\%s' % (self.__class__.__name__, repr(self.ivar_lookup),
                           Util.pretty_format_dict(self.superclass_dict,
                                                   True))
Ejemplo n.º 14
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)
Ejemplo n.º 15
0
 def __str__(self):
     return '%s: %s' % (self.__class__.__name__, Util.pretty_format_dict(self.stack))
Ejemplo n.º 16
0
 def node_color_green(self):
     return Util.random_rgb_val()
Ejemplo n.º 17
0
 def node_color_blue(self):
     return Util.random_rgb_val()
Ejemplo n.º 18
0
 def next_regs_for_spret(self, reg_list):
     ''' Same as `next_reg_for_spret`, but do it for the whole list of `Register` '''
     return Util.filter_not_none(
         (self.next_reg_for_spret(reg) for reg in reg_list))