Ejemplo n.º 1
0
    def test_is_android_api_with_custom_method(self):
        method = MethodObject(
            "Lcom/example/google/service/ContactsHelper;",
            "getPhoneContacts",
            "()V",
        )

        assert method.is_android_api() is False
Ejemplo n.º 2
0
    def test_is_android_api_with_api(self):
        method = MethodObject(
            class_name="Ljava/lang/Object;",
            name="clone",
            descriptor="()Ljava/lang/Object;",
        )

        assert method.is_android_api() is True
Ejemplo n.º 3
0
 def test_custom_methods(self, apkinfo):
     test_custom_method = {
         MethodObject(
             "Lcom/example/google/service/ContactsHelper;",
             "getPhoneContacts",
             "()V",
         ),
         MethodObject(
             "Lcom/example/google/service/ContactsHelper;",
             "getSIMContacts",
             "()V",
         ),
     }
     assert len(apkinfo.custom_methods) == 3999
     assert test_custom_method.issubset(apkinfo.custom_methods)
Ejemplo n.º 4
0
    def _get_methods_classified(self, dexindex):
        rz = self._get_rz(dexindex)

        method_json_list = rz.cmdj("isj")
        method_dict = defaultdict(list)
        for json_obj in method_json_list:
            if json_obj.get("type") not in ["FUNC", "METH"]:
                continue

            full_name = json_obj["realname"]
            class_name, method_descriptor = full_name.split(".method.",
                                                            maxsplit=1)
            class_name = class_name + ";"

            delimiter = method_descriptor.index('(')
            methodname = method_descriptor[:delimiter]
            descriptor = method_descriptor[delimiter:]
            descriptor = descriptor_to_androguard_format(descriptor)

            is_imported = json_obj["is_imported"]

            method = MethodObject(
                class_name=class_name,
                name=methodname,
                descriptor=descriptor,
                cache=RizinCache(json_obj["vaddr"], dexindex, is_imported),
            )
            method_dict[class_name].append(method)

        return method_dict
Ejemplo n.º 5
0
    def test_android_apis(self, apkinfo):
        api = {
            MethodObject(
                "Landroid/telephony/SmsMessage;",
                "getDisplayOriginatingAddress",
                "()Ljava/lang/String;",
            ),
            MethodObject(
                "Ljava/io/File;",
                "mkdir",
                "()Z",
            ),
        }

        assert len(apkinfo.android_apis) == 1270
        assert api.issubset(apkinfo.android_apis)
Ejemplo n.º 6
0
    def test_compare_with_different_caches(self):
        method_1 = MethodObject(
            class_name="Ljava/lang/Object;",
            name="clone",
            descriptor="()Ljava/lang/Object;",
            cache=("Cache Type A"),
        )

        method_2 = MethodObject(
            class_name=method_1.class_name,
            name=method_1.name,
            descriptor=method_1.descriptor,
            cache={"Cache Type B"},
        )

        assert method_1 == method_2
Ejemplo n.º 7
0
    def test_compare_with_different_access_flags(self):
        method_1 = MethodObject(
            class_name="Ljava/lang/Object;",
            name="clone",
            descriptor="()Ljava/lang/Object;",
            access_flags="public",
        )

        method_2 = MethodObject(
            class_name=method_1.class_name,
            name=method_1.name,
            descriptor=method_1.descriptor,
            access_flags="protected",
        )

        assert method_1 == method_2
Ejemplo n.º 8
0
    def test_full_name(self):
        method = MethodObject(
            class_name="ClassName;", name="Method", descriptor="(Descriptor)"
        )

        full_name = method.full_name

        assert full_name == "ClassName; Method (Descriptor)"
Ejemplo n.º 9
0
 def test_custom_methods(self, apkinfo):
     test_custom_method = {
         MethodObject(
             "Lcom/example/google/service/ContactsHelper;",
             "getPhoneContacts",
             "()V",
         ),
         MethodObject(
             "Lcom/example/google/service/ContactsHelper;",
             "getSIMContacts",
             "()V",
         ),
     }
     if apkinfo.core_library == "androguard":
         assert len(apkinfo.custom_methods) == 3999
     elif apkinfo.core_library == "rizin":
         assert len(apkinfo.custom_methods) == 3990
     assert test_custom_method.issubset(apkinfo.custom_methods)
Ejemplo n.º 10
0
 def _convert_to_method_object(
     method_analysis: MethodAnalysis, ) -> MethodObject:
     return MethodObject(
         access_flags=method_analysis.access,
         class_name=str(method_analysis.class_name),
         name=str(method_analysis.name),
         descriptor=str(method_analysis.descriptor),
         cache=method_analysis,
     )
