Пример #1
0
    def methods_it(file_iterator, read_all_procedures=False):
        '''
        Returns an iterator running over the methods.
        For each method a dictionary is yield with the line number as key and the method line as value. 
        
        Parameters
        ----------
        read_all_procedures: boolean, optional (default is False)
            If True, all procedures will be read.
            If False, only those recognized as a `CategoryClass` or method implementation
            will be read. 
            See `AsmRegEx.is_method_implementation` for details.
        file_iterator: iterator<tuple<int, string>>
            the iterator to use
              
        Returns
        -------
        method_dict iterator: iterator<dict<int, string>>
        '''
        re_procedure = AsmRegEx.compiled_re(AsmRegEx.RE_PROCEDURE)
        # list of lines of the current method
        method_dict = {}
        first_method_found = False

        def init_proper_method():
            ''' indicates if the method is a method implementation or a category method '''
            return True if read_all_procedures else False

        proper_method = init_proper_method()

        first_method_fix = False
        for linenr, line in file_iterator:
            procedure_match = re_procedure.search(line)
            # `sections_it` cuts the lines before the first occurrence of section
            # use this pattern to detect first method anyway
            if not first_method_fix:
                first_method_fix = line.find('; Section') != -1
            # check if proper method
            if not read_all_procedures and not proper_method:
                proper_method = any((anare.is_method_implementation(line),
                                     anare.is_entrypoint(line)))
            # procedure found
            if procedure_match is not None:
                # not the first method_dict
                if proper_method:
                    yield method_dict
                method_dict = {}
                first_method_found = True
                proper_method = init_proper_method()
            # start collecting the lines of a method after the first method pattern has been found
            if first_method_found or (first_method_fix and proper_method):
                method_dict.update({linenr: line})
        # yield rest
        if proper_method and method_dict:
            yield method_dict
Пример #2
0
    def compiled_re_stack(stack_pointer_name, frame_pointer_name):
        ''' 
        Return a compiled regular expression that matches  e.g. "[sp, #0x8]" or "[sp], #0x4"
        Use `RE_STACK_GR_ADDRESS` group key to get the stack address.
            
        Parameters
        ----------
        stack_pointer_name: string
            the name of stack pointer register (e.g. "sp")
        '''
        RE_STACK = r'''
         \[                              # [
         (?P<%s>%s|%s)                   # stack pointer name or frame pointer name
         (
                 (
                 \]
                 ,\s+                            # ,
                 [#]                             # #
                 (?P<%s>0x\w+)                   # 0x8
                 )
             |                                   # or
                 (                
                 ,\s+                            # , 
                 [#]
                 (?P<%s>0x\w+)                   # #0x8
                 \]                              # ]
                 )
            |
                \]                              # ]
         )

        ''' % (AsmRegEx_arm.RE_STACK_GR_STACK_POINTER, stack_pointer_name,
               frame_pointer_name, AsmRegEx_arm.RE_STACK_GR_OFFSET,
               AsmRegEx_arm.RE_STACK_GR_ADDRESS)
        return AsmRegEx.compiled_vre(RE_STACK)
Пример #3
0
 def parse_hex(self, asmline):
     ''' 
     Parse a line containing a hex value and convert it to an int. 
       
     Parameters
     ----------
     asmline: string
     
     Returns
     -------
     int: int
         hex value converted to int
     None
         if regular expression did not classify as hex value
     
     '''
     hex_match = regexp.compiled_vre(regexp.RE_HEX_VALUE).search(asmline)
     hex_value, res = None, None
     if hex_match is not None:
         hex_value = hex_match.group(regexp.RE_HEX_VALUE_GR_HEX_VALUE)
         try:
             res = int(hex_value, 16)
         except TypeError:
             log.warn('%s is no hex value!', hex_value)
     return res
Пример #4
0
 def parse_c_string(self, asmline):
     ''' Create a `CString` from a c string like e.g. "defaults" '''
     c_string_match = regexp.compiled_vre(regexp.RE_C_STRING).search(asmline)
     if c_string_match is not None:
         c_string = c_string_match.group(regexp.RE_C_STRING_GR_NAME)
         return CString(c_string)
     return None
Пример #5
0
 def parse_nsstring(self, asmline):
     ''' Create a `NSString` from e.g. @"defaults" '''
     string_match = regexp.compiled_vre(regexp.RE_STRING).search(asmline)
     if string_match is not None:
         name = string_match.group(regexp.RE_STRING_GR_STRING)
         return NSString(name)
     return None
