def test_obfuscation_decode_apk_success( self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path, ignore_libs=True, interactive=True) assert not obfuscation._decoded_apk_path obfuscation.decode_apk() assert os.path.isdir(obfuscation._decoded_apk_path)
def test_obfuscation_decode_apk_error(self, tmp_demo_apk_v10_original_path: str, monkeypatch): def mock(*args, **kwargs): raise Exception monkeypatch.setattr(Apktool, "decode", mock) obfuscation = Obfuscation(tmp_demo_apk_v10_original_path, ignore_libs=True, interactive=True) with pytest.raises(Exception): obfuscation.decode_apk()
def test_obfuscation_align_obfuscated_apk_success( self, tmp_working_directory_path: str, tmp_demo_apk_v10_original_path: str, tmp_demo_apk_v10_rebuild_path: str, ): obfuscated_apk_path = os.path.join(tmp_working_directory_path, "obfuscated.apk") obfuscation = Obfuscation( tmp_demo_apk_v10_original_path, tmp_working_directory_path, obfuscated_apk_path, ) obfuscation.obfuscated_apk_path = tmp_demo_apk_v10_rebuild_path # In case of errors an exception would be thrown. obfuscation.align_obfuscated_apk()
def test_obfuscation_build_obfuscated_apk_success( self, tmp_working_directory_path: str, tmp_demo_apk_v10_original_path: str, ): obfuscated_apk_path = os.path.join(tmp_working_directory_path, "obfuscated.apk") obfuscation = Obfuscation( tmp_demo_apk_v10_original_path, tmp_working_directory_path, obfuscated_apk_path, ) assert not os.path.isfile(obfuscated_apk_path) obfuscation.build_obfuscated_apk() assert os.path.isfile(obfuscated_apk_path)
def test_obfuscation_sign_obfuscated_apk_error_missing_keystore_file( self, tmp_working_directory_path: str, tmp_demo_apk_v10_original_path: str, tmp_demo_apk_v10_rebuild_path: str, ): obfuscated_apk_path = os.path.join(tmp_working_directory_path, "obfuscated.apk") obfuscation = Obfuscation( tmp_demo_apk_v10_original_path, tmp_working_directory_path, obfuscated_apk_path, keystore_file="invalid.keystore.path", ) obfuscation.obfuscated_apk_path = tmp_demo_apk_v10_rebuild_path with pytest.raises(FileNotFoundError): obfuscation.sign_obfuscated_apk()
def perform_obfuscation( input_apk_path: str, obfuscator_list: List[str], working_dir_path: str = None, obfuscated_apk_path: str = None, interactive: bool = False, ignore_libs: bool = False, virus_total_api_key: List[str] = None, ): """ Apply the obfuscation techniques to an input application and generate an obfuscated apk file. :param input_apk_path: The path to the input application file to obfuscate. :param obfuscator_list: A list containing the names of the obfuscation techniques to apply. :param working_dir_path: The working directory where to store the intermediate files. By default a directory will be created in the same directory as the input application. If the specified directory doesn't exist, it will be created. :param obfuscated_apk_path: The path where to save the obfuscated apk file. By default the file will be saved in the working directory. :param interactive: If True, show a progress bar with the obfuscation progress. :param ignore_libs: If True, exclude known third party libraries from the obfuscation operations. :param virus_total_api_key: A list containing Virus Total API keys, needed only when using Virus Total obfuscator. """ check_external_tool_dependencies() if not os.path.isfile(input_apk_path): logger.critical( 'Unable to find application file "{0}"'.format(input_apk_path)) raise FileNotFoundError( 'Unable to find application file "{0}"'.format(input_apk_path)) obfuscation = Obfuscation( input_apk_path, working_dir_path, obfuscated_apk_path, interactive=interactive, ignore_libs=ignore_libs, virus_total_api_key=virus_total_api_key, ) manager = ObfuscatorManager() obfuscator_name_to_obfuscator_object = { ob.name: ob.plugin_object for ob in manager.get_all_obfuscators() } obfuscator_name_to_function = { ob.name: ob.plugin_object.obfuscate for ob in manager.get_all_obfuscators() } valid_obfuscators = manager.get_obfuscators_names() # Check how many obfuscators in list will add new fields/methods. for obfuscator_name in obfuscator_list: # Make sure all the provided obfuscator names are valid. if obfuscator_name not in valid_obfuscators: raise ValueError( 'There is no obfuscator named "{0}"'.format(obfuscator_name)) if obfuscator_name_to_obfuscator_object[ obfuscator_name].is_adding_fields: obfuscation.obfuscators_adding_fields += 1 if obfuscator_name_to_obfuscator_object[ obfuscator_name].is_adding_methods: obfuscation.obfuscators_adding_methods += 1 obfuscator_progress = util.show_list_progress( obfuscator_list, interactive=interactive, unit="obfuscator", description="Running obfuscators", ) for obfuscator_name in obfuscator_progress: try: if interactive: obfuscator_progress.set_description( "Running obfuscators ({0})".format(obfuscator_name)) (obfuscator_name_to_function[obfuscator_name])(obfuscation) except Exception as e: logger.critical("Error during obfuscation: {0}".format(e), exc_info=True) raise
def test_obfuscation_error_invalid_apk_path(self): with pytest.raises(FileNotFoundError): Obfuscation("invalid.apk.path")
def test_get_resource_directory(self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) resource_dir = obfuscation.get_resource_directory() assert os.path.isdir(resource_dir) assert "drawable" in os.listdir(resource_dir)
def test_get_assets_directory(self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) assets_dir = obfuscation.get_assets_directory() assert os.path.isdir(assets_dir) assert "message.txt" in os.listdir(assets_dir)
def test_get_native_lib_files(self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) native_libs = obfuscation.get_native_lib_files() assert len(native_libs) > 0 assert all(os.path.isfile(native_lib) for native_lib in native_libs)
def test_get_multidex_smali_files(self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) smali_files = obfuscation.get_multidex_smali_files() # This test application is not multidex. assert len(smali_files) == 0
def test_get_smali_files(self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) smali_files = obfuscation.get_smali_files() assert len(smali_files) > 5 assert all(os.path.isfile(smali_file) for smali_file in smali_files)
def test_get_manifest_file(self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) manifest = obfuscation.get_manifest_file() assert os.path.isfile(manifest)
def test_is_multidex(self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) is_multidex = obfuscation.is_multidex() assert is_multidex is False
def test_obfuscation_get_remaining_methods( self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) remaining_methods = obfuscation._get_remaining_methods() assert isinstance(remaining_methods, int) assert remaining_methods > 63500
def test_obfuscation_get_total_methods( self, tmp_demo_apk_v10_original_path: str): obfuscation = Obfuscation(tmp_demo_apk_v10_original_path) total_methods = obfuscation._get_total_methods() assert isinstance(total_methods, int) assert total_methods > 10