Ejemplo n.º 11
0
    def test_android_apis(self, apkinfo):
        api = {
            MethodObject(
                "Landroid/telephony/SmsMessage;",
                "getDisplayOriginatingAddress",
                "()Ljava/lang/String;",
            ),
            MethodObject(
                "Ljava/io/File;",
                "mkdir",
                "()Z",
            ),
        }

        if apkinfo.core_library == "androguard":
            assert len(apkinfo.android_apis) == 1270
        elif apkinfo.core_library == "rizin":
            assert len(apkinfo.android_apis) == 1269
        assert api.issubset(apkinfo.android_apis)
Ejemplo n.º 12
0
    def test_upperfunc(self, apkinfo):
        api = apkinfo.find_method("Ljava/lang/reflect/Field;", "setAccessible",
                                  "(Z)V")

        expect_function = MethodObject(
            ("Landroid/support/v4/widget/SlidingPaneLayout$"
             "SlidingPanelLayoutImplJB;"),
            "<init>",
            "()V",
        )

        upper = list(apkinfo.upperfunc(api))[0]

        assert upper == expect_function
Ejemplo n.º 13
0
    def test_lowerfunc(self, apkinfo):
        method = apkinfo.find_method(
            "Lcom/example/google/service/WebServiceCalling;",
            "Send",
            "(Landroid/os/Handler; Ljava/lang/String;)V",
        )

        expect_method = MethodObject(
            "Ljava/lang/StringBuilder;",
            "append",
            "(Ljava/lang/String;)Ljava/lang/StringBuilder;",
        )
        expect_offset = 42

        upper_methods = apkinfo.lowerfunc(method)

        assert (expect_method, expect_offset) in upper_methods
Ejemplo n.º 14
0
    def _get_methods_classified(self, dexindex):
        rz = self._get_rz(dexindex)

        method_json_list = rz.cmdj("isj")
        method_dict = defaultdict(list)
        for json_obj in method_json_list:
            if json_obj.get("type") not in ["FUNC", "METH"]:
                continue

            # -- Descriptor --
            full_method_name = json_obj["name"]
            raw_argument_str = next(
                re.finditer("\\(.*\\).*", full_method_name), None)
            if raw_argument_str is None:
                continue
            raw_argument_str = raw_argument_str.group(0)

            if raw_argument_str.endswith(")"):
                # Convert Java lauguage type to JVM type signature

                # Parse the arguments
                raw_argument_str = raw_argument_str[1:-1]
                arguments = [
                    self._convert_type_to_type_signature(arg)
                    for arg in raw_argument_str.split(", ")
                ]

                # Parse the return type
                return_type = next(
                    re.finditer("[A-Za-zL][A-Za-z0-9L/\\;[\\]$.]+ ",
                                full_method_name),
                    None,
                )
                if return_type is None:
                    print(f"Unresolved method signature: {full_method_name}")
                    continue
                return_type = return_type.group(0).strip()

                # Convert
                raw_argument_str = (
                    "(" + " ".join(arguments) + ")" +
                    self._convert_type_to_type_signature(return_type))

            descriptor = descriptor_to_androguard_format(raw_argument_str)

            # -- Method name --
            method_name = json_obj["realname"]

            # -- Is imported --
            is_imported = json_obj["is_imported"]

            # -- Class name --
            # Test if the class name is truncated
            escaped_method_name = self._escape_str_in_rizin_manner(method_name)
            if escaped_method_name.endswith("_"):
                escaped_method_name = escaped_method_name[:-1]

            flag_name = json_obj["flagname"]

            # sym.imp.clone doesn't belong to a class
            if flag_name == "sym.imp.clone":
                method = MethodObject(
                    class_name="",
                    name="clone",
                    descriptor="()Ljava/lang/Object;",
                    cache=RizinCache(json_obj["vaddr"], dexindex, is_imported),
                )
                method_dict[""].append(method)
                continue

            if escaped_method_name not in flag_name:
                logging.warning(
                    f"The class name may be truncated: {json_obj['flagname']}")

            # Drop the method name
            match = None
            for match in re.finditer("_+[A-Za-z]+", flag_name):
                pass
            if match is None:
                logging.warning(
                    f"Skip the damaged flag: {json_obj['flagname']}")
                continue
            match = match.group(0)
            flag_name = flag_name[:flag_name.rfind(match)]

            # Drop the prefixes sym. and imp.
            while flag_name.startswith("sym.") or flag_name.startswith("imp."):
                flag_name = flag_name[4:]

            class_name = self._convert_type_to_type_signature(flag_name)

            # Append the method
            method = MethodObject(
                class_name=class_name,
                name=method_name,
                descriptor=descriptor,
                cache=RizinCache(json_obj["vaddr"], dexindex, is_imported),
            )
            method_dict[class_name].append(method)

        # Remove duplicates
        for class_name, method_list in method_dict.items():
            method_dict[class_name] = remove_dup_list(method_list)

        return method_dict