androguard/core/analysis/analysis.py
def _create_xref(self, current_class):
        """
        Create the xref for `current_class`

        There are four steps involved in getting the xrefs:
        * Xrefs for class instantiation and static class usage
        *       for method calls
        *       for string usage
        *       for field manipulation

        All these information are stored in the *Analysis Objects.

        Note that this might be quite slow, as all instructions are parsed.

        :param androguard.core.bytecodes.dvm.ClassDefItem current_class: The class to create xrefs for
        """
        cur_cls_name = current_class.get_name()

        log.debug("Creating XREF/DREF for class at @%s" % current_class.get_class_data_off())
        for current_method in current_class.get_methods():
            log.debug("Creating XREF for method at @%s" % current_method.get_code_off())

            for off, instruction in current_method.get_instructions_idx():
                op_value = instruction.get_op_value()

                # 1) check for class calls: const-class (0x1c), new-instance (0x22)
                if op_value in [0x1c, 0x22]:
                    idx_type = instruction.get_ref_kind()
                    # type_info is the string like 'Ljava/lang/Object;'
                    type_info = instruction.cm.vm.get_cm_type(idx_type).lstrip(b'[')
                    if type_info[0] != b'L':
                        # Need to make sure, that we get class types and not other types
                        continue

                    # Internal xref related to class manipulation
                    # FIXME should the xref really only set if the class is in self.classes? If an external class is added later, it will be added too!
                    # See https://github.com/androguard/androguard/blob/d720ebf2a9c8e2a28484f1c81fdddbc57e04c157/androguard/core/analysis/analysis.py#L806
                    # Before the check would go for internal classes only!
                    # FIXME: effectively ignoring calls to itself - do we want that?
                    if type_info == cur_cls_name:
                        continue

                    if type_info not in self.classes:
                        # Create new external class
                        self.classes[type_info] = ClassAnalysis(ExternalClass(type_info))

                    cur_cls = self.classes[cur_cls_name]
                    oth_cls = self.classes[type_info]

                    # FIXME: xref_to does not work here! current_method is wrong, as it is not the target!
                    cur_cls.AddXrefTo(REF_TYPE(op_value), oth_cls, current_method, off)
                    oth_cls.AddXrefFrom(REF_TYPE(op_value), cur_cls, current_method, off)

                # 2) check for method calls: invoke-* (0x6e ... 0x72), invoke-xxx/range (0x74 ... 0x78)
                elif (0x6e <= op_value <= 0x72) or (0x74 <= op_value <= 0x78):
                    idx_meth = instruction.get_ref_kind()
                    method_info = instruction.cm.vm.get_cm_method(idx_meth)
                    if not method_info:
                        log.warning("Could not get method_info for instruction at {} in method at @{}".format(off, current_method.get_code_off()))
                        continue

                    class_info = method_info[0].lstrip(b'[')
                    if class_info[0] != b'L':
                        # Need to make sure, that we get class types and not other types
                        continue

                    method_item = None
                    # TODO: should create get_method_descriptor inside Analysis
                    for vm in self.vms:
                        method_item = vm.get_method_descriptor(class_info, method_info[1], mutf8.MUTF8String.join(method_info[2]))
                        if method_item:
                            break

                    if not method_item:
                        # Seems to be an external class, create it first
                        # Beware: if not all DEX files are loaded at the time create_xref runs
                        # you will run into problems!
                        if class_info not in self.classes:
                            self.classes[class_info] = ClassAnalysis(ExternalClass(class_info))
                        method_item = self.classes[class_info].get_fake_method(method_info[1], method_info[2])

                    self.classes[cur_cls_name].AddMXrefTo(current_method, self.classes[class_info], method_item, off)
                    self.classes[class_info].AddMXrefFrom(method_item, self.classes[cur_cls_name], current_method, off)

                    # Internal xref related to class manipulation
                    if class_info in self.classes and class_info != cur_cls_name:
                        self.classes[cur_cls_name].AddXrefTo(REF_TYPE(op_value), self.classes[class_info], method_item, off)
                        self.classes[class_info].AddXrefFrom(REF_TYPE(op_value), self.classes[cur_cls_name], current_method, off)

                # 3) check for string usage: const-string (0x1a), const-string/jumbo (0x1b)
                elif 0x1a <= op_value <= 0x1b:
                    string_value = instruction.cm.vm.get_cm_string(instruction.get_ref_kind())
                    if string_value not in self.strings:
                        self.strings[string_value] = StringAnalysis(string_value)

                    # TODO: The bytecode offset is stored for classes but not here?
                    self.strings[string_value].AddXrefFrom(self.classes[cur_cls_name], current_method)

                # TODO maybe we should add a step 3a) here and check for all const fields. You can then xref for integers etc!
                # But: This does not work, as const fields are usually optimized internally to const calls...

                # 4) check for field usage: i*op (0x52 ... 0x5f), s*op (0x60 ... 0x6d)
                elif 0x52 <= op_value <= 0x6d:
                    idx_field = instruction.get_ref_kind()
                    field_info = instruction.cm.vm.get_cm_field(idx_field)
                    field_item = instruction.cm.vm.get_field_descriptor(field_info[0], field_info[2], field_info[1])
                    # TODO: The bytecode offset is stored for classes but not here?
                    if not field_item:
                        continue

                    if (0x52 <= op_value <= 0x58) or (0x60 <= op_value <= 0x66):
                        # read access to a field
                        self.classes[cur_cls_name].AddFXrefRead(current_method, self.classes[cur_cls_name], field_item)
                    else:
                        # write access to a field
                        self.classes[cur_cls_name].AddFXrefWrite(current_method, self.classes[cur_cls_name], field_item)

        Create the xref for `current_class`

        There are four steps involved in getting the xrefs:
        * Xrefs for class instantiation and static class usage
        *       for method calls
        *       for string usage
        *       for field manipulation

        All these information are stored in the *Analysis Objects.

        Note that this might be quite slow, as all instructions are parsed.

        :param androguard.core.bytecodes.dvm.ClassDefItem current_class: The class to create xrefs for
        
