From 97119fef300dd6e5484a29948fcbb7ae563ef24e Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 12:23:05 +0200 Subject: [PATCH 01/10] replacement of jarsigner with apksigner --- README.md | 31 +++---- src/obfuscapk/cli.py | 2 +- src/obfuscapk/main.py | 4 +- src/obfuscapk/obfuscation.py | 6 +- src/obfuscapk/tool.py | 165 +++++++++++++++++------------------ src/test/test_cli.py | 2 +- src/test/test_obfuscation.py | 2 +- src/test/test_tool.py | 30 +++---- 8 files changed, 119 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index 17cb3fd0..f69278aa 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ information. Make sure to have a recent version of [`apktool`](https://ibotpeaches.github.io/Apktool/), -[`jarsigner`](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html) +[`apksigner`](https://developer.android.com/studio/command-line/apksigner) and [`zipalign`](https://developer.android.com/studio/command-line/zipalign) installed and available from the command line: @@ -161,9 +161,10 @@ Apktool v2.5.0 - a tool for reengineering Android apk files ... ``` ```Shell -$ jarsigner -Usage: jarsigner [options] jar-file alias - jarsigner -verify [options] jar-file [alias...] +$ apksigner +Usage: apksigner [options] + apksigner --version + apksigner --help ... ``` ```Shell @@ -173,10 +174,10 @@ Copyright (C) 2009 The Android Open Source Project ... ``` -To install and use `apktool` you need a recent version of Java, which should also have -`jarsigner` bundled. `zipalign` is included in the Android SDK. The location of the +To install and use `apktool` you need a recent version of Java. +`zipalign` and `apksigner` is included in the Android SDK. The location of the executables can also be specified through the following environment variables: -`APKTOOL_PATH`, `JARSIGNER_PATH` and `ZIPALIGN_PATH` (e.g., in Ubuntu, run +`APKTOOL_PATH`, `APKSIGNER_PATH` and `ZIPALIGN_PATH` (e.g., in Ubuntu, run `export APKTOOL_PATH=/custom/location/apktool` before running Obfuscapk in the same terminal). @@ -257,7 +258,7 @@ obfuscapk [-h] -o OBFUSCATOR [-w DIR] [-d OUT_APK] [-i] [-p] [-k VT_API_KEY] There are two mandatory parameters: ``, the path (relative or absolute) to the apk file to obfuscate and the list with the names of the obfuscation techniques to apply (specified with a `-o` option that can be used multiple times, e.g., -`-o Rebuild -o NewSignature -o NewAlignment`). The other optional arguments are as +`-o Rebuild -o NewAlignment -o NewSignature`). The other optional arguments are as follows: * `-w DIR` is used to set the working directory where to save the intermediate files @@ -307,7 +308,7 @@ Let's consider now a simple working example to see how Obfuscapk works: ```Shell $ # original.apk is a valid Android apk file. -$ obfuscapk -o RandomManifest -o Rebuild -o NewSignature -o NewAlignment original.apk +$ obfuscapk -o RandomManifest -o Rebuild -o NewAlignment -o NewSignature original.apk ``` When running the above command, this is what happens behind the scenes: @@ -332,18 +333,18 @@ available and ready to be used manifest) using `apktool`, and since no output file was specified, the resulting apk file is saved in the working directory created before - - `NewSignature` obfuscator signs the newly created apk file with a custom - certificate contained in a - [keystore bundled with Obfuscapk](https://github.com/ClaudiuGeorgiu/Obfuscapk/blob/master/src/obfuscapk/resources/obfuscation_keystore.jks) - (though a different keystore can be specified with the `--keystore-file` parameter) - - `NewAlignment` obfuscator uses `zipalign` tool to align the resulting apk file + + - `NewSignature` obfuscator signs the newly created apk file with a custom + certificate contained in a + [keystore bundled with Obfuscapk](https://github.com/ClaudiuGeorgiu/Obfuscapk/blob/master/src/obfuscapk/resources/obfuscation_keystore.jks) + (though a different keystore can be specified with the `--keystore-file` parameter) * when all the obfuscators have been executed without errors, the resulting obfuscated apk file can be found in `obfuscation_working_dir/original_obfuscated.apk`, signed, aligned and ready to be installed into a device/emulator -As seen in the previous example, `Rebuild`, `NewSignature` and `NewAlignment` +As seen in the previous example, `Rebuild`, `NewAlignment` and `NewSignature` obfuscators are always needed to complete an obfuscation operation, to build the final obfuscated apk. They are not actual obfuscation techniques, but they are needed in the build process and so they are included in the list of obfuscators to keep the overall diff --git a/src/obfuscapk/cli.py b/src/obfuscapk/cli.py index ccad8ad8..d02e71dc 100644 --- a/src/obfuscapk/cli.py +++ b/src/obfuscapk/cli.py @@ -125,7 +125,7 @@ def main(): -o AssetEncryption -o MethodOverload -o ConstStringEncryption \ -o ResStringEncryption -o ArithmeticBranch -o FieldRename -o Nop -o Goto \ -o ClassRename -o Reflection -o AdvancedReflection -o Reorder -o RandomManifest \ - -o Rebuild -o NewSignature -o NewAlignment \ + -o Rebuild -o NewAlignment -o NewSignature \ -o VirusTotal -k virus_total_key \ /path/to/original.apk """ diff --git a/src/obfuscapk/main.py b/src/obfuscapk/main.py index a0a800ba..ca4f3489 100644 --- a/src/obfuscapk/main.py +++ b/src/obfuscapk/main.py @@ -7,7 +7,7 @@ from obfuscapk import util from obfuscapk.obfuscation import Obfuscation from obfuscapk.obfuscator_manager import ObfuscatorManager -from obfuscapk.tool import Apktool, Jarsigner, Zipalign +from obfuscapk.tool import Apktool, Zipalign, ApkSigner if "LOG_LEVEL" in os.environ: log_level = os.environ["LOG_LEVEL"] @@ -38,7 +38,7 @@ def check_external_tool_dependencies(): # an exception will be thrown by the corresponding constructor. logger.debug("Checking external tool dependencies") Apktool() - Jarsigner() + ApkSigner() Zipalign() diff --git a/src/obfuscapk/obfuscation.py b/src/obfuscapk/obfuscation.py index 05883734..4f3f1141 100644 --- a/src/obfuscapk/obfuscation.py +++ b/src/obfuscapk/obfuscation.py @@ -7,7 +7,7 @@ from typing import List, Union from obfuscapk import util -from obfuscapk.tool import Apktool, Jarsigner, Zipalign +from obfuscapk.tool import Apktool, Jarsigner, Zipalign, ApkSigner class Obfuscation(object): @@ -511,7 +511,7 @@ def sign_obfuscated_apk(self) -> None: # This method must be called AFTER the obfuscated apk has been built. # The obfuscated apk will be signed with jarsigner. - jarsigner: Jarsigner = Jarsigner() + apksigner: ApkSigner = ApkSigner() # If a custom keystore file is not provided, use the default one bundled with # the tool. Otherwise check that the keystore password and a key alias are @@ -537,7 +537,7 @@ def sign_obfuscated_apk(self) -> None: ) try: - jarsigner.resign( + apksigner.resign( self.obfuscated_apk_path, self.keystore_file, self.keystore_password, diff --git a/src/obfuscapk/tool.py b/src/obfuscapk/tool.py index caf7d781..edb89f62 100644 --- a/src/obfuscapk/tool.py +++ b/src/obfuscapk/tool.py @@ -188,27 +188,90 @@ def build(self, source_dir_path: str, output_apk_path: str = None) -> str: raise -class Jarsigner(object): +class Zipalign(object): + def __init__(self): + self.logger = logging.getLogger( + "{0}.{1}".format(__name__, self.__class__.__name__) + ) + + if "ZIPALIGN_PATH" in os.environ: + self.zipalign_path: str = os.environ["ZIPALIGN_PATH"] + else: + self.zipalign_path: str = "zipalign" + + full_zipalign_path = shutil.which(self.zipalign_path) + + # Make sure to use the full path of the executable (needed for cross-platform + # compatibility). + if full_zipalign_path is None: + raise RuntimeError( + 'Something is wrong with executable "{0}"'.format(self.zipalign_path) + ) + else: + self.zipalign_path = full_zipalign_path + + def align(self, apk_path: str) -> str: + + # Check if the apk file to align is a valid file. + if not os.path.isfile(apk_path): + self.logger.error('Unable to find file "{0}"'.format(apk_path)) + raise FileNotFoundError('Unable to find file "{0}"'.format(apk_path)) + + # Since zipalign cannot be run inplace, a temp file will be created. + apk_copy_path = "{0}.copy.apk".format( + os.path.join( + os.path.dirname(apk_path), + os.path.splitext(os.path.basename(apk_path))[0], + ) + ) + + try: + apk_copy_path = shutil.copy2(apk_path, apk_copy_path) + + align_cmd = [self.zipalign_path, "-p", "-v", "-f", "4", apk_copy_path, apk_path] + + self.logger.info('Running align command "{0}"'.format(" ".join(align_cmd))) + output = subprocess.check_output( + align_cmd, stderr=subprocess.STDOUT + ).strip() + return output.decode(errors="replace") + except subprocess.CalledProcessError as e: + self.logger.error( + "Error during align command: {0}".format( + e.output.decode(errors="replace") if e.output else e + ) + ) + raise + except Exception as e: + self.logger.error("Error during aligning: {0}".format(e)) + raise + finally: + # Remove the temp file used for zipalign. + if os.path.isfile(apk_copy_path): + os.remove(apk_copy_path) + + +class ApkSigner(object): def __init__(self): self.logger = logging.getLogger( "{0}.{1}".format(__name__, self.__class__.__name__) ) - if "JARSIGNER_PATH" in os.environ: - self.jarsigner_path: str = os.environ["JARSIGNER_PATH"] + if "APKSIGNER_PATH" in os.environ: + self.apksigner_path: str = os.environ["APKSIGNER_PATH"] else: - self.jarsigner_path: str = "jarsigner" + self.apksigner_path: str = "apksigner" - full_jarsigner_path = shutil.which(self.jarsigner_path) + full_apksigner_path = shutil.which(self.apksigner_path) # Make sure to use the full path of the executable (needed for cross-platform # compatibility). - if full_jarsigner_path is None: + if full_apksigner_path is None: raise RuntimeError( - 'Something is wrong with executable "{0}"'.format(self.jarsigner_path) + 'Something is wrong with executable "{0}"'.format(self.apksigner_path) ) else: - self.jarsigner_path = full_jarsigner_path + self.apksigner_path = full_apksigner_path def sign( self, @@ -225,24 +288,19 @@ def sign( raise FileNotFoundError('Unable to find file "{0}"'.format(apk_path)) sign_cmd: List[str] = [ - self.jarsigner_path, - "-tsa", - "http://timestamp.comodoca.com/rfc3161", - "-sigalg", - "SHA1withRSA", - "-digestalg", - "SHA1", - "-keystore", + self.apksigner_path, + "sign", + "--ks", keystore_file_path, - "-storepass", - keystore_password, - apk_path, + "--ks-key-alias", key_alias, + "--ks-pass", + f"pass:{keystore_password}", + apk_path, ] - if key_password: - sign_cmd.insert(-2, "-keypass") - sign_cmd.insert(-2, key_password) + sign_cmd.insert(-2, " --key-pass ") + sign_cmd.insert(-2, f"pass:{key_password} ") try: self.logger.info('Running sign command "{0}"'.format(" ".join(sign_cmd))) @@ -310,66 +368,3 @@ def resign( return self.sign( apk_path, keystore_file_path, keystore_password, key_alias, key_password ) - - -class Zipalign(object): - def __init__(self): - self.logger = logging.getLogger( - "{0}.{1}".format(__name__, self.__class__.__name__) - ) - - if "ZIPALIGN_PATH" in os.environ: - self.zipalign_path: str = os.environ["ZIPALIGN_PATH"] - else: - self.zipalign_path: str = "zipalign" - - full_zipalign_path = shutil.which(self.zipalign_path) - - # Make sure to use the full path of the executable (needed for cross-platform - # compatibility). - if full_zipalign_path is None: - raise RuntimeError( - 'Something is wrong with executable "{0}"'.format(self.zipalign_path) - ) - else: - self.zipalign_path = full_zipalign_path - - def align(self, apk_path: str) -> str: - - # Check if the apk file to align is a valid file. - if not os.path.isfile(apk_path): - self.logger.error('Unable to find file "{0}"'.format(apk_path)) - raise FileNotFoundError('Unable to find file "{0}"'.format(apk_path)) - - # Since zipalign cannot be run inplace, a temp file will be created. - apk_copy_path = "{0}.copy.apk".format( - os.path.join( - os.path.dirname(apk_path), - os.path.splitext(os.path.basename(apk_path))[0], - ) - ) - - try: - apk_copy_path = shutil.copy2(apk_path, apk_copy_path) - - align_cmd = [self.zipalign_path, "-v", "-f", "4", apk_copy_path, apk_path] - - self.logger.info('Running align command "{0}"'.format(" ".join(align_cmd))) - output = subprocess.check_output( - align_cmd, stderr=subprocess.STDOUT - ).strip() - return output.decode(errors="replace") - except subprocess.CalledProcessError as e: - self.logger.error( - "Error during align command: {0}".format( - e.output.decode(errors="replace") if e.output else e - ) - ) - raise - except Exception as e: - self.logger.error("Error during aligning: {0}".format(e)) - raise - finally: - # Remove the temp file used for zipalign. - if os.path.isfile(apk_copy_path): - os.remove(apk_copy_path) diff --git a/src/test/test_cli.py b/src/test/test_cli.py index 2d219c7d..42e490fe 100644 --- a/src/test/test_cli.py +++ b/src/test/test_cli.py @@ -25,7 +25,7 @@ def test_valid_basic_command_without_quotes( # Mock the command line parser. arguments = cli.get_cmd_args( "-w {working_dir} -d {destination} " - "-o Rebuild -o NewSignature -o NewAlignment {apk_file}".format( + "-o Rebuild -o NewAlignment -o NewSignature {apk_file}".format( working_dir=tmp_working_directory_path, destination=obfuscated_apk_path, apk_file=tmp_demo_apk_v10_original_path, diff --git a/src/test/test_obfuscation.py b/src/test/test_obfuscation.py index a584ce6b..9c9f3174 100644 --- a/src/test/test_obfuscation.py +++ b/src/test/test_obfuscation.py @@ -49,8 +49,8 @@ def test_perform_full_obfuscation_valid_apk( "Reorder", "RandomManifest", "Rebuild", - "NewSignature", "NewAlignment", + "NewSignature", ], tmp_working_directory_path, obfuscated_apk_path, diff --git a/src/test/test_tool.py b/src/test/test_tool.py index 9b48d282..e9d75fbf 100644 --- a/src/test/test_tool.py +++ b/src/test/test_tool.py @@ -109,23 +109,23 @@ def mock(*args, **kwargs): Apktool().build(tmp_demo_apk_v10_decoded_files_directory_path) -class TestJarsigner(object): - def test_jarsigner_valid_path(self): - jarsigner = Jarsigner() - assert os.path.isfile(jarsigner.jarsigner_path) +class ApkSigner(object): + def test_apksigner_valid_path(self): + apksigner = ApkSigner() + assert os.path.isfile(apksigner.apksigner_path) output = subprocess.check_output( - jarsigner.jarsigner_path, stderr=subprocess.STDOUT + apksigner.apksigner_path, stderr=subprocess.STDOUT ).decode() - assert "usage: jarsigner" in output.lower() + assert "USAGE: apksigner" in output.lower() - def test_jarsigner_wrong_path(self, monkeypatch): - monkeypatch.setenv("JARSIGNER_PATH", "invalid.jarsigner.path") + def test_apksigner_wrong_path(self, monkeypatch): + monkeypatch.setenv("APKSIGNER_PATH", "invalid.apksigner.path") with pytest.raises(RuntimeError): - Jarsigner() + ApkSigner() def test_resign_valid_apk(self, tmp_demo_apk_v10_rebuild_path: str): - output = Jarsigner().resign( + output = ApkSigner().resign( tmp_demo_apk_v10_rebuild_path, os.path.join( os.path.dirname(__file__), @@ -148,7 +148,7 @@ def mock(*args, **kwargs): monkeypatch.setattr("subprocess.check_output", mock) with pytest.raises(Exception): - Jarsigner().resign( + ApkSigner().resign( tmp_demo_apk_v10_original_path, "ignore", "ignore", "ignore" ) @@ -161,13 +161,13 @@ def mock(*args, **kwargs): monkeypatch.setattr("zipfile.ZipFile", mock) with pytest.raises(Exception): - Jarsigner().resign( + ApkSigner().resign( tmp_demo_apk_v10_original_path, "ignore", "ignore", "ignore" ) def test_sign_error_invalid_apk_path(self): with pytest.raises(FileNotFoundError): - Jarsigner().sign("invalid.apk.path", "ignore", "ignore", "ignore") + ApkSigner().sign("invalid.apk.path", "ignore", "ignore", "ignore") def test_sign_error_invalid_file(self, tmp_working_directory_path: str): invalid_file_path = os.path.join(tmp_working_directory_path, "invalid.apk") @@ -176,11 +176,11 @@ def test_sign_error_invalid_file(self, tmp_working_directory_path: str): invalid_file.write("This is not an apk file\n") with pytest.raises(subprocess.CalledProcessError): - Jarsigner().sign(invalid_file_path, "ignore", "ignore", "ignore") + ApkSigner().sign(invalid_file_path, "ignore", "ignore", "ignore") def test_sign_error_invalid_key_password(self, tmp_demo_apk_v10_rebuild_path: str): with pytest.raises(subprocess.CalledProcessError): - Jarsigner().sign( + ApkSigner().sign( tmp_demo_apk_v10_rebuild_path, os.path.join( os.path.dirname(__file__), From fe4f4ceea963a8d880152042cf4d17f889b253e8 Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 12:27:08 +0200 Subject: [PATCH 02/10] add verbose option to apksigner and add test case to apksigner --- src/obfuscapk/tool.py | 1 + src/test/test_tool.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/obfuscapk/tool.py b/src/obfuscapk/tool.py index edb89f62..1bd59470 100644 --- a/src/obfuscapk/tool.py +++ b/src/obfuscapk/tool.py @@ -290,6 +290,7 @@ def sign( sign_cmd: List[str] = [ self.apksigner_path, "sign", + "-v" "--ks", keystore_file_path, "--ks-key-alias", diff --git a/src/test/test_tool.py b/src/test/test_tool.py index e9d75fbf..ea329857 100644 --- a/src/test/test_tool.py +++ b/src/test/test_tool.py @@ -137,7 +137,7 @@ def test_resign_valid_apk(self, tmp_demo_apk_v10_rebuild_path: str): "obfuscation_password", "obfuscation_key", ) - assert "jar signed" in output.lower() + assert "Signed" in output.lower() def test_resign_error_generic( self, tmp_demo_apk_v10_original_path: str, monkeypatch From 0326df17c76e80b1c371f66e56f8aedf0312778c Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 13:03:55 +0200 Subject: [PATCH 03/10] fix error import JarSigner --- docs/TROUBLESHOOTING.md | 2 +- src/obfuscapk/main.py | 2 +- src/obfuscapk/obfuscation.py | 4 ++-- src/test/test_tool.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 32c2de60..15c37101 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -30,7 +30,7 @@ from Docker Hub. If you are not using the Docker image, make sure to install and setup properly the additional tools needed for Obfuscapk to work: [`apktool`](https://ibotpeaches.github.io/Apktool/), -[`jarsigner`](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html) +[`apksigner`](https://developer.android.com/studio/command-line/apksigner) and [`zipalign`](https://developer.android.com/studio/command-line/zipalign). Please ensure to be using a recent release of [`apktool`](https://ibotpeaches.github.io/Apktool/) (some systems, like Kali Linux, diff --git a/src/obfuscapk/main.py b/src/obfuscapk/main.py index ca4f3489..d5083fb8 100644 --- a/src/obfuscapk/main.py +++ b/src/obfuscapk/main.py @@ -32,7 +32,7 @@ def check_external_tool_dependencies(): """ Make sure all the external needed tools are available and ready to be used. """ - # APKTOOL_PATH, JARSIGNER_PATH and ZIPALIGN_PATH environment variables can be + # APKTOOL_PATH, APKSIGNER_PATH and ZIPALIGN_PATH environment variables can be # used to specify the location of the external tools (make sure they have the # execute permission). If there is a problem with any of the executables below, # an exception will be thrown by the corresponding constructor. diff --git a/src/obfuscapk/obfuscation.py b/src/obfuscapk/obfuscation.py index 4f3f1141..6c235ac7 100644 --- a/src/obfuscapk/obfuscation.py +++ b/src/obfuscapk/obfuscation.py @@ -7,7 +7,7 @@ from typing import List, Union from obfuscapk import util -from obfuscapk.tool import Apktool, Jarsigner, Zipalign, ApkSigner +from obfuscapk.tool import Apktool, Zipalign, ApkSigner class Obfuscation(object): @@ -510,7 +510,7 @@ def sign_obfuscated_apk(self) -> None: # This method must be called AFTER the obfuscated apk has been built. - # The obfuscated apk will be signed with jarsigner. + # The obfuscated apk will be signed with apksigner. apksigner: ApkSigner = ApkSigner() # If a custom keystore file is not provided, use the default one bundled with diff --git a/src/test/test_tool.py b/src/test/test_tool.py index ea329857..3fffe0d9 100644 --- a/src/test/test_tool.py +++ b/src/test/test_tool.py @@ -5,7 +5,7 @@ import pytest -from obfuscapk.tool import Apktool, Jarsigner, Zipalign +from obfuscapk.tool import Apktool, ApkSigner, Zipalign # noinspection PyUnresolvedReferences from test.test_fixtures import ( From eeccaeb07c21b4ed904942b590f8c641973e2fc7 Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 13:10:19 +0200 Subject: [PATCH 04/10] fix error import JarSigner --- src/obfuscapk/tool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obfuscapk/tool.py b/src/obfuscapk/tool.py index 1bd59470..09500013 100644 --- a/src/obfuscapk/tool.py +++ b/src/obfuscapk/tool.py @@ -290,7 +290,7 @@ def sign( sign_cmd: List[str] = [ self.apksigner_path, "sign", - "-v" + "-v", "--ks", keystore_file_path, "--ks-key-alias", From e4de7b21116c5f42cd02030be9db592c14e88e57 Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 13:21:58 +0200 Subject: [PATCH 05/10] fix inserting error keypass --- src/obfuscapk/tool.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/obfuscapk/tool.py b/src/obfuscapk/tool.py index 09500013..43dd98bb 100644 --- a/src/obfuscapk/tool.py +++ b/src/obfuscapk/tool.py @@ -228,7 +228,15 @@ def align(self, apk_path: str) -> str: try: apk_copy_path = shutil.copy2(apk_path, apk_copy_path) - align_cmd = [self.zipalign_path, "-p", "-v", "-f", "4", apk_copy_path, apk_path] + align_cmd = [ + self.zipalign_path, + "-p", + "-v", + "-f", + "4", + apk_copy_path, + apk_path, + ] self.logger.info('Running align command "{0}"'.format(" ".join(align_cmd))) output = subprocess.check_output( @@ -299,9 +307,11 @@ def sign( f"pass:{keystore_password}", apk_path, ] + + self.logger.error(sign_cmd) if key_password: - sign_cmd.insert(-2, " --key-pass ") - sign_cmd.insert(-2, f"pass:{key_password} ") + sign_cmd.insert(-1, "--key-pass") + sign_cmd.insert(-1, f"pass:{key_password}") try: self.logger.info('Running sign command "{0}"'.format(" ".join(sign_cmd))) From ef9bb80886bf3cbc5b1dbbd8f4e15309dd060c56 Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 13:30:04 +0200 Subject: [PATCH 06/10] fix name testool --- src/test/test_tool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test_tool.py b/src/test/test_tool.py index 3fffe0d9..d201a558 100644 --- a/src/test/test_tool.py +++ b/src/test/test_tool.py @@ -109,7 +109,7 @@ def mock(*args, **kwargs): Apktool().build(tmp_demo_apk_v10_decoded_files_directory_path) -class ApkSigner(object): +class TestApkSigner(object): def test_apksigner_valid_path(self): apksigner = ApkSigner() assert os.path.isfile(apksigner.apksigner_path) From f7ecaa2df3cf190f74bc2510064e70b64c7a1cf0 Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 13:34:46 +0200 Subject: [PATCH 07/10] fix name testool --- src/test/test_tool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test_tool.py b/src/test/test_tool.py index d201a558..93d87741 100644 --- a/src/test/test_tool.py +++ b/src/test/test_tool.py @@ -137,7 +137,7 @@ def test_resign_valid_apk(self, tmp_demo_apk_v10_rebuild_path: str): "obfuscation_password", "obfuscation_key", ) - assert "Signed" in output.lower() + assert "signed" in output.lower() def test_resign_error_generic( self, tmp_demo_apk_v10_original_path: str, monkeypatch From d6891c34edc62a1ae1ef32d488f8ab92c5f56a01 Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 13:36:47 +0200 Subject: [PATCH 08/10] fix name usage apksigner --- src/test/test_tool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/test_tool.py b/src/test/test_tool.py index 93d87741..e02b1783 100644 --- a/src/test/test_tool.py +++ b/src/test/test_tool.py @@ -117,7 +117,7 @@ def test_apksigner_valid_path(self): output = subprocess.check_output( apksigner.apksigner_path, stderr=subprocess.STDOUT ).decode() - assert "USAGE: apksigner" in output.lower() + assert "usage: apksigner" in output.lower() def test_apksigner_wrong_path(self, monkeypatch): monkeypatch.setenv("APKSIGNER_PATH", "invalid.apksigner.path") From c190ca02e83c6a77d1a7a507762582045fa5bc0b Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 13:48:16 +0200 Subject: [PATCH 09/10] remove logger error --- src/obfuscapk/tool.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/obfuscapk/tool.py b/src/obfuscapk/tool.py index 43dd98bb..6ff49304 100644 --- a/src/obfuscapk/tool.py +++ b/src/obfuscapk/tool.py @@ -308,7 +308,6 @@ def sign( apk_path, ] - self.logger.error(sign_cmd) if key_password: sign_cmd.insert(-1, "--key-pass") sign_cmd.insert(-1, f"pass:{key_password}") From df086182acbfbf3385791e78f0d977ef8a83c8c1 Mon Sep 17 00:00:00 2001 From: Davide Caputo Date: Mon, 12 Apr 2021 14:32:38 +0200 Subject: [PATCH 10/10] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f69278aa..f0ad232f 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ Copyright (C) 2009 The Android Open Source Project ``` To install and use `apktool` you need a recent version of Java. -`zipalign` and `apksigner` is included in the Android SDK. The location of the +`zipalign` and `apksigner` are included in the Android SDK. The location of the executables can also be specified through the following environment variables: `APKTOOL_PATH`, `APKSIGNER_PATH` and `ZIPALIGN_PATH` (e.g., in Ubuntu, run `export APKTOOL_PATH=/custom/location/apktool` before running Obfuscapk in the same