Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions qark/apk_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand Down
39 changes: 19 additions & 20 deletions qark/decompiler/decompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
6 changes: 3 additions & 3 deletions qark/decompiler/external_decompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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):
Expand All @@ -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())
23 changes: 16 additions & 7 deletions qark/qark.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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...")
Expand Down