From ccf0f3f18eb146703da0add4d302750b02dd18de Mon Sep 17 00:00:00 2001 From: Hamza Z Date: Wed, 21 Jul 2021 13:17:58 +0200 Subject: [PATCH] Add Android device serial specification --- mvt/android/cli.py | 15 +++++++++------ mvt/android/download_apks.py | 5 +++-- mvt/android/modules/adb/base.py | 10 ++++++---- mvt/android/modules/adb/chrome_history.py | 6 +++--- mvt/android/modules/adb/dumpsys_batterystats.py | 6 +++--- mvt/android/modules/adb/dumpsys_packages.py | 6 +++--- mvt/android/modules/adb/dumpsys_procstats.py | 6 +++--- mvt/android/modules/adb/packages.py | 6 +++--- mvt/android/modules/adb/processes.py | 6 +++--- mvt/android/modules/adb/rootbinaries.py | 6 +++--- mvt/android/modules/adb/sms.py | 6 +++--- mvt/android/modules/adb/whatsapp.py | 6 +++--- mvt/common/module.py | 4 +++- 13 files changed, 48 insertions(+), 40 deletions(-) diff --git a/mvt/android/cli.py b/mvt/android/cli.py index eccf9e1..f8c37a8 100644 --- a/mvt/android/cli.py +++ b/mvt/android/cli.py @@ -49,7 +49,8 @@ def cli(): help="Specify a path to a folder where you want to store JSON results") @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)") -def download_apks(all_apks, virustotal, koodous, all_checks, output, from_file): +@click.option("--serial", "-s", type=str, help="Use the Android device with a given serial") +def download_apks(all_apks, virustotal, koodous, all_checks, output, from_file, serial): try: if from_file: download = DownloadAPKs.from_json(from_file) @@ -58,7 +59,7 @@ def download_apks(all_apks, virustotal, koodous, all_checks, output, from_file): log.critical("You need to specify an output folder (with --output, -o) when extracting APKs from a device") sys.exit(-1) - download = DownloadAPKs(output_folder=output, all_apks=all_apks) + download = DownloadAPKs(output_folder=output, all_apks=all_apks, serial=serial) download.run() packages = download.packages @@ -85,7 +86,8 @@ def download_apks(all_apks, virustotal, koodous, all_checks, output, from_file): 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") -def check_adb(iocs, output, list_modules, module): +@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:") for adb_module in ADB_MODULES: @@ -106,7 +108,7 @@ def check_adb(iocs, output, list_modules, module): if module and adb_module.__name__ != module: continue - m = adb_module(output_folder=output, log=logging.getLogger(adb_module.__module__)) + m = adb_module(output_folder=output, serial=serial, log=logging.getLogger(adb_module.__module__)) if iocs: indicators.log = m.log @@ -128,8 +130,9 @@ def check_adb(iocs, output, list_modules, module): @cli.command("check-backup", help="Check an Android Backup") @click.option("--iocs", "-i", type=click.Path(exists=True), help="Path to indicators file") @click.option("--output", "-o", type=click.Path(exists=True), 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): +def check_backup(iocs, output, backup_path, serial): log.info("Checking ADB backup located at: %s", backup_path) if iocs: @@ -147,7 +150,7 @@ def check_backup(iocs, output, backup_path): for module in BACKUP_MODULES: m = module(base_folder=backup_path, output_folder=output, - log=logging.getLogger(module.__module__)) + serial=serial, log=logging.getLogger(module.__module__)) if iocs: indicators.log = m.log diff --git a/mvt/android/download_apks.py b/mvt/android/download_apks.py index 5dd4cbc..6420c5e 100644 --- a/mvt/android/download_apks.py +++ b/mvt/android/download_apks.py @@ -38,15 +38,16 @@ 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): + 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) + output_folder=output_folder, serial=serial) 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 31aa931..e39fcf9 100644 --- a/mvt/android/modules/adb/base.py +++ b/mvt/android/modules/adb/base.py @@ -25,16 +25,17 @@ 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, - fast_mode=False, log=None, results=[]): + serial=None, 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, fast_mode=fast_mode, - log=log, results=results) + output_folder=output_folder, serial=serial, + fast_mode=fast_mode, log=log, results=results) self.device = None @@ -56,7 +57,8 @@ class AndroidExtraction(MVTModule): priv_key = handle.read() signer = PythonRSASigner("", priv_key) - self.device = AdbDeviceUsb() + + self.device = AdbDeviceUsb(serial=self.serial) while True: try: diff --git a/mvt/android/modules/adb/chrome_history.py b/mvt/android/modules/adb/chrome_history.py index 6b223d2..b02a86d 100644 --- a/mvt/android/modules/adb/chrome_history.py +++ b/mvt/android/modules/adb/chrome_history.py @@ -19,10 +19,10 @@ class ChromeHistory(AndroidExtraction): """This module extracts records from Android's Chrome browsing history.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + 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 ad90027..986161f 100644 --- a/mvt/android/modules/adb/dumpsys_batterystats.py +++ b/mvt/android/modules/adb/dumpsys_batterystats.py @@ -14,10 +14,10 @@ class DumpsysBatterystats(AndroidExtraction): """This module extracts stats on battery consumption by processes.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + 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 45fbf68..b1b5260 100644 --- a/mvt/android/modules/adb/dumpsys_packages.py +++ b/mvt/android/modules/adb/dumpsys_packages.py @@ -14,10 +14,10 @@ class DumpsysPackages(AndroidExtraction): """This module extracts stats on installed packages.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + 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 416f01f..7fece74 100644 --- a/mvt/android/modules/adb/dumpsys_procstats.py +++ b/mvt/android/modules/adb/dumpsys_procstats.py @@ -14,10 +14,10 @@ class DumpsysProcstats(AndroidExtraction): """This module extracts stats on memory consumption by processes.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + 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 dcdc375..fa87de9 100644 --- a/mvt/android/modules/adb/packages.py +++ b/mvt/android/modules/adb/packages.py @@ -15,10 +15,10 @@ class Packages(AndroidExtraction): """This module extracts the list of installed packages.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + 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 0be051b..0052abf 100644 --- a/mvt/android/modules/adb/processes.py +++ b/mvt/android/modules/adb/processes.py @@ -13,10 +13,10 @@ class Processes(AndroidExtraction): """This module extracts details on running processes.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + 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 b591603..1804e81 100644 --- a/mvt/android/modules/adb/rootbinaries.py +++ b/mvt/android/modules/adb/rootbinaries.py @@ -15,10 +15,10 @@ class RootBinaries(AndroidExtraction): """This module extracts the list of installed packages.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + 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 dcaccac..9b0c431 100644 --- a/mvt/android/modules/adb/sms.py +++ b/mvt/android/modules/adb/sms.py @@ -18,10 +18,10 @@ class SMS(AndroidExtraction): """This module extracts all SMS messages containing links.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + 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 6d369d6..68db6c2 100644 --- a/mvt/android/modules/adb/whatsapp.py +++ b/mvt/android/modules/adb/whatsapp.py @@ -18,10 +18,10 @@ class Whatsapp(AndroidExtraction): """This module extracts all WhatsApp messages containing links.""" def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + 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) + output_folder=output_folder, serial=serial, + fast_mode=fast_mode, log=log, results=results) def serialize(self, record): text = record["data"].replace("\n", "\\n") diff --git a/mvt/common/module.py b/mvt/common/module.py index 7b6acac..7e287e3 100644 --- a/mvt/common/module.py +++ b/mvt/common/module.py @@ -20,11 +20,12 @@ class MVTModule(object): slug = None def __init__(self, file_path=None, base_folder=None, output_folder=None, - fast_mode=False, log=None, results=[]): + serial=None, fast_mode=False, log=None, results=[]): """Initialize module. :param file_path: Path to the module's database file, if there is any. :param base_folder: Path to the base folder (backup or filesystem dump) :param output_folder: Folder where results will be stored + :param serial: The USB device serial ID :param fast_mode: Flag to enable or disable slow modules :param log: Handle to logger :param results: Provided list of results entries @@ -32,6 +33,7 @@ class MVTModule(object): self.file_path = file_path self.base_folder = base_folder self.output_folder = output_folder + self.serial= serial self.fast_mode = fast_mode self.log = log self.indicators = None