Add CLI flags to disable version and indicator checks

This commit is contained in:
Janik Besendorf
2025-08-05 15:15:53 +02:00
parent ab9abfaded
commit 3b144b263b
12 changed files with 135 additions and 59 deletions

View File

@@ -31,6 +31,8 @@ from mvt.common.help import (
HELP_MSG_HASHES,
HELP_MSG_CHECK_IOCS,
HELP_MSG_STIX2,
HELP_MSG_DISABLE_UPDATE_CHECK,
HELP_MSG_DISABLE_INDICATOR_UPDATE_CHECK,
)
from mvt.common.logo import logo
from mvt.common.updates import IndicatorsUpdates
@@ -57,8 +59,14 @@ CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
# Main
# ==============================================================================
@click.group(invoke_without_command=False)
def cli():
logo()
@click.option("--disable-update-check", is_flag=True, help=HELP_MSG_DISABLE_UPDATE_CHECK)
@click.option("--disable-indicator-update-check", is_flag=True, help=HELP_MSG_DISABLE_INDICATOR_UPDATE_CHECK)
@click.pass_context
def cli(ctx, disable_update_check, disable_indicator_update_check):
ctx.ensure_object(dict)
ctx.obj['disable_version_check'] = disable_update_check
ctx.obj['disable_indicator_check'] = disable_indicator_update_check
logo(disable_version_check=disable_update_check, disable_indicator_check=disable_indicator_update_check)
# ==============================================================================
@@ -166,6 +174,8 @@ def check_adb(
module_name=module,
serial=serial,
module_options=module_options,
disable_version_check=ctx.obj.get('disable_version_check', False),
disable_indicator_check=ctx.obj.get('disable_indicator_check', False),
)
if list_modules:
@@ -212,6 +222,8 @@ def check_bugreport(ctx, iocs, output, list_modules, module, verbose, bugreport_
ioc_files=iocs,
module_name=module,
hashes=True,
disable_version_check=ctx.obj.get('disable_version_check', False),
disable_indicator_check=ctx.obj.get('disable_indicator_check', False),
)
if list_modules:
@@ -274,6 +286,8 @@ def check_backup(
"interactive": not non_interactive,
"backup_password": cli_load_android_backup_password(log, backup_password),
},
disable_version_check=ctx.obj.get('disable_version_check', False),
disable_indicator_check=ctx.obj.get('disable_indicator_check', False),
)
if list_modules:
@@ -338,6 +352,8 @@ def check_androidqf(
"interactive": not non_interactive,
"backup_password": cli_load_android_backup_password(log, backup_password),
},
disable_version_check=ctx.obj.get('disable_version_check', False),
disable_indicator_check=ctx.obj.get('disable_indicator_check', False),
)
if list_modules:
@@ -372,7 +388,13 @@ def check_androidqf(
@click.argument("FOLDER", type=click.Path(exists=True))
@click.pass_context
def check_iocs(ctx, iocs, list_modules, module, folder):
cmd = CmdCheckIOCS(target_path=folder, ioc_files=iocs, module_name=module)
cmd = CmdCheckIOCS(
target_path=folder,
ioc_files=iocs,
module_name=module,
disable_version_check=ctx.obj.get('disable_version_check', False),
disable_indicator_check=ctx.obj.get('disable_indicator_check', False),
)
cmd.modules = BACKUP_MODULES + ADB_MODULES + BUGREPORT_MODULES
if list_modules:

View File

@@ -22,6 +22,8 @@ class CmdAndroidCheckADB(Command):
module_name: Optional[str] = None,
serial: Optional[str] = None,
module_options: Optional[dict] = None,
disable_version_check: bool = False,
disable_indicator_check: bool = False,
) -> None:
super().__init__(
target_path=target_path,
@@ -31,6 +33,8 @@ class CmdAndroidCheckADB(Command):
serial=serial,
module_options=module_options,
log=log,
disable_version_check=disable_version_check,
disable_indicator_check=disable_indicator_check,
)
self.name = "check-adb"

View File

@@ -26,6 +26,8 @@ class CmdAndroidCheckAndroidQF(Command):
serial: Optional[str] = None,
module_options: Optional[dict] = None,
hashes: bool = False,
disable_version_check: bool = False,
disable_indicator_check: bool = False,
) -> None:
super().__init__(
target_path=target_path,
@@ -36,6 +38,8 @@ class CmdAndroidCheckAndroidQF(Command):
module_options=module_options,
hashes=hashes,
log=log,
disable_version_check=disable_version_check,
disable_indicator_check=disable_indicator_check,
)
self.name = "check-androidqf"

View File

@@ -36,6 +36,8 @@ class CmdAndroidCheckBackup(Command):
serial: Optional[str] = None,
module_options: Optional[dict] = None,
hashes: bool = False,
disable_version_check: bool = False,
disable_indicator_check: bool = False,
) -> None:
super().__init__(
target_path=target_path,
@@ -46,6 +48,8 @@ class CmdAndroidCheckBackup(Command):
module_options=module_options,
hashes=hashes,
log=log,
disable_version_check=disable_version_check,
disable_indicator_check=disable_indicator_check,
)
self.name = "check-backup"

