示例#1
0
    def msg_send_from_destination(self, destination, selector):
        '''
        Create a MsgSend from the given `destination` and `selector`.
        
        Parameters
        ----------
        selector: Selector
        destination: 
            to which object to send the message

        Returns
        -------
        msg_send: MsgSend
            the created `MsgSend`
        '''
        msg_send = None
        if selector is not None:
            if isinstance(destination, MsgSendInterface) or destination == 0:
                # set 0 to not_initialized
                if isinstance(destination, IVar):
                    if destination.ivar_ref == 0:
                        destination.ivar_ref = MsgSend(NOT_INITIALIZED_CLASS,
                                                       [])
                # set 0 to not_initialized
                if destination == 0:
                    msg_send = MsgSend(NOT_INITIALIZED_CLASS, [selector])
                else:
                    # ivar_ref_lookup kwarg resolves ivar_ref from IVar
                    msg_send = destination.create_msg_send(
                        selector, ivar_ref_lookup=self.ivar_lookup)
        return msg_send
示例#2
0
文件: IVar.py 项目: nachtmaar/vizasm
 def create_msg_send(self, selector, ivar_ref_lookup=None, *args, **kwargs):
     ''' Create a `MsgSend` with the specified `selector`.
     If the `ivar_ref` is not None, this will be used for the `MsgSend`.
     Otherwise the `ivar_class` is used.
     
     Parameters
     ----------
     selector: Selector
         the `Selector` with which the `MsgSend` shall be created.
     ivar_ref_lookup: IVarRefLookup, optional
         if given, the ivar_ref will be resolved
     Returns
     -------
     MsgSend
         the created `MsgSend` with `ivar_ref`  or `ivar_class`  
     '''
     # ivar_ref_lookup = kwargs.get('ivar_ref_lookup')
     if ivar_ref_lookup is not None:
         try:
             self.resolve_ivar_ref(ivar_ref_lookup)
         except (IvarRefCouldNotBeResolvedException,
                 IvarRefWrongTypeException) as e:
             log.exception(e)
     ivar_ref = self.get_ivar_ref()
     if ivar_ref is not None:
         return MsgSend.create_from_msgsend(ivar_ref, selector)
     else:
         return MsgSend(self.get_ivar_class(), [selector])
示例#3
0
 def test_filter_function(self):
     ''' Test the `mc_filter_function` method '''
     func = lambda x: str(x) == '@"foo"'
     c_func = MsgSend(ObjcClass('Bla'), [Selector('foo:', [NSString('foo')])]) 
     msgsend = MsgSend(ObjcClass('SomeClass'), [Selector('someSelector:2dnarg:3rdarg:', [c_func, NSString('SomeString'), NSString('bar')])])
     check_method_correct_working = mc_filter_method_call(msgsend, [func], steps = 3)
     self.assertTrue(check_method_correct_working, 'The method `mc_filter_function` is not working properly!')
示例#4
0
    def test_has_any_selector(self):
        ''' Test the method `mc_has_any_selector` '''
        sel_name = 'format'
        msg_send = MsgSend(ObjcClass('NSString'), [Selector('stringWithFormat:', [FormatString('@"%@", @"foo"')])])

        res = mc_has_any_selector(msg_send, [sel_name], search_substring = True)
        print '%s has selector "%s" = %s' % (msg_send, sel_name, res)
        
        # [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:]
        sel = 'beginBackgroundTaskWithExpirationHandler:'
        msg_send2 = MsgSend(ObjcClass('UIApplication'), [Selector('sharedApplication'), Selector(sel)])
        res2 = mc_has_any_selector(msg_send2, [sel], search_substring = False)
        self.assertTrue(res and res2 , 'The method `mc_has_any_selector` is not working properly!')
