diff --git a/qark/apk_builder.py b/qark/apk_builder.py index b9e31f1d..767ab398 100644 --- a/qark/apk_builder.py +++ b/qark/apk_builder.py @@ -2,9 +2,9 @@ import logging import os -import shlex import shutil import subprocess +import platform from six import StringIO from six.moves import configparser @@ -25,6 +25,9 @@ EXPLOIT_APK_TEMPLATE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "exploit_apk") +OS = platform.system() + +GRADLEW_NAME = "./gradlew" if OS != "Windows" else "gradlew.bat" class APKBuilder(object): __instance = None @@ -44,12 +47,13 @@ def __init__(self, exploit_apk_path, issues, apk_name, manifest_path, sdk_path): :param str apk_name: name of the examined APK """ self.exploit_apk_path = os.path.join(exploit_apk_path, "{apk_name}_exploit_apk".format(apk_name=apk_name)) - + log.debug("Exploit APK Path") + log.debug(self.exploit_apk_path) # need to remove directory if it exists otherwise shutil.copytree will error from helper if os.path.isdir(self.exploit_apk_path): shutil.rmtree(self.exploit_apk_path) - # copy template exploit APK to exploit location + # copy template exploit APK to exploit location+ try: copy_directory_to_location(directory_to_copy=EXPLOIT_APK_TEMPLATE_PATH, destination=self.exploit_apk_path) except Exception: @@ -110,11 +114,11 @@ def _build_apk(self): os.chdir(self.exploit_apk_path) write_key_value_to_xml('packageName', self.package_name, self.strings_xml_path) self._write_properties_file({"sdk.dir": self.sdk_path}) - command = "./gradlew assembleDebug" + command = "{} assembleDebug".format(GRADLEW_NAME) try: - subprocess.call(shlex.split(command)) + subprocess.call(command,shell=True) except Exception: - log.exception("Error running command %s") + log.exception("Error running command {}".format(command)) raise # raise here as we can still make the report for the user except Exception: raise diff --git a/qark/decompiler/decompiler.py b/qark/decompiler/decompiler.py index 216362c2..bfed403e 100644 --- a/qark/decompiler/decompiler.py +++ b/qark/decompiler/decompiler.py @@ -26,9 +26,9 @@ DECOMPILERS_PATH = os.path.join(LIB_PATH, "decompilers") -APK_TOOL_COMMAND = ("java -Djava.awt.headless=true -jar {apktool_path}/apktool.jar " - "d {path_to_source} --no-src --force -m --output {build_directory}") -DEX2JAR_COMMAND = "{dex2jar_path} {path_to_dex} -o {build_apk}.jar" +APK_TOOL_COMMAND = ("java -Djava.awt.headless=true -jar \"{apktool_path}/apktool.jar\" " + "d \"{path_to_source}\" --no-src --force -m --output \"{build_directory}\"") +DEX2JAR_COMMAND = "{dex2jar_path} \"{path_to_dex}\" -o \"{build_apk}.jar\"" def escape_windows_path(path): @@ -111,13 +111,12 @@ def _decompiler_function(self, decompiler): log.debug(".jar file path not found, trying to create dex file.") self.jar_path = self._run_dex2jar() - decompiler_command = escape_windows_path( - decompiler.command.format(path_to_decompiler=decompiler.path_to_decompiler, - jar=self.jar_path, - build_directory=self.build_directory)) + decompiler_command = decompiler.command.format(path_to_decompiler=decompiler.path_to_decompiler, + jar=self.jar_path, + build_directory=self.build_directory) try: - retcode = subprocess.call(shlex.split(decompiler_command)) + retcode = subprocess.call(decompiler_command,shell=True) except Exception: log.exception("%s failed to finish decompiling, continuing", decompiler.name) else: @@ -145,14 +144,14 @@ def run_apktool(self): configure_apktool() - custom_apktool_command = escape_windows_path(APK_TOOL_COMMAND.format(apktool_path=APK_TOOL_PATH, - path_to_source=self.path_to_source, - build_directory=os.path.join( - self.build_directory, "apktool"))) + custom_apktool_command = APK_TOOL_COMMAND.format(apktool_path=APK_TOOL_PATH, + path_to_source=self.path_to_source, + build_directory=os.path.join( + self.build_directory, "apktool")) log.debug("Calling APKTool with following command") log.debug(custom_apktool_command) try: - subprocess.call(shlex.split(custom_apktool_command)) + subprocess.call(custom_apktool_command,shell=True) except Exception: log.exception("Failed to run APKTool with command: %s", custom_apktool_command) raise SystemExit("Failed to run APKTool") @@ -194,16 +193,16 @@ def _run_dex2jar(self): configure_dex2jar() - dex2jar_command = escape_windows_path(DEX2JAR_COMMAND.format(dex2jar_path=os.path.join(DEX2JAR_PATH, - "d2j-dex2jar.{extension}".format( - extension=DEX2JAR_EXTENSION)), - path_to_dex=self.dex_path, - build_apk=os.path.join(self.build_directory, - self.apk_name))) + dex2jar_command = DEX2JAR_COMMAND.format(dex2jar_path=os.path.join(DEX2JAR_PATH, + "d2j-dex2jar.{extension}".format( + extension=DEX2JAR_EXTENSION)), + path_to_dex=self.dex_path, + build_apk=os.path.join(self.build_directory, + self.apk_name)) log.debug("Running dex2jar with command %s", dex2jar_command) try: - ret_code = subprocess.call(shlex.split(dex2jar_command)) + ret_code = subprocess.call(dex2jar_command,shell=True) if ret_code != 0: log.critical("Error running dex2jar command: %s", dex2jar_command) raise SystemExit("Error running dex2jar") diff --git a/qark/decompiler/external_decompiler.py b/qark/decompiler/external_decompiler.py index 47d6a27f..9e44739d 100644 --- a/qark/decompiler/external_decompiler.py +++ b/qark/decompiler/external_decompiler.py @@ -19,7 +19,7 @@ def __init__(self): ExternalDecompiler.__init__(self, name="cfr", path_to_decompiler=os.path.join(PATH_TO_DECOMPILERS, "cfr_0_124.jar"), - command="java -jar {path_to_decompiler} {jar} --outputdir {build_directory}/cfr") + command="java -jar \"{path_to_decompiler}\" \"{jar}\" --outputdir \"{build_directory}/cfr\"") class Procyon(ExternalDecompiler): @@ -28,7 +28,7 @@ def __init__(self): name="procyon", path_to_decompiler=os.path.join(PATH_TO_DECOMPILERS, "procyon-decompiler-1.0.jar"), - command="java -jar {path_to_decompiler} {jar} -o {build_directory}/procyon") + command="java -jar \"{path_to_decompiler}\" \"{jar}\" -o \"{build_directory}/procyon\"") class Fernflower(ExternalDecompiler): @@ -37,7 +37,7 @@ def __init__(self): name="fernflower", path_to_decompiler=os.path.join(PATH_TO_DECOMPILERS, "fernflower.jar"), - command="java -jar {path_to_decompiler} -ren=1 {jar} {build_directory}/fernflower") + command="java -jar \"{path_to_decompiler}\" -ren=1 \"{jar}\" \"{build_directory}/fernflower\"") DECOMPILERS = (CFR(), Procyon(), Fernflower()) diff --git a/qark/qark.py b/qark/qark.py index 88cf6a2a..6ce11eeb 100644 --- a/qark/qark.py +++ b/qark/qark.py @@ -49,9 +49,13 @@ help="report output path.", show_default=True) @click.option("--keep-report/--no-keep-report", default=False, help="Append to final report file.", show_default=True) +@click.option("--bypass-decompile/--no-bypass-decompile", default=False, + help="Resume after the decompilation", show_default=True) +@click.option("--report/--no-report", default=False, + help="Resume after the decompilation", show_default=True) @click.version_option() @click.pass_context -def cli(ctx, sdk_path, build_path, debug, source, report_type, exploit_apk, report_path, keep_report): +def cli(ctx, sdk_path, build_path, debug, source, report_type, exploit_apk, report_path, keep_report, bypass_decompile,report): if not source: click.secho("Please pass a source for scanning through either --java or --apk") click.secho(ctx.get_help()) @@ -74,6 +78,7 @@ def cli(ctx, sdk_path, build_path, debug, source, report_type, exploit_apk, repo else: click.secho("Please provide path to android SDK if building exploit APK.") return + sdk_path = sdk_path.replace("\\","\\\\") #Test for build # Debug controls the output to stderr, debug logs are ALWAYS stored in `qark_debug.log` if debug: @@ -83,9 +88,12 @@ def cli(ctx, sdk_path, build_path, debug, source, report_type, exploit_apk, repo initialize_logging(level) - click.secho("Decompiling...") decompiler = Decompiler(path_to_source=source, build_directory=build_path) - decompiler.run() + if bypass_decompile: + click.secho("Skipping decompilation...") + else: + click.secho("Decompiling...") + decompiler.run() click.secho("Running scans...") path_to_source = decompiler.path_to_source if decompiler.source_code else decompiler.build_directory @@ -94,10 +102,11 @@ def cli(ctx, sdk_path, build_path, debug, source, report_type, exploit_apk, repo scanner.run() click.secho("Finish scans...") - click.secho("Writing report...") - report = Report(issues=set(scanner.issues), report_path=report_path, keep_report=keep_report) - report_path = report.generate(file_type=report_type) - click.secho("Finish writing report to {report_path} ...".format(report_path=report_path)) + if report: + click.secho("Writing report...") + report = Report(issues=set(scanner.issues), report_path=report_path, keep_report=keep_report) + report_path = report.generate(file_type=report_type) + click.secho("Finish writing report to {report_path} ...".format(report_path=report_path)) if exploit_apk: click.secho("Building exploit APK...")