Refactor CLI help messages to make the CLI code more readable and maintainable. (#554)

* - modified help message string storage and referencing for consistency
- grammar correction to docs/android/download_apks.md
- changed ios backup help message from a format string that would reference
  and explicitly print the environment variable, to printing the name of the
  environment variable itself

* Fix formatting for help message refactor

---------

Co-authored-by: jazzy0verflow <hi@ra0x1duk3.mozmail.com>
Co-authored-by: kh0rvus <50286871+kh0rvus@users.noreply.github.com>
This commit is contained in:
Donncha Ó Cearbhaill
2024-10-17 12:28:42 +02:00
committed by GitHub
parent 7575315966
commit f4bf3f362b
4 changed files with 100 additions and 105 deletions

View File

@@ -1,6 +1,6 @@
# Downloading APKs from an Android phone
MVT allows to attempt to download all available installed packages (APKs) in order to further inspect them and potentially identify any which might be malicious in nature.
MVT allows you to attempt to download all available installed packages (APKs) from a device in order to further inspect them and potentially identify any which might be malicious in nature.
You can do so by launching the following command:

View File

@@ -9,16 +9,28 @@ import click
from mvt.common.cmd_check_iocs import CmdCheckIOCS
from mvt.common.help import (
HELP_MSG_ANDROID_BACKUP_PASSWORD,
HELP_MSG_FAST,
HELP_MSG_HASHES,
HELP_MSG_VERSION,
HELP_MSG_OUTPUT,
HELP_MSG_SERIAL,
HELP_MSG_DOWNLOAD_APKS,
HELP_MSG_DOWNLOAD_ALL_APKS,
HELP_MSG_VIRUS_TOTAL,
HELP_MSG_APK_OUTPUT,
HELP_MSG_APKS_FROM_FILE,
HELP_MSG_VERBOSE,
HELP_MSG_CHECK_ADB,
HELP_MSG_IOC,
HELP_MSG_FAST,
HELP_MSG_LIST_MODULES,
HELP_MSG_MODULE,
HELP_MSG_NONINTERACTIVE,
HELP_MSG_OUTPUT,
HELP_MSG_SERIAL,
HELP_MSG_VERBOSE,
HELP_MSG_ANDROID_BACKUP_PASSWORD,
HELP_MSG_CHECK_BUGREPORT,
HELP_MSG_CHECK_ANDROID_BACKUP,
HELP_MSG_CHECK_ANDROIDQF,
HELP_MSG_HASHES,
HELP_MSG_CHECK_IOCS,
HELP_MSG_STIX2,
)
from mvt.common.logo import logo
from mvt.common.updates import IndicatorsUpdates
@@ -52,7 +64,7 @@ def cli():
# ==============================================================================
# Command: version
# ==============================================================================
@cli.command("version", help="Show the currently installed version of MVT")
@cli.command("version", help=HELP_MSG_VERSION)
def version():
return
@@ -61,30 +73,14 @@ def version():
# Command: download-apks
# ==============================================================================
@cli.command(
"download-apks",
help="Download all or only non-system installed APKs",
context_settings=CONTEXT_SETTINGS,
"download-apks", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_DOWNLOAD_APKS
)
@click.option("--serial", "-s", type=str, help=HELP_MSG_SERIAL)
@click.option("--all-apks", "-a", is_flag=True, help=HELP_MSG_DOWNLOAD_ALL_APKS)
@click.option("--virustotal", "-V", is_flag=True, help=HELP_MSG_VIRUS_TOTAL)
@click.option("--output", "-o", type=click.Path(exists=False), help=HELP_MSG_APK_OUTPUT)
@click.option(
"--all-apks",
"-a",
is_flag=True,
help="Extract all packages installed on the phone, including system packages",
)
@click.option("--virustotal", "-V", is_flag=True, help="Check packages on VirusTotal")
@click.option(
"--output",
"-o",
type=click.Path(exists=False),
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)",
"--from-file", "-f", type=click.Path(exists=True), help=HELP_MSG_APKS_FROM_FILE
)
@click.option("--verbose", "-v", is_flag=True, help=HELP_MSG_VERBOSE)
@click.pass_context
@@ -127,11 +123,7 @@ def download_apks(ctx, all_apks, virustotal, output, from_file, serial, verbose)
# ==============================================================================
# Command: check-adb
# ==============================================================================
@cli.command(
"check-adb",
help="Check an Android device over ADB",
context_settings=CONTEXT_SETTINGS,
)
@cli.command("check-adb", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_CHECK_ADB)
@click.option("--serial", "-s", type=str, help=HELP_MSG_SERIAL)
@click.option(
"--iocs",
@@ -195,9 +187,7 @@ def check_adb(
# Command: check-bugreport
# ==============================================================================
@cli.command(
"check-bugreport",
help="Check an Android Bug Report",
context_settings=CONTEXT_SETTINGS,
"check-bugreport", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_CHECK_BUGREPORT
)
@click.option(
"--iocs",
@@ -243,7 +233,9 @@ def check_bugreport(ctx, iocs, output, list_modules, module, verbose, bugreport_
# Command: check-backup
# ==============================================================================
@cli.command(
"check-backup", help="Check an Android Backup", context_settings=CONTEXT_SETTINGS
"check-backup",
context_settings=CONTEXT_SETTINGS,
help=HELP_MSG_CHECK_ANDROID_BACKUP,
)
@click.option(
"--iocs",
@@ -303,9 +295,7 @@ def check_backup(
# Command: check-androidqf
# ==============================================================================
@cli.command(
"check-androidqf",
help="Check data collected with AndroidQF",
context_settings=CONTEXT_SETTINGS,
"check-androidqf", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_CHECK_ANDROIDQF
)
@click.option(
"--iocs",
@@ -368,11 +358,7 @@ def check_androidqf(
# ==============================================================================
# Command: check-iocs
# ==============================================================================
@cli.command(
"check-iocs",
help="Compare stored JSON results to provided indicators",
context_settings=CONTEXT_SETTINGS,
)
@cli.command("check-iocs", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_CHECK_IOCS)
@click.option(
"--iocs",
"-i",
@@ -399,11 +385,7 @@ def check_iocs(ctx, iocs, list_modules, module, folder):
# ==============================================================================
# Command: download-iocs
# ==============================================================================
@cli.command(
"download-iocs",
help="Download public STIX2 indicators",
context_settings=CONTEXT_SETTINGS,
)
@cli.command("download-iocs", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_STIX2)
def download_indicators():
ioc_updates = IndicatorsUpdates()
ioc_updates.update()

View File

@@ -3,16 +3,49 @@
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
# Help messages of repeating options.
# Help messages of generic options.
HELP_MSG_VERSION = "Show the currently installed version of MVT"
HELP_MSG_OUTPUT = "Specify a path to a folder where you want to store JSON results"
HELP_MSG_IOC = "Path to indicators file (can be invoked multiple time)"
HELP_MSG_FAST = "Avoid running time/resource consuming features"
HELP_MSG_LIST_MODULES = "Print list of available modules and exit"
HELP_MSG_MODULE = "Name of a single module you would like to run instead of all"
HELP_MSG_NONINTERACTIVE = "Don't ask interactive questions during processing"
HELP_MSG_ANDROID_BACKUP_PASSWORD = "The backup password to use for an Android backup"
HELP_MSG_HASHES = "Generate hashes of all the files analyzed"
HELP_MSG_VERBOSE = "Verbose mode"
HELP_MSG_CHECK_IOCS = "Compare stored JSON results to provided indicators"
HELP_MSG_STIX2 = "Download public STIX2 indicators"
# Android-specific.
# IOS Specific
HELP_MSG_DECRYPT_BACKUP = "Decrypt an encrypted iTunes backup"
HELP_MSG_BACKUP_DESTINATION = (
"Path to the folder where the decrypted backup should be stored"
)
HELP_MSG_IOS_BACKUP_PASSWORD = (
"Password to use to decrypt the backup (or, set the {MVT_IOS_BACKUP_PASSWORD} "
"environment variable)"
)
HELP_MSG_BACKUP_KEYFILE = (
"File containing raw encryption key to use to decrypt the backup"
)
HELP_MSG_EXTRACT_KEY = "Extract decryption key from an iTunes backup"
HELP_MSG_CHECK_IOS_BACKUP = "Extract artifacts from an iTunes backup"
HELP_MSG_CHECK_FS = "Extract artifacts from a full filesystem dump"
# Android Specific
HELP_MSG_SERIAL = "Specify a device serial number or HOST:PORT connection string"
HELP_MSG_DOWNLOAD_APKS = "Download all or only non-system installed APKs"
HELP_MSG_ANDROID_BACKUP_PASSWORD = "The backup password to use for an Android backup"
HELP_MSG_DOWNLOAD_ALL_APKS = (
"Extract all packages installed on the phone, including system packages"
)
HELP_MSG_VIRUS_TOTAL = "Check packages on VirusTotal"
HELP_MSG_APK_OUTPUT = "Specify a path to a folder where you want to store the APKs"
HELP_MSG_APKS_FROM_FILE = (
"Instead of acquiring APKs from a phone, load an existing packages.json file for "
"lookups (mainly for debug purposes)"
)
HELP_MSG_CHECK_ADB = "Check an Android device over ADB"
HELP_MSG_CHECK_BUGREPORT = "Check an Android Bug Report"
HELP_MSG_CHECK_ANDROID_BACKUP = "Check an Android Backup"
HELP_MSG_CHECK_ANDROIDQF = "Check data collected with AndroidQF"

View File

@@ -11,15 +11,6 @@ import click
from rich.prompt import Prompt
from mvt.common.cmd_check_iocs import CmdCheckIOCS
from mvt.common.help import (
HELP_MSG_FAST,
HELP_MSG_HASHES,
HELP_MSG_IOC,
HELP_MSG_LIST_MODULES,
HELP_MSG_MODULE,
HELP_MSG_OUTPUT,
HELP_MSG_VERBOSE,
)
from mvt.common.logo import logo
from mvt.common.options import MutuallyExclusiveOption
from mvt.common.updates import IndicatorsUpdates
@@ -28,7 +19,25 @@ from mvt.common.utils import (
init_logging,
set_verbose_logging,
)
from mvt.common.help import (
HELP_MSG_VERSION,
HELP_MSG_DECRYPT_BACKUP,
HELP_MSG_BACKUP_DESTINATION,
HELP_MSG_IOS_BACKUP_PASSWORD,
HELP_MSG_BACKUP_KEYFILE,
HELP_MSG_HASHES,
HELP_MSG_EXTRACT_KEY,
HELP_MSG_IOC,
HELP_MSG_OUTPUT,
HELP_MSG_FAST,
HELP_MSG_LIST_MODULES,
HELP_MSG_MODULE,
HELP_MSG_VERBOSE,
HELP_MSG_CHECK_FS,
HELP_MSG_CHECK_IOCS,
HELP_MSG_STIX2,
HELP_MSG_CHECK_IOS_BACKUP,
)
from .cmd_check_backup import CmdIOSCheckBackup
from .cmd_check_fs import CmdIOSCheckFS
from .decrypt import DecryptBackup
@@ -55,7 +64,7 @@ def cli():
# ==============================================================================
# Command: version
# ==============================================================================
@cli.command("version", help="Show the currently installed version of MVT")
@cli.command("version", help=HELP_MSG_VERSION)
def version():
return
@@ -64,31 +73,23 @@ def version():
# Command: decrypt-backup
# ==============================================================================
@cli.command(
"decrypt-backup",
help="Decrypt an encrypted iTunes backup",
context_settings=CONTEXT_SETTINGS,
)
@click.option(
"--destination",
"-d",
required=True,
help="Path to the folder where to store the decrypted backup",
"decrypt-backup", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_DECRYPT_BACKUP
)
@click.option("--destination", "-d", required=True, help=HELP_MSG_BACKUP_DESTINATION)
@click.option(
"--password",
"-p",
cls=MutuallyExclusiveOption,
help="Password to use to decrypt the backup (or, set "
f"{MVT_IOS_BACKUP_PASSWORD} environment variable)",
mutually_exclusive=["key_file"],
help=HELP_MSG_IOS_BACKUP_PASSWORD,
)
@click.option(
"--key-file",
"-k",
cls=MutuallyExclusiveOption,
type=click.Path(exists=True),
help="File containing raw encryption key to use to decrypt " "the backup",
mutually_exclusive=["password"],
help=HELP_MSG_BACKUP_KEYFILE,
)
@click.option("--hashes", "-H", is_flag=True, help=HELP_MSG_HASHES)
@click.argument("BACKUP_PATH", type=click.Path(exists=True))
@@ -145,22 +146,15 @@ def decrypt_backup(ctx, destination, password, key_file, hashes, backup_path):
# Command: extract-key
# ==============================================================================
@cli.command(
"extract-key",
help="Extract decryption key from an iTunes backup",
context_settings=CONTEXT_SETTINGS,
)
@click.option(
"--password",
"-p",
help="Password to use to decrypt the backup (or, set "
f"{MVT_IOS_BACKUP_PASSWORD} environment variable)",
"extract-key", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_EXTRACT_KEY
)
@click.option("--password", "-p", help=HELP_MSG_IOS_BACKUP_PASSWORD)
@click.option(
"--key-file",
"-k",
help="Key file to be written (if unset, will print to STDOUT)",
required=False,
type=click.Path(exists=False, file_okay=True, dir_okay=False, writable=True),
help=HELP_MSG_BACKUP_KEYFILE,
)
@click.argument("BACKUP_PATH", type=click.Path(exists=True))
def extract_key(password, key_file, backup_path):
@@ -195,9 +189,7 @@ def extract_key(password, key_file, backup_path):
# Command: check-backup
# ==============================================================================
@cli.command(
"check-backup",
help="Extract artifacts from an iTunes backup",
context_settings=CONTEXT_SETTINGS,
"check-backup", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_CHECK_IOS_BACKUP
)
@click.option(
"--iocs",
@@ -247,11 +239,7 @@ def check_backup(
# ==============================================================================
# Command: check-fs
# ==============================================================================
@cli.command(
"check-fs",
help="Extract artifacts from a full filesystem dump",
context_settings=CONTEXT_SETTINGS,
)
@cli.command("check-fs", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_CHECK_FS)
@click.option(
"--iocs",
"-i",
@@ -299,11 +287,7 @@ def check_fs(ctx, iocs, output, fast, list_modules, module, hashes, verbose, dum
# ==============================================================================
# Command: check-iocs
# ==============================================================================
@cli.command(
"check-iocs",
help="Compare stored JSON results to provided indicators",
context_settings=CONTEXT_SETTINGS,
)
@cli.command("check-iocs", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_CHECK_IOCS)
@click.option(
"--iocs",
"-i",
@@ -330,11 +314,7 @@ def check_iocs(ctx, iocs, list_modules, module, folder):
# ==============================================================================
# Command: download-iocs
# ==============================================================================
@cli.command(
"download-iocs",
help="Download public STIX2 indicators",
context_settings=CONTEXT_SETTINGS,
)
@cli.command("download-iocs", context_settings=CONTEXT_SETTINGS, help=HELP_MSG_STIX2)
def download_iocs():
ioc_updates = IndicatorsUpdates()
ioc_updates.update()