示例#5
0
 def test_msg_send_eq(self):
     objc_class = ObjcClass('Foo')
     sels = [Selector('alloc'), Selector('init'), Selector('foo:', ['1'])]
     sels2 = [Selector('foo:', ['1'])]
     msg_send1 = MsgSend(objc_class, sels)
     msg_send2 = MethodImplementation(objc_class, sels2)
     res = msg_send1 == msg_send2 and msg_send2 == msg_send1
     print '%s == %s and vice versa = %s' % (msg_send1, msg_send2, res)
     self.assertTrue(res, 'Node quality not correct! Method calls will not link to the corresponding method implementations and vice versa\n')
 def test_filter_method_definition(self):
     ''' Test `md_filter_method_defintion` '''
     selname = 'application:handleOpenURL:'
     sel = Selector(selname)
     msg_send = MsgSend(ObjcClass('AppDelegate'), [sel])
     res = md_filter_method_defintion(msg_send,
                                      class_name=None,
                                      selector_name=selname,
                                      search_substring=True)
     print '%s has selector %s = %s' % (msg_send, sel, res)
     self.assertTrue(res, self.MSG % 'MethodDefFilterUtil')
示例#7
0
 def msg_send_from_destination(self, destination, selector):
     ''' Overwritten to accept other ints as destination.
     Currently annotation in Hopper is not so good, leading often to hex values (parsed to int) in the `destination_register`. '''
     # temporary workaround to read a msgSend even if destination is integer (transformed from hex)
     # because Hopper is currently not annotating all destinations!
     msg_send = ObjectiveCRuntime.msg_send_from_destination(
         self, destination, selector)
     if msg_send is None:
         arm_fix = isinstance(destination, int)
         if selector is not None and arm_fix:
             msg_send = MsgSend(ObjcClass(str(destination)), [selector])
     return msg_send
    def test_filter_category(self):
        ''' Tests for the method `md_filter_category` '''
        category_on_class_name = 'NSURLRequest'
        category_on_class = ObjcClass(category_on_class_name)
        category_name = 'AnyHttpsCert'
        cclass = CategoryClass(category_name,
                               category_on_class=category_on_class)
        selector = Selector('allowsAnyHTTPSCertificateForHost')
        category_msg_send = MsgSend(cclass, [selector])

        # test with all properties at once
        category_match = md_filter_category(category_msg_send,
                                            str(selector),
                                            category_on_class_name,
                                            category_name,
                                            search_substring=False)
        print '%s is category on %s with name %s and selector %s = %s' % (
            category_msg_send, category_on_class_name, category_name, selector,
            category_match)

        category_match2 = md_filter_category(category_msg_send,
                                             str(selector),
                                             category_on_class_name,
                                             category_name=None,
                                             search_substring=False)
        print '%s is category on %s and selector %s = %s' % (
            category_msg_send, category_on_class_name, selector,
            category_match2)

        # category_on test
        category_match3 = md_filter_category(
            category_msg_send, category_on=category_on_class_name)
        print '%s is category on %s = %s' % (
            category_msg_send, category_on_class_name, category_match3)

        # category name test
        category_match4 = md_filter_category(category_msg_send,
                                             category_name=category_name)
        print '%s is category with name %s = %s' % (
            category_msg_send, category_name, category_match4)

        # selector test
        category_match5 = md_filter_category(category_msg_send,
                                             selector=str(selector))
        print '%s is category with selector %s = %s' % (
            category_msg_send, str(selector), category_match5)

        self.assertTrue(
            all((category_match, category_match2, category_match3,
                 category_match4, category_match5)),
            self.MSG % 'md_filter_category')
示例#9
0
 def create_msg_send(self, selector, *args, **kwargs):
     ''' Create a `MsgSend` with the specified `selector`.
     
     Parameters
     ----------
     selector: Selector
         the `Selector` with which the `MsgSend` shall be created.
         
     Returns
     -------
     MsgSend
         the created `MsgSend` 
     '''
     return MsgSend(self, [selector])