Create the xref for `current_class`
There are four steps involved in getting the xrefs:
Xrefs for class instantiation and static class usage
for method calls
for string usage
for field manipulation

All these information are stored in the *Analysis Objects.

Note that this might be quite slow, as all instructions are parsed.
Create the xref for ` current_class ` There are four steps involved in getting the xrefs : Xrefs for class instantiation and static class usage for method calls for string usage for field manipulation All these information are stored in the * Analysis Objects . Note that this might be quite slow as all instructions are parsed .
def _create_xref(self, current_class):
        cur_cls_name = current_class.get_name()
        log.debug("Creating XREF/DREF for class at @%s" % current_class.get_class_data_off())
        for current_method in current_class.get_methods():
            log.debug("Creating XREF for method at @%s" % current_method.get_code_off())
            for off, instruction in current_method.get_instructions_idx():
                op_value = instruction.get_op_value()
                if op_value in [0x1c, 0x22]:
                    idx_type = instruction.get_ref_kind()
                    type_info = instruction.cm.vm.get_cm_type(idx_type).lstrip(b'[')
                    if type_info[0] != b'L':
                        continue
                    if type_info == cur_cls_name:
                        continue
                    if type_info not in self.classes:
                        self.classes[type_info] = ClassAnalysis(ExternalClass(type_info))
                    cur_cls = self.classes[cur_cls_name]
                    oth_cls = self.classes[type_info]
                    cur_cls.AddXrefTo(REF_TYPE(op_value), oth_cls, current_method, off)
                    oth_cls.AddXrefFrom(REF_TYPE(op_value), cur_cls, current_method, off)
                elif (0x6e <= op_value <= 0x72) or (0x74 <= op_value <= 0x78):
                    idx_meth = instruction.get_ref_kind()
                    method_info = instruction.cm.vm.get_cm_method(idx_meth)
                    if not method_info:
                        log.warning("Could not get method_info for instruction at {} in method at @{}".format(off, current_method.get_code_off()))
                        continue
                    class_info = method_info[0].lstrip(b'[')
                    if class_info[0] != b'L':
                        continue
                    method_item = None
                    for vm in self.vms:
                        method_item = vm.get_method_descriptor(class_info, method_info[1], mutf8.MUTF8String.join(method_info[2]))
                        if method_item:
                            break
                    if not method_item:
                        if class_info not in self.classes:
                            self.classes[class_info] = ClassAnalysis(ExternalClass(class_info))
                        method_item = self.classes[class_info].get_fake_method(method_info[1], method_info[2])
                    self.classes[cur_cls_name].AddMXrefTo(current_method, self.classes[class_info], method_item, off)
                    self.classes[class_info].AddMXrefFrom(method_item, self.classes[cur_cls_name], current_method, off)
                    if class_info in self.classes and class_info != cur_cls_name:
                        self.classes[cur_cls_name].AddXrefTo(REF_TYPE(op_value), self.classes[class_info], method_item, off)
                        self.classes[class_info].AddXrefFrom(REF_TYPE(op_value), self.classes[cur_cls_name], current_method, off)
                elif 0x1a <= op_value <= 0x1b:
                    string_value = instruction.cm.vm.get_cm_string(instruction.get_ref_kind())
                    if string_value not in self.strings:
                        self.strings[string_value] = StringAnalysis(string_value)
                    self.strings[string_value].AddXrefFrom(self.classes[cur_cls_name], current_method)
                elif 0x52 <= op_value <= 0x6d:
                    idx_field = instruction.get_ref_kind()
                    field_info = instruction.cm.vm.get_cm_field(idx_field)
                    field_item = instruction.cm.vm.get_field_descriptor(field_info[0], field_info[2], field_info[1])
                    if not field_item:
                        continue
                    if (0x52 <= op_value <= 0x58) or (0x60 <= op_value <= 0x66):
                        self.classes[cur_cls_name].AddFXrefRead(current_method, self.classes[cur_cls_name], field_item)
                    else:
                        self.classes[cur_cls_name].AddFXrefWrite(current_method, self.classes[cur_cls_name], field_item)