View File

@@ -27,6 +27,8 @@ class CmdAndroidCheckBugreport(Command):
serial: Optional[str] = None,
module_options: Optional[dict] = None,
hashes: bool = False,
disable_version_check: bool = False,
disable_indicator_check: bool = False,
) -> None:
super().__init__(
target_path=target_path,
@@ -37,6 +39,8 @@ class CmdAndroidCheckBugreport(Command):
module_options=module_options,
hashes=hashes,
log=log,
disable_version_check=disable_version_check,
disable_indicator_check=disable_indicator_check,
)
self.name = "check-bugreport"

View File

@@ -22,6 +22,8 @@ class CmdCheckIOCS(Command):
module_name: Optional[str] = None,
serial: Optional[str] = None,
module_options: Optional[dict] = None,
disable_version_check: bool = False,
disable_indicator_check: bool = False,
) -> None:
super().__init__(
target_path=target_path,
@@ -31,6 +33,8 @@ class CmdCheckIOCS(Command):
serial=serial,
module_options=module_options,
log=log,
disable_version_check=disable_version_check,
disable_indicator_check=disable_indicator_check,
)
self.name = "check-iocs"

View File

@@ -32,6 +32,8 @@ class Command:
module_options: Optional[dict] = None,
hashes: bool = False,
log: logging.Logger = logging.getLogger(__name__),
disable_version_check: bool = False,
disable_indicator_check: bool = False,
) -> None:
self.name = ""
self.modules = []
@@ -42,6 +44,8 @@ class Command:
self.module_name = module_name
self.serial = serial
self.log = log
self.disable_version_check = disable_version_check
self.disable_indicator_check = disable_indicator_check
# This dictionary can contain options that will be passed down from
# the Command to all modules. This can for example be used to pass

View File

@@ -15,6 +15,8 @@ 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"
HELP_MSG_DISABLE_UPDATE_CHECK = "Disable MVT version update check"
HELP_MSG_DISABLE_INDICATOR_UPDATE_CHECK = "Disable indicators update check"
# IOS Specific
HELP_MSG_DECRYPT_BACKUP = "Decrypt an encrypted iTunes backup"

View File

@@ -12,74 +12,77 @@ from .updates import IndicatorsUpdates, MVTUpdates
from .version import MVT_VERSION
def check_updates() -> None:
def check_updates(disable_version_check: bool = False, disable_indicator_check: bool = False) -> None:
log = logging.getLogger("mvt")
# First we check for MVT version updates.
try:
mvt_updates = MVTUpdates()
latest_version = mvt_updates.check()
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
rich_print(
"\t\t[bold]Note: Could not check for MVT updates.[/bold] "
"You may be working offline. Please update MVT regularly."
)
except Exception as e:
log.error("Error encountered when trying to check latest MVT version: %s", e)
else:
if latest_version:
if not disable_version_check:
try:
mvt_updates = MVTUpdates()
latest_version = mvt_updates.check()
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
rich_print(
f"\t\t[bold]Version {latest_version} is available! "
"Upgrade mvt with `pip3 install -U mvt` or with `pipx upgrade mvt`[/bold]"
"\t\t[bold]Note: Could not check for MVT updates.[/bold] "
"You may be working offline. Please update MVT regularly."
)
except Exception as e:
log.error("Error encountered when trying to check latest MVT version: %s", e)
else:
if latest_version:
rich_print(
f"\t\t[bold]Version {latest_version} is available! "
"Upgrade mvt with `pip3 install -U mvt` or with `pipx upgrade mvt`[/bold]"
)
# Then we check for indicators files updates.
ioc_updates = IndicatorsUpdates()
if not disable_indicator_check:
ioc_updates = IndicatorsUpdates()
# Before proceeding, we check if we have downloaded an indicators index.
# If not, there's no point in proceeding with the updates check.
if ioc_updates.get_latest_update() == 0:
rich_print(
"\t\t[bold]You have not yet downloaded any indicators, check "
"the `download-iocs` command![/bold]"
)
return
# We only perform this check at a fixed frequency, in order to not
# overburden the user with too many lookups if the command is being run
# multiple times.
should_check, hours = ioc_updates.should_check()
if not should_check:
rich_print(
f"\t\tIndicators updates checked recently, next automatic check "
f"in {int(hours)} hours"
)
return
try:
ioc_to_update = ioc_updates.check()
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
rich_print(
"\t\t[bold]Note: Could not check for indicator updates.[/bold] "
"You may be working offline. Please update MVT indicators regularly."
)
except Exception as e:
log.error("Error encountered when trying to check latest MVT indicators: %s", e)
else:
if ioc_to_update:
# Before proceeding, we check if we have downloaded an indicators index.
# If not, there's no point in proceeding with the updates check.
if ioc_updates.get_latest_update() == 0:
rich_print(
"\t\t[bold]There are updates to your indicators files! "
"Run the `download-iocs` command to update![/bold]"
"\t\t[bold]You have not yet downloaded any indicators, check "
"the `download-iocs` command![/bold]"
)
return
# We only perform this check at a fixed frequency, in order to not
# overburden the user with too many lookups if the command is being run
# multiple times.
should_check, hours = ioc_updates.should_check()
if not should_check:
rich_print(
f"\t\tIndicators updates checked recently, next automatic check "
f"in {int(hours)} hours"
)
return
try:
ioc_to_update = ioc_updates.check()
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout):
rich_print(
"\t\t[bold]Note: Could not check for indicator updates.[/bold] "
"You may be working offline. Please update MVT indicators regularly."
)
except Exception as e:
log.error("Error encountered when trying to check latest MVT indicators: %s", e)
else:
rich_print("\t\tYour indicators files seem to be up to date.")
if ioc_to_update:
rich_print(
"\t\t[bold]There are updates to your indicators files! "
"Run the `download-iocs` command to update![/bold]"
)
else:
rich_print("\t\tYour indicators files seem to be up to date.")
def logo() -> None:
def logo(disable_version_check: bool = False, disable_indicator_check: bool = False) -> None:
rich_print("\n")
rich_print("\t[bold]MVT[/bold] - Mobile Verification Toolkit")
rich_print("\t\thttps://mvt.re")
rich_print(f"\t\tVersion: {MVT_VERSION}")
check_updates()
check_updates(disable_version_check, disable_indicator_check)
rich_print("\n")