示例#10
0
 def test_contains_imp_got(self):
     ''' Test the `mc_contains_imp_got` method '''
     imp_got_to_search = 'NSStreamSocketSecurityLevelNone'
     args = [ImpGot(imp_got_to_search), ImpGot('NSStreamSocketSecurityLevel')]
     msg_send = MsgSend(ObjcClass("NSOutputStream"), [Selector('setProperty:forKey:', arguments = args)])
     res = mc_contains_imp_got(msg_send, imp_got_to_search)
     print '%s\n has %s: %s' % (msg_send, imp_got_to_search, res)
     
     imp_got_to_search = 'kSBXProfileNoWrite'
     c_func = Function('sandbox_init', func_arguments = [ImpGot('kSBXProfileNoWrite')])
     res2 = mc_contains_imp_got(c_func, imp_got_to_search)
     print '%s\n has %s: %s' % (c_func, imp_got_to_search, res)
     
     self.assertTrue(res and res2, 'Method `mc_contains_imp_got` not working properly!')
示例#11
0
 def create_msg_send(self, selector, *args, **kwargs):
     ''' Create a `MsgSend` with the specified `selector`.
     
     Parameters
     ----------
     selector: Selector
         the `Selector` with which the `MsgSend` shall be created.
         
     Returns
     -------
     MsgSend
         the created `MsgSend` 
     '''
     from vizasm.model.objc.function.MsgSend import MsgSend
     return MsgSend(self, [selector])
示例#12
0
 def test_is_exploitable_log_func(self):
     ''' Test the method `mc_is_exploitable_log_func` '''
     msg_send = MsgSend(ObjcClass('NSString'), [Selector('stringWithFormat:', [MethodSelectorArgument('arg1')])])
     exploitable_func = Function('NSLog', [msg_send])
     res = mc_is_exploitable_log_func(exploitable_func)
     print 'is exploitable: %s = %s' % (exploitable_func, res)
     
     exploitable_printf = Function('printf', [StackVar('var_216')])
     res2 = mc_is_exploitable_log_func(exploitable_printf)
     print 'is exploitable: %s = %s' % (exploitable_printf, res2)
     
     exploitable_printf2 = Function('printf', [MethodSelectorArgument('arg1')])
     res3 = mc_is_exploitable_log_func(exploitable_printf2)
     print 'is exploitable: %s = %s' % (exploitable_printf2, res3)
     
     self.assertTrue(all((res, res2, res3)), 'The method `mc_is_exploitable_log_func` is not working properly!')
示例#13
0
    print 'register: %s' % pu.parse_register(
        ' r2                                ; XREF=0x31ae')
    print pu.parse_stack_push_via_stm('stm.w      sp, {r3, r11}',
                                      cpu.stack_pointer_register())
    print pu.parse_stack_push_via_stm('stm.w      sp, {r2, r9}',
                                      cpu.stack_pointer_register().register)
    print pu.parse_stack_access('[sp, #0x8]')
    print pu.parse_stack_access('[sp]')
    print pu.parse_offset_addring_offset_needed('[r0, r4]')
    print pu.parse_offset_addressing('[r0]')

    # VarAssignment test
    cpu.memory.registers.set_value_for_register(
        reg('r5'),
        IVar(ObjcClass('SelfClass'),
             MsgSend(ObjcClass('Foo'),
                     [Selector('alloc'), Selector('init')])))
    cpu.memory.registers.set_value_for_register(reg('r0'), ObjcClass('Foo'))
    cpu.memory.registers.set_value_for_register(reg('r4'),
                                                ObjcClass('SelfClass'))
    print pu.parse_var_assignment_with_ivar_ref_from_asmline(
        'str r0, [r4, r5]')
    print pu.parse_var_assignment_without_ivar_ref_from_asmline('[sp, r5]')
    print pu.parse_var_assignment_with_ivar_ref_from_asmline(
        'str r0, [sp, r5]')
    print 'stack access: %s' % str(pu.parse_stack_access('[sp, #0x4]'))
    print 'stack access: %s' % str(pu.parse_stack_access('[sp], #0x4'))
    print 'stack access: %s' % str(pu.parse_stack_access('[sp]'))

    print pu.parse_add('add        r7, sp, #0xc')
    print pu.parse_add('add        r7, sp')
    print pu.parse_add('add        r7, #0xc')