Пример #6
0
 def __read_superclasses_from_sections(section_it):
     '''
     Read the superclasses from the specified section name 
     
     Parameters
     ----------
     section_it: iterator<tuple<int, string>>
         iterator over the sections where the superclass infos are stored
     
     Returns
     -------
     dict<ObjcClass, ObjcClass>
         dict with object as key and the superclass as item
     '''
     superclasses_dict = {}
     for (_, i) in section_it:
         CLASS_PARENT_MATCH = AsmRegEx.compiled_vre(
             AsmRegEx.RE_CLASS_PARENT).search(i)
         if CLASS_PARENT_MATCH is not None:
             clazzname = CLASS_PARENT_MATCH.group(
                 AsmRegEx.RE_CLASS_PARENT_GR_CLASS)
             superclazz_name = CLASS_PARENT_MATCH.group(
                 AsmRegEx.RE_CLASS_PARENT_GR_PARENT)
             superclasses_dict[ObjcClass(clazzname)] = ObjcClass(
                 superclazz_name)
     return superclasses_dict
Пример #7
0
    def read_assignment(self, asmline):
        '''
        Read an assigment and try to split it.
        
        Parameters
        ----------
        asmline : string
            line of assembler
        '''
        AssignmentMatchingSystem.reset(self)
        assignment_match = AsmRegEx.compiled_vre(
            regexp.RE_ASSINGMENT_SPLIT).search(asmline)
        if assignment_match is not None:
            self.is_assignment = True
            val1 = assignment_match.group(regexp.RE_ASSINGMENT_SPLIT_GR_VAL1)
            val2 = assignment_match.group(regexp.RE_ASSINGMENT_SPLIT_GR_VAL2)
            pu = self.parse_util

            # stack push
            stack_access = pu.parse_stack_access(val1)
            if stack_access is not None:
                _, addr = stack_access
                self.is_stack_push = True
                self.stack_address = addr
                # save stack access in args_since_last_call to determine number of stack arguments needed for next call
                self.stack_usage_since_last_call.add(stack_access)

            self._log_assignment_split(val1, val2)

            stackvar1 = pu.parse_stackvar(val1)
            var_assign1 = pu.parse_var_assignment_without_ivar_ref_from_asmline(
                val1)

            # assume classref, frameworkclass, ivar, selector and string cannot exist on the left side
            var_assign2 = pu.parse_var_assignment_without_ivar_ref_from_asmline(
                val2)

            val2_remaining_types = [
                pu.parse_ivar, pu.parse_objc_class, pu.parse_selector,
                pu.parse_string, pu.parse_imp
            ]

            # stack fetch
            stackvar2 = pu.parse_stackvar(val2)
            if stackvar2 is not None:
                self.is_stack_fetch = True
                # replace arg_ with method argument for c function definition
                self._try_replace_argument_stack_var_c_method(stackvar2, val2)

            lobject = self._get_val1_value(val1, stackvar1, var_assign1)
            self.lobject = lobject
            robject = self._get_val2_value(val2, stackvar2, var_assign2,
                                           val2_remaining_types)
            self.robject = robject

            # save register in args_since_last_call to determine number of register arguments needed for next call
            self.add_reg_arg_since_last_call(lobject, robject)
Пример #8
0
 def create_from_asm_line(asmline):
     ''' Create Selector from asm line like e.g. @selector(objectForKey:) '''
     selector_match = AsmRegEx.compiled_vre(
         AsmRegEx.RE_SELECTOR).search(asmline)
     if selector_match is not None:
         selector = Selector(
             selector_match.group(AsmRegEx.RE_SELECTOR_GR_SELECTOR))
         return selector
     return None
Пример #9
0
 def parse_c_method_name(asmline):
     '''
     Check if is `RE_SUB` or `RE_C_METHOD` and return the appropriate name if available.
     Otherwise None.
     
     Returns
     -------
     Function
         if `RE_C_METHOD` matches
     Sub
         if `RE_SUB` matches
     '''
     re_sub_match = regexp.compiled_vre(regexp.RE_SUB).search(asmline)
     if re_sub_match:
         return Sub(re_sub_match.group(regexp.RE_SUB_GR_SUBNAME))
     re_c_method_match = regexp.compiled_vre(regexp.RE_C_METHOD).search(asmline)
     if re_c_method_match:
         return Function(re_c_method_match.group(regexp.RE_C_METHOD_GR_NAME))
     return None