View File

@@ -37,6 +37,8 @@ from mvt.common.help import (
HELP_MSG_CHECK_IOCS,
HELP_MSG_STIX2,
HELP_MSG_CHECK_IOS_BACKUP,
HELP_MSG_DISABLE_UPDATE_CHECK,
HELP_MSG_DISABLE_INDICATOR_UPDATE_CHECK,
)
from .cmd_check_backup import CmdIOSCheckBackup
from .cmd_check_fs import CmdIOSCheckFS
@@ -57,8 +59,14 @@ CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
# Main
# ==============================================================================
@click.group(invoke_without_command=False)
def cli():
logo()
@click.option("--disable-update-check", is_flag=True, help=HELP_MSG_DISABLE_UPDATE_CHECK)
@click.option("--disable-indicator-update-check", is_flag=True, help=HELP_MSG_DISABLE_INDICATOR_UPDATE_CHECK)
@click.pass_context
def cli(ctx, disable_update_check, disable_indicator_update_check):
ctx.ensure_object(dict)
ctx.obj['disable_version_check'] = disable_update_check
ctx.obj['disable_indicator_check'] = disable_indicator_update_check
logo(disable_version_check=disable_update_check, disable_indicator_check=disable_indicator_update_check)
# ==============================================================================
@@ -219,6 +227,8 @@ def check_backup(
module_name=module,
module_options=module_options,
hashes=hashes,
disable_version_check=ctx.obj.get('disable_version_check', False),
disable_indicator_check=ctx.obj.get('disable_indicator_check', False),
)
if list_modules:
@@ -266,6 +276,8 @@ def check_fs(ctx, iocs, output, fast, list_modules, module, hashes, verbose, dum
module_name=module,
module_options=module_options,
hashes=hashes,
disable_version_check=ctx.obj.get('disable_version_check', False),
disable_indicator_check=ctx.obj.get('disable_indicator_check', False),
)
if list_modules:
@@ -300,7 +312,13 @@ def check_fs(ctx, iocs, output, fast, list_modules, module, hashes, verbose, dum
@click.argument("FOLDER", type=click.Path(exists=True))
@click.pass_context
def check_iocs(ctx, iocs, list_modules, module, folder):
cmd = CmdCheckIOCS(target_path=folder, ioc_files=iocs, module_name=module)
cmd = CmdCheckIOCS(
target_path=folder,
ioc_files=iocs,
module_name=module,
disable_version_check=ctx.obj.get('disable_version_check', False),
disable_indicator_check=ctx.obj.get('disable_indicator_check', False),
)
cmd.modules = BACKUP_MODULES + FS_MODULES + MIXED_MODULES
if list_modules:

View File

@@ -24,6 +24,8 @@ class CmdIOSCheckBackup(Command):
serial: Optional[str] = None,
module_options: Optional[dict] = None,
hashes: bool = False,
disable_version_check: bool = False,
disable_indicator_check: bool = False,
) -> None:
super().__init__(
target_path=target_path,
@@ -34,6 +36,8 @@ class CmdIOSCheckBackup(Command):
module_options=module_options,
hashes=hashes,
log=log,
disable_version_check=disable_version_check,
disable_indicator_check=disable_indicator_check,
)
self.name = "check-backup"

View File

@@ -24,16 +24,19 @@ class CmdIOSCheckFS(Command):
serial: Optional[str] = None,
module_options: Optional[dict] = None,
hashes: bool = False,
disable_version_check: bool = False,
disable_indicator_check: bool = False,
) -> None:
super().__init__(
target_path=target_path,
results_path=results_path,
ioc_files=ioc_files,
module_name=module_name,
serial=serial,
module_options=module_options,
hashes=hashes,
log=log,
disable_version_check=disable_version_check,
disable_indicator_check=disable_indicator_check,
)
self.name = "check-fs"