def _create_xref ( self , current_class ) : cur_cls_name = current_class . get_name ( ) log . debug ( "Creating XREF/DREF for class at @%s" % current_class . get_class_data_off ( ) ) for current_method in current_class . get_methods ( ) : log . debug ( "Creating XREF for method at @%s" % current_method . get_code_off ( ) ) for off , instruction in current_method . get_instructions_idx ( ) : op_value = instruction . get_op_value ( ) if op_value in [ 0x1c , 0x22 ] : idx_type = instruction . get_ref_kind ( ) type_info = instruction . cm . vm . get_cm_type ( idx_type ) . lstrip ( b'[' ) if type_info [ 0 ] != b'L' : continue if type_info == cur_cls_name : continue if type_info not in self . classes : self . classes [ type_info ] = ClassAnalysis ( ExternalClass ( type_info ) ) cur_cls = self . classes [ cur_cls_name ] oth_cls = self . classes [ type_info ] cur_cls . AddXrefTo ( REF_TYPE ( op_value ) , oth_cls , current_method , off ) oth_cls . AddXrefFrom ( REF_TYPE ( op_value ) , cur_cls , current_method , off ) elif ( 0x6e <= op_value <= 0x72 ) or ( 0x74 <= op_value <= 0x78 ) : idx_meth = instruction . get_ref_kind ( ) method_info = instruction . cm . vm . get_cm_method ( idx_meth ) if not method_info : log . warning ( "Could not get method_info for instruction at {} in method at @{}" . format ( off , current_method . get_code_off ( ) ) ) continue class_info = method_info [ 0 ] . lstrip ( b'[' ) if class_info [ 0 ] != b'L' : continue method_item = None for vm in self . vms : method_item = vm . get_method_descriptor ( class_info , method_info [ 1 ] , mutf8 . MUTF8String . join ( method_info [ 2 ] ) ) if method_item : break if not method_item : if class_info not in self . classes : self . classes [ class_info ] = ClassAnalysis ( ExternalClass ( class_info ) ) method_item = self . classes [ class_info ] . get_fake_method ( method_info [ 1 ] , method_info [ 2 ] ) self . classes [ cur_cls_name ] . AddMXrefTo ( current_method , self . classes [ class_info ] , method_item , off ) self . classes [ class_info ] . AddMXrefFrom ( method_item , self . classes [ cur_cls_name ] , current_method , off ) if class_info in self . classes and class_info != cur_cls_name : self . classes [ cur_cls_name ] . AddXrefTo ( REF_TYPE ( op_value ) , self . classes [ class_info ] , method_item , off ) self . classes [ class_info ] . AddXrefFrom ( REF_TYPE ( op_value ) , self . classes [ cur_cls_name ] , current_method , off ) elif 0x1a <= op_value <= 0x1b : string_value = instruction . cm . vm . get_cm_string ( instruction . get_ref_kind ( ) ) if string_value not in self . strings : self . strings [ string_value ] = StringAnalysis ( string_value ) self . strings [ string_value ] . AddXrefFrom ( self . classes [ cur_cls_name ] , current_method ) elif 0x52 <= op_value <= 0x6d : idx_field = instruction . get_ref_kind ( ) field_info = instruction . cm . vm . get_cm_field ( idx_field ) field_item = instruction . cm . vm . get_field_descriptor ( field_info [ 0 ] , field_info [ 2 ] , field_info [ 1 ] ) if not field_item : continue if ( 0x52 <= op_value <= 0x58 ) or ( 0x60 <= op_value <= 0x66 ) : self . classes [ cur_cls_name ] . AddFXrefRead ( current_method , self . classes [ cur_cls_name ] , field_item ) else : self . classes [ cur_cls_name ] . AddFXrefWrite ( current_method , self . classes [ cur_cls_name ] , field_item )
Create the xref for `current_class`
There are four steps involved in getting the xrefs:
 Xrefs for class instantiation and static class usage
       for method calls
       for string usage
       for field manipulation