Пример #10
0
 def parse_meth_impl(asmline):
     ''' Parse a method implementation like e.g. "methImpl_AppDelegate_applicationDidFinishLaunching_". 
     
     For more details see `RE_METH_IMPL`.
     
     Returns
     -------
     MethodImplementation
     ''' 
     meth_impl_match = regexp.compiled_vre(regexp.RE_METH_IMPL).search(asmline)
     if meth_impl_match is not None:
         classname = meth_impl_match.group(regexp.RE_METH_IMPL_GR_CLASS)
         selectorname = meth_impl_match.group(regexp.RE_METH_IMPL_GR_SELECTOR)
         selector = Selector.selector_from_underscore_delimiter(selectorname)
         is_static = regexp.method_implementation_is_static(meth_impl_match.group(regexp.RE_METH_IMPL_GR_STATIC))
         if classname is not None:
             objc_class = ObjcClass(classname, is_static = is_static)
             return MethodImplementation(objc_class, [selector], is_static)
     return None
Пример #11
0
 def parse_own_c_method_called(asmline):
     re_own_c_method_call_match = regexp.compiled_vre(regexp.RE_OWN_C_METHOD_CALLED).search(asmline)
     if re_own_c_method_call_match:
         func_name = re_own_c_method_call_match.group(regexp.RE_OWN_C_METHOD_BASE_GR_NAME)
         func_args_str = re_own_c_method_call_match.group(regexp.RE_OWN_C_METHOD_BASE_GR_ARGS)
         if func_args_str is not None:
             func_args_list = re_own_c_method_call_match.group(regexp.RE_OWN_C_METHOD_BASE_GR_ARGS).split(', ')
         else:
             func_args_list = []                
         return Function(func_name, func_args_list)
     return None
Пример #12
0
 def parse_format_string(self, asmline):
     ''' Create a `FormatString` from e.g. @"%s%d" '''
     string_match = regexp.compiled_vre(regexp.RE_FORMAT_STRING).search(asmline)
     if string_match is not None:
         name = string_match.group(regexp.RE_FORMAT_STRING_GR_STRING)
         is_objc_format_string = string_match.group(regexp.RE_FORMAT_STRING_GR_OBJC_STRING)
         if not is_objc_format_string:
             return CFormatString(CString(name))
         else:
             return FormatString(NSString(name))
     return None
Пример #13
0
 def _read_basic_block(self, asmline):
     ''' 
     Read a Basic Block like " ; Basic Block Input Regs: rax rdx rsi rdi -  Killed Regs: rax rcx rdx rsp rbp rsi rdi r8"
     and kill the specified registers.
     '''
     basic_block_match = AsmRegEx.compiled_vre(
         AsmRegEx.RE_BASIC_BLOCK).search(asmline)
     if basic_block_match is not None:
         killed_regs = basic_block_match.group(
             AsmRegEx.RE_BASIC_BLOCK_KILLED_REGS)
         killed_regs = killed_regs.split(' ')
         self.memory.registers.delete_elements(killed_regs)
Пример #14
0
 def compiled_re_stack(stack_pointer_name):
     ''' 
     Return a compiled regular expression that matches  e.g. "qword [ss:rsp+0x8]"
     Use `RE_STACK_GR_ADDRESS` group key to get the stack address.
         
     Parameters
     ----------
     stack_pointer_name: string
         the name of stack pointer register (e.g. "rsp")
     '''
     RE_STACK = r'''
      \[ss:                           # [ss:
      (?P<%s>%s)                      # stack pointer name
      (\+                             # + 
      (?P<%s>0x\w+))*                 # 0x8 or empty -> 0x0
      \]                              # ]
     ''' % (AsmRegEx_x86_64.RE_STACK_GR_REG, stack_pointer_name,
            AsmRegEx_x86_64.RE_STACK_GR_ADDRESS)
     return AsmRegEx.compiled_vre(RE_STACK)
Пример #15
0
 def create_from_asm_line(asmline):
     ''' Create a `MethodImplementation` from an assembler line like e.g " +[NSURLRequest(AnyHttpsCert) allowsAnyHTTPSCertificateForHost:]_100002120:" 
         Returns a `MethodImplementation` where the class is a `CategoryClass`.
     '''
     msg_send = None
     category_match = AsmRegEx.compiled_vre(
         AsmRegEx.RE_CATEGORY).search(asmline)
     if category_match is not None:
         category_on_class = category_match.group(
             AsmRegEx.RE_CATEGORY_ON_CLASS)
         classname = category_match.group(AsmRegEx.RE_CATEGORY_CLASS)
         category_is_static = category_match.group(
             AsmRegEx.RE_CATEGORY_STATIC_SYMBOL
         ) == AsmRegEx.RE_CATEGORY_SYMBOL_STATIC
         selectorname = category_match.group(AsmRegEx.RE_CATEGORY_SELECTOR)
         selector = Selector(selectorname)
         cclass = CategoryClass(classname, category_on_class)
         msg_send = MethodImplementation(cclass, [selector],
                                         is_static=category_is_static)
     return msg_send