Example #1
0
 def test_build_error_invalid_input_directory_path(self):
     with pytest.raises(NotADirectoryError):
         Apktool().build("invalid.input.directory.path")
Example #2
0
    def test_build_error_invalid_input_directory(self, tmp_working_directory_path: str):
        invalid_directory_path = os.path.join(tmp_working_directory_path, "empty")
        os.makedirs(invalid_directory_path)

        with pytest.raises(subprocess.CalledProcessError):
            Apktool().build(invalid_directory_path)
Example #3
0
 def test_decode_error_invalid_output_directory(
     self, tmp_demo_apk_v10_original_path: str
 ):
     with pytest.raises(NotADirectoryError):
         Apktool().decode(tmp_demo_apk_v10_original_path, "invalid.directory")
Example #4
0
 def test_decode_error_invalid_apk_path(self):
     with pytest.raises(FileNotFoundError):
         Apktool().decode("invalid.apk.path")
Example #5
0
 def test_decode_valid_apk(self, tmp_demo_apk_v10_original_path: str):
     output = Apktool().decode(tmp_demo_apk_v10_original_path)
     assert "using apktool" in output.lower()
Example #6
0
 def test_apktool_wrong_path(self, monkeypatch):
     monkeypatch.setenv("APKTOOL_PATH", "invalid.apktool.path")
     with pytest.raises(RuntimeError):
         Apktool()
Example #7
0
    def decode_apk(self) -> None:

        if not self._is_decoded:

            # The input apk will be decoded with apktool.
            apktool: Apktool = Apktool()

            # <working_directory>/<apk_path>/
            self._decoded_apk_path = os.path.join(
                self.working_dir_path,
                os.path.splitext(os.path.basename(self.apk_path))[0],
            )
            try:
                apktool.decode(self.apk_path,
                               self._decoded_apk_path,
                               force=True)

                # Path to the decoded manifest file.
                self._manifest_file = os.path.join(self._decoded_apk_path,
                                                   "AndroidManifest.xml")

                # A list containing the paths to all the smali files obtained with
                # apktool.
                self._smali_files = [
                    os.path.join(root, file_name) for root, dir_names,
                    file_names in os.walk(self._decoded_apk_path)
                    for file_name in file_names if file_name.endswith(".smali")
                ]

                if self.ignore_libs:
                    # Normalize paths for the current OS ('.join(x, "")' is used to add
                    # a trailing slash).
                    libs_to_ignore = list(
                        map(
                            lambda x: os.path.join(os.path.normpath(x), ""),
                            util.get_libs_to_ignore(),
                        ))
                    filtered_smali_files = []

                    for smali_file in self._smali_files:
                        # Get the path without the initial part <root>/smali/.
                        relative_smali_file = os.path.join(*(
                            os.path.relpath(smali_file, self._decoded_apk_path
                                            ).split(os.path.sep)[1:]))
                        # Get only the smali files that are not part of known third
                        # party libraries.
                        if not any(
                                relative_smali_file.startswith(lib)
                                for lib in libs_to_ignore):
                            filtered_smali_files.append(smali_file)

                    self._smali_files = filtered_smali_files

                # Sort the list of smali files to always have the list in the same
                # order.
                self._smali_files.sort()

                # Check if multidex.
                if os.path.isdir(
                        os.path.join(self._decoded_apk_path,
                                     "smali_classes2")):
                    self._is_multidex = True

                    smali_directories = ["smali"]
                    for i in range(2, 15):
                        smali_directories.append("smali_classes{0}".format(i))

                    for smali_directory in smali_directories:
                        current_directory = os.path.join(
                            self._decoded_apk_path, smali_directory, "")
                        if os.path.isdir(current_directory):
                            self._multidex_smali_files.append([
                                smali_file for smali_file in self._smali_files
                                if smali_file.startswith(current_directory)
                            ])

                # A list containing the paths to the native libraries included in the
                # application.
                self._native_lib_files = [
                    os.path.join(root, file_name)
                    for root, dir_names, file_names in os.walk(
                        os.path.join(self._decoded_apk_path, "lib"))
                    for file_name in file_names if file_name.endswith(".so")
                ]

                # Sort the list of native libraries to always have the list in the
                # same order.
                self._native_lib_files.sort()

            except Exception as e:
                self.logger.error("Error during apk decoding: {0}".format(e))
                raise
            else:
                self._is_decoded = True