示例#14
0
    from vizasm.analysis.asm.cpu.x86.Cpu_x86 import Cpu_x86
    from vizasm.analysis.asm.cpu.x86.Register_x86 import Register_x86 as reg
    cpu = Cpu_x86({})
    pu = ParseUtil_x86(cpu, reg)
    imp_stub_x86 = pu.parse_imp(
        'call       imp___symbol_stub__objc_setProperty')
    stackvar = pu.parse_stackvar(
        '00002caf 8B4D14                          mov        ecx, dword [ss:ebp-0x48+arg_4]'
    )
    cls_ref = pu.parse_objc_class_from_classref('[ds:cls_NSAssertionHandler]')
    cls_ref2 = pu.parse_objc_class_from_classref(
        'dword [ds:eax-0x25e1+cls_Object1]')

    cpu.read_line('mov        ecx, dword [ds:eax-0x25e1+cls_Object1]')
    var_assignment_without_ivar_ref = pu.parse_var_assignment_without_ivar_ref_from_asmline(
        'dword [ds:ecx+0x8]')
    cpu.memory.registers.set_value_for_register(
        reg('eax'),
        MsgSend(ObjcClass('Object1'),
                [Selector('alloc'), Selector('init')]))
    var_assignment_with_ivar_ref = pu.parse_var_assignment_with_ivar_ref_from_asmline(
        'mov dword [ds:ecx+0x8], eax')
    print imp_stub_x86
    print cls_ref
    print cls_ref2
    print stackvar
    print var_assignment_without_ivar_ref
    print var_assignment_with_ivar_ref
    print pu.parse_imp(
        '[ds:eax-0x221e+imp___nl_symbol_ptr__NSStreamSocketSecurityLevelKey]')
示例#15
0
class MethodCall(object, AddMethodCallToGraphInterface):
    ''' 
    The `Methodcall` stores messages a sender has sent.
    This model is uses for a method (sender) that sends several messages and is the output of the `Cpu`.

    If the sender is not present at creation, using None as argument for the sender creates a pseudo none sender. 
    You can check if this sender is still present with the method has_no_sender().
    
    Parameters
    ----------
    __sender: FunctionInterface, optional (default is PSEUDO_NONE_SENDER)
    __calls: list<MethodCallItem>, optional (default is [])
    '''
    
    PSEUDO_NONE_NAME = 'pseudo none'
    PSEUDO_NONE_SENDER = MsgSend(ObjcClass(PSEUDO_NONE_NAME), [])
    
    def __init__(self, sender = None, calls = None):
        object.__init__(self)
        if calls is None:
            calls = []
        # fix for creation with None as sender
        if sender is None:
            sender = MethodCall.PSEUDO_NONE_SENDER
        self.__sender = sender
        self.__calls = calls

    def __len__(self):
        return len(self.get_calls())

    def __eq__(self, other): 
        if isinstance(other, MethodCall):
            return self is other or ((self.get_sender(), self.get_calls())) == ((other.sender(), other.get_msg()))   
        return False
    
    def __ne__(self, other):
        return not self == other
    
    def __hash__(self):
        return hash((self.get_sender().__hash__(), tuple(self.get_calls()).__hash__()))
    
    def __iter__(self):
        return iter(sorted(self.calls))
    
    def format_head(self):
        ''' Format the head (first line) of the `MethodCall`.
        No newline will be appended.
        '''
        return 'Method: %s' % (self.get_sender())
        
    def __str__(self):
        head = self.format_head()
        return '%s:\n%s\n%s' % (head, (len(head) + 1) * '-', ''.join(str(call) for call in self))
    
    def __repr__(self):
        return '%s(%s: %s)' % (self.__class__.__name__, self.get_sender(), self.get_calls())
    
    def get_sender(self):
        return self.__sender

    def get_calls(self):
        return self.__calls

    def set_sender(self, value):
        self.__sender = value

    def set_calls(self, value):
        self.__calls = value
        
    sender = property(get_sender, set_sender, None, "__sender(MsgSend, optional (default is PSEUDO_NONE_SENDER))")
    calls = property(get_calls, set_calls, None, "__calls:(list<MethodCallItem>, optional (default is []))")

    def add_methodcall(self, call, linenr, address = None):
        ''' Add a call.
        
        Parameters:
        -----------
        call: Function or MsgSend
        linenr: int
        address: int
        '''
        self.add_methodcallitem(MethodCallItem(call, linenr, address)) 
        
    def add_methodcallitem(self, methodcallitem):
        ''' Add the `MethodCallItem`.
        
        Parameters:
        -----------
        methodcallitem: MethodCallItem
            the `MethodCallItem` which shall be added
        '''
        self.get_calls().append(methodcallitem) 

    def idx_methodcallitem(self, linenr):
        ''' Return the index of the `MethodCallItem` with the given line number'''
        for i, methocallitem in enumerate(self.calls):
            if methocallitem.linenr == linenr:
                return i
        return None
                    
    def has_no_sender(self):
        ''' Check if the `Methodcall` has a sender. 
        If the `MethodCall` is initialized with None as sender, a pseudo none sender is created and used.
        ''' 
        return self.get_sender() == MethodCall.PSEUDO_NONE_SENDER
    
    def is_empty(self):
        ''' Returns if the methodcall does not contain any calls '''
        return len(self.get_calls()) == 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)
   
