diff --git a/mvt/android/cli.py b/mvt/android/cli.py index 945277f..a291539 100644 --- a/mvt/android/cli.py +++ b/mvt/android/cli.py @@ -28,7 +28,7 @@ log = logging.getLogger(__name__) # Help messages of repeating options. OUTPUT_HELP_MESSAGE = "Specify a path to a folder where you want to store JSON results" - +SERIAL_HELP_MESSAGE = "Specify a device serial number or HOST:PORT connection string" #============================================================================== # Main @@ -42,6 +42,7 @@ def cli(): # Download APKs #============================================================================== @cli.command("download-apks", help="Download all or non-safelisted installed APKs installed on the device") +@click.option("--serial", "-s", type=str, help=SERIAL_HELP_MESSAGE) @click.option("--all-apks", "-a", is_flag=True, help="Extract all packages installed on the phone, even those marked as safe") @click.option("--virustotal", "-v", is_flag=True, help="Check packages on VirusTotal") @@ -51,7 +52,6 @@ def cli(): help="Specify a path to a folder where you want to store the APKs") @click.option("--from-file", "-f", type=click.Path(exists=True), help="Instead of acquiring from phone, load an existing packages.json file for lookups (mainly for debug purposes)") -@click.option("--serial", "-s", type=str, help="Use the Android device with a given serial number") def download_apks(all_apks, virustotal, koodous, all_checks, output, from_file, serial): try: if from_file: @@ -64,7 +64,9 @@ def download_apks(all_apks, virustotal, koodous, all_checks, output, from_file, log.critical("Unable to create output folder %s: %s", output, e) sys.exit(-1) - download = DownloadAPKs(output_folder=output, all_apks=all_apks, serial=serial) + download = DownloadAPKs(output_folder=output, all_apks=all_apks) + if serial: + download.serial = serial download.run() packages = download.packages @@ -86,12 +88,12 @@ def download_apks(all_apks, virustotal, koodous, all_checks, output, from_file, # Checks through ADB #============================================================================== @cli.command("check-adb", help="Check an Android device over adb") +@click.option("--serial", "-s", type=str, help=SERIAL_HELP_MESSAGE) @click.option("--iocs", "-i", type=click.Path(exists=True), help="Path to indicators file") @click.option("--output", "-o", type=click.Path(exists=False), help="Specify a path to a folder where you want to store JSON results") @click.option("--list-modules", "-l", is_flag=True, help="Print list of available modules and exit") @click.option("--module", "-m", help="Name of a single module you would like to run instead of all") -@click.option("--serial", "-s", type=str, help="Use the Android device with a given serial") def check_adb(iocs, output, list_modules, module, serial): if list_modules: log.info("Following is the list of available check-adb modules:") @@ -120,7 +122,9 @@ def check_adb(iocs, output, list_modules, module, serial): if module and adb_module.__name__ != module: continue - m = adb_module(output_folder=output, serial=serial, log=logging.getLogger(adb_module.__module__)) + m = adb_module(output_folder=output, log=logging.getLogger(adb_module.__module__)) + if serial: + m.serial = serial if iocs: indicators.log = m.log @@ -140,9 +144,9 @@ def check_adb(iocs, output, list_modules, module, serial): # Check ADB backup #============================================================================== @cli.command("check-backup", help="Check an Android Backup") +@click.option("--serial", "-s", type=str, help=SERIAL_HELP_MESSAGE) @click.option("--iocs", "-i", type=click.Path(exists=True), help="Path to indicators file") @click.option("--output", "-o", type=click.Path(exists=False), help=OUTPUT_HELP_MESSAGE) -@click.option("--serial", "-s", type=str, help="Use the Android device with a given serial") @click.argument("BACKUP_PATH", type=click.Path(exists=True)) def check_backup(iocs, output, backup_path, serial): log.info("Checking ADB backup located at: %s", backup_path) @@ -169,7 +173,10 @@ def check_backup(iocs, output, backup_path, serial): for module in BACKUP_MODULES: m = module(base_folder=backup_path, output_folder=output, - serial=serial, log=logging.getLogger(module.__module__)) + log=logging.getLogger(module.__module__)) + + if serial: + m.serial = serial if iocs: indicators.log = m.log diff --git a/mvt/android/download_apks.py b/mvt/android/download_apks.py index 3ac03c2..8cfe6b8 100644 --- a/mvt/android/download_apks.py +++ b/mvt/android/download_apks.py @@ -40,16 +40,11 @@ class DownloadAPKs(AndroidExtraction): """DownloadAPKs is the main class operating the download of APKs from the device.""" - def __init__(self, output_folder=None, all_apks=False, packages=None, serial=None): - """Initialize module. - :param output_folder: Path to the folder where data should be stored - :param all_apks: Boolean indicating whether to download all packages - or filter known-goods - :param packages: Provided list of packages, typically for JSON checks - :param serial: The USB device serial ID - """ - super().__init__(file_path=None, base_folder=None, - output_folder=output_folder, serial=serial) + def __init__(self, file_path=None, base_folder=None, output_folder=None, + serial=None, fast_mode=False, log=None, results=[]): + super().__init__(file_path=file_path, base_folder=base_folder, + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) self.output_folder_apk = None self.packages = packages or [] diff --git a/mvt/android/modules/adb/base.py b/mvt/android/modules/adb/base.py index 338445e..71832e5 100644 --- a/mvt/android/modules/adb/base.py +++ b/mvt/android/modules/adb/base.py @@ -27,19 +27,19 @@ class AndroidExtraction(MVTModule): """This class provides a base for all Android extraction modules.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - serial=None, fast_mode=False, log=None, results=[]): + fast_mode=False, log=None, results=[]): """Initialize Android extraction module. :param file_path: Path to the database file to parse :param base_folder: Path to a base folder containing an Android dump :param output_folder: Path to the folder where to store extraction results - :param serial: The USB device serial ID """ super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) self.device = None + self.serial = None def _adb_check_keys(self): """Make sure Android adb keys exist. @@ -60,15 +60,18 @@ class AndroidExtraction(MVTModule): signer = PythonRSASigner("", priv_key) - if self.serial is None or ":" not in self.serial: + # If no serial was specified or if the serial does not seem to be + # a HOST:PORT definition, we use the USB transport. + if not self.serial or ":" not in self.serial: self.device = AdbDeviceUsb(serial=self.serial) + # Otherwise we try to use the TCP transport. else: addr = self.serial.split(":") - if len(addr) < 2: raise ValueError("TCP serial number must follow the format: `address:port`") - self.device = AdbDeviceTcp(addr[0], int(addr[1]), default_transport_timeout_s=9.) + self.device = AdbDeviceTcp(addr[0], int(addr[1]), + default_transport_timeout_s=30.) while True: try: diff --git a/mvt/android/modules/adb/chrome_history.py b/mvt/android/modules/adb/chrome_history.py index a09a27b..f163147 100644 --- a/mvt/android/modules/adb/chrome_history.py +++ b/mvt/android/modules/adb/chrome_history.py @@ -22,8 +22,8 @@ class ChromeHistory(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def serialize(self, record): return { diff --git a/mvt/android/modules/adb/dumpsys_batterystats.py b/mvt/android/modules/adb/dumpsys_batterystats.py index 8e66180..b804c2f 100644 --- a/mvt/android/modules/adb/dumpsys_batterystats.py +++ b/mvt/android/modules/adb/dumpsys_batterystats.py @@ -16,8 +16,8 @@ class DumpsysBatterystats(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def run(self): self._adb_connect() diff --git a/mvt/android/modules/adb/dumpsys_packages.py b/mvt/android/modules/adb/dumpsys_packages.py index a6cd1fe..3e87769 100644 --- a/mvt/android/modules/adb/dumpsys_packages.py +++ b/mvt/android/modules/adb/dumpsys_packages.py @@ -16,8 +16,8 @@ class DumpsysPackages(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def run(self): self._adb_connect() diff --git a/mvt/android/modules/adb/dumpsys_procstats.py b/mvt/android/modules/adb/dumpsys_procstats.py index 2a5c203..a2a69c7 100644 --- a/mvt/android/modules/adb/dumpsys_procstats.py +++ b/mvt/android/modules/adb/dumpsys_procstats.py @@ -16,8 +16,8 @@ class DumpsysProcstats(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def run(self): self._adb_connect() diff --git a/mvt/android/modules/adb/packages.py b/mvt/android/modules/adb/packages.py index 09cc7a0..54d1158 100644 --- a/mvt/android/modules/adb/packages.py +++ b/mvt/android/modules/adb/packages.py @@ -18,8 +18,8 @@ class Packages(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def serialize(self, record): records = [] diff --git a/mvt/android/modules/adb/processes.py b/mvt/android/modules/adb/processes.py index 2f4dbf8..6350416 100644 --- a/mvt/android/modules/adb/processes.py +++ b/mvt/android/modules/adb/processes.py @@ -15,8 +15,8 @@ class Processes(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def run(self): self._adb_connect() diff --git a/mvt/android/modules/adb/rootbinaries.py b/mvt/android/modules/adb/rootbinaries.py index c6ff128..65e45dd 100644 --- a/mvt/android/modules/adb/rootbinaries.py +++ b/mvt/android/modules/adb/rootbinaries.py @@ -18,8 +18,8 @@ class RootBinaries(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def run(self): root_binaries_path = os.path.join("..", "..", "data", "root_binaries.txt") diff --git a/mvt/android/modules/adb/sms.py b/mvt/android/modules/adb/sms.py index d384833..5db5652 100644 --- a/mvt/android/modules/adb/sms.py +++ b/mvt/android/modules/adb/sms.py @@ -45,8 +45,8 @@ class SMS(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def serialize(self, record): text = record["text"].replace("\n", "\\n") diff --git a/mvt/android/modules/adb/whatsapp.py b/mvt/android/modules/adb/whatsapp.py index 28d7518..7a8fe37 100644 --- a/mvt/android/modules/adb/whatsapp.py +++ b/mvt/android/modules/adb/whatsapp.py @@ -22,8 +22,8 @@ class Whatsapp(AndroidExtraction): def __init__(self, file_path=None, base_folder=None, output_folder=None, serial=None, fast_mode=False, log=None, results=[]): super().__init__(file_path=file_path, base_folder=base_folder, - output_folder=output_folder, serial=serial, - fast_mode=fast_mode, log=log, results=results) + output_folder=output_folder, fast_mode=fast_mode, + log=log, results=results) def serialize(self, record): text = record["data"].replace("\n", "\\n")