Create the xref for ` current_class ` There are four steps involved in getting the xrefs : Xrefs for class instantiation and static class usage for method calls for string usage for field manipulation
"""
        Create the xref for `current_class`

        There are four steps involved in getting the xrefs:
        * Xrefs for class instantiation and static class usage
        *       for method calls
        *       for string usage
        *       for field manipulation

        All these information are stored in the *Analysis Objects.

        Note that this might be quite slow, as all instructions are parsed.

        :param androguard.core.bytecodes.dvm.ClassDefItem current_class: The class to create xrefs for
        """ # 1) check for class calls: const-class (0x1c), new-instance (0x22) # type_info is the string like 'Ljava/lang/Object;' # Need to make sure, that we get class types and not other types # Internal xref related to class manipulation # FIXME should the xref really only set if the class is in self.classes? If an external class is added later, it will be added too! # See https://github.com/androguard/androguard/blob/d720ebf2a9c8e2a28484f1c81fdddbc57e04c157/androguard/core/analysis/analysis.py#L806 # Before the check would go for internal classes only! # FIXME: effectively ignoring calls to itself - do we want that? # Create new external class # FIXME: xref_to does not work here! current_method is wrong, as it is not the target! # 2) check for method calls: invoke-* (0x6e ... 0x72), invoke-xxx/range (0x74 ... 0x78) # Need to make sure, that we get class types and not other types # TODO: should create get_method_descriptor inside Analysis # Seems to be an external class, create it first # Beware: if not all DEX files are loaded at the time create_xref runs # you will run into problems! # Internal xref related to class manipulation # 3) check for string usage: const-string (0x1a), const-string/jumbo (0x1b) # TODO: The bytecode offset is stored for classes but not here? # TODO maybe we should add a step 3a) here and check for all const fields. You can then xref for integers etc! # But: This does not work, as const fields are usually optimized internally to const calls... # 4) check for field usage: i*op (0x52 ... 0x5f), s*op (0x60 ... 0x6d) # TODO: The bytecode offset is stored for classes but not here? # read access to a field # write access to a field
self
current_class
The class to create xrefs for
The class to create xrefs for