#####################################################################################
# AddToGraphInterface                                                               #
#####################################################################################
    
    def add_to_graph(self, graph, methodcall_sender_attr_dict = None, methodcall_calls_attr_list_dict = None, sender_methodcall_edge_attr_dict = None):
        ''' Add the `MethodCall` to the graph
        
        Parameters
        ----------
        methodcall_sender_attr_dict: dict, optional (Default {})
        methodcall_calls_attr_list_dict: dict, optional (Default {})
        methodcall_calls_attr_list_dict: dict, optional (Default {})
         '''
        
        if methodcall_sender_attr_dict is None:
            methodcall_sender_attr_dict = {}
        if methodcall_calls_attr_list_dict is None:
            methodcall_calls_attr_list_dict = []
        if sender_methodcall_edge_attr_dict is None:
            sender_methodcall_edge_attr_dict = {}
            
        if len(self) > 0:
            key = self.sender
            graph.add_node(key)
            graph.add_attributes(key, methodcall_sender_attr_dict)
            for idx, methodcallitem in enumerate(self):
                # only set the next attribute dictionary if list is not empty
                if methodcall_calls_attr_list_dict:
                    methodcall_attr_dict = deepcopy(methodcall_calls_attr_list_dict[idx])
                else:
                    methodcall_attr_dict = {}
                    
                edge_label = methodcallitem.call
                graph.add_node(edge_label)
                graph.add_edge(self.sender, edge_label, key = None, attr_dict = deepcopy(sender_methodcall_edge_attr_dict))
                methodcall_attr_dict.update({NodeAttributes.NATTR_LINENUMBER : str(methodcallitem.linenr)}) 
                methodcall_attr_dict.update({NodeAttributes.NATTR_ADDRESS : str(hex(methodcallitem.address))}) 
                graph.add_attributes(edge_label, methodcall_attr_dict)
示例#16
0
 def __init__(self, msg_send_class):
     MsgSend.__init__(self, msg_send_class, [])
示例#17
0
 def create_msg_send(self, selector, *args, **kwargs):
     from vizasm.model.objc.function.MsgSend import MsgSend
     return MsgSend(self, [selector])