mirror of
https://github.com/mvt-project/mvt.git
synced 2026-09-03 00:21:07 +02:00
Do not end the whole androidqf run on an encrypted backup.ab (#891)
from_ab() raises InvalidAndroidBackup instead of exiting when it runs as a sub-command, which check-androidqf catches to skip the backup modules. The two password branches still called sys.exit(1) unconditionally, and since run_backup_cmd() runs inside finish(), that ended the parent run before the intrusion-logs command and before the timeline, alerts, urls, info and run manifest were stored — leaving an output directory that looks complete but has no alerts.json. Also drop "as backup.ab is malformed" from the skip warning: it covers a missing or wrong password too.
This commit is contained in:
@@ -292,9 +292,7 @@ class CmdAndroidCheckAndroidQF(Command):
|
||||
try:
|
||||
cmd.from_ab(backup)
|
||||
except InvalidAndroidBackup as exc:
|
||||
self.log.warning(
|
||||
"Skipping backup modules as backup.ab is malformed: %s", exc
|
||||
)
|
||||
self.log.warning("Skipping backup modules: %s", exc)
|
||||
return False
|
||||
|
||||
cmd.run()
|
||||
|
||||
@@ -87,11 +87,15 @@ class CmdAndroidCheckBackup(Command):
|
||||
if header["encryption"] != "none":
|
||||
password = prompt_or_load_android_backup_password(log, self.module_options)
|
||||
if not password:
|
||||
if self.sub_command:
|
||||
raise InvalidAndroidBackup("No backup password provided")
|
||||
log.critical("No backup password provided.")
|
||||
sys.exit(1)
|
||||
try:
|
||||
tardata = parse_backup_file(ab_file_bytes, password=password)
|
||||
except InvalidBackupPassword:
|
||||
if self.sub_command:
|
||||
raise InvalidAndroidBackup("Invalid backup password")
|
||||
log.critical("Invalid backup password")
|
||||
sys.exit(1)
|
||||
except AndroidBackupParsingError as exc:
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 The MVT Authors.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
"""An encrypted backup.ab must not take the whole check-androidqf run with it.
|
||||
|
||||
`CmdAndroidCheckBackup.from_ab()` already raises `InvalidAndroidBackup` instead
|
||||
of exiting when it runs as a sub-command (`check-androidqf` catches that and
|
||||
skips the backup modules), for a wrong file format and for a parse error. The
|
||||
password branches used to call `sys.exit(1)` unconditionally, which ends the
|
||||
parent run inside `finish()` — before the intrusion-logs command and before the
|
||||
timeline, alerts, urls, info and run-manifest are written.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from mvt.android.cmd_check_backup import CmdAndroidCheckBackup, InvalidAndroidBackup
|
||||
|
||||
ENCRYPTED_AB_HEADER = b"ANDROID BACKUP\n5\n0\nAES-256\n" + b"\x00" * 64
|
||||
|
||||
|
||||
class TestCheckBackupOptionalFailure:
|
||||
def _cmd(self, tmp_path, sub_command):
|
||||
return CmdAndroidCheckBackup(
|
||||
target_path=None,
|
||||
results_path=str(tmp_path),
|
||||
module_options={"interactive": False},
|
||||
sub_command=sub_command,
|
||||
)
|
||||
|
||||
def test_missing_password_raises_when_nested(self, tmp_path):
|
||||
cmd = self._cmd(tmp_path, sub_command=True)
|
||||
with pytest.raises(InvalidAndroidBackup):
|
||||
cmd.from_ab(ENCRYPTED_AB_HEADER)
|
||||
|
||||
def test_missing_password_still_exits_on_its_own_command(self, tmp_path):
|
||||
cmd = self._cmd(tmp_path, sub_command=False)
|
||||
with pytest.raises(SystemExit):
|
||||
cmd.from_ab(ENCRYPTED_AB_HEADER)
|
||||
@@ -155,7 +155,7 @@ class TestCheckAndroidqfCommand:
|
||||
result = runner.invoke(check_androidqf, [str(path)])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Skipping backup modules as backup.ab is malformed" in caplog.text
|
||||
assert "Skipping backup modules: Invalid backup format" in caplog.text
|
||||
assert not any(
|
||||
record.levelname in {"CRITICAL", "FATAL"} for record in caplog.records
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user