Merge branch 'main' into fix/alert-timestamps

This commit is contained in:
Donncha Ó Cearbhaill
2026-08-30 14:10:32 +02:00
committed by GitHub
76 changed files with 7658 additions and 648 deletions
@@ -0,0 +1,54 @@
# 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/
"""A `Caused by:` line must not discard the whole text tombstone.
Keys are matched as bare prefixes, so `Caused by: …` — an ordinary line inside
an abort message — reached the `Cause` key, failed the key comparison and
raised, which `Tombstones.run()` logged while dropping the entire crash record.
Seen on a 1.6 MB tombstone whose protobuf twin was zero bytes: the crash then
had no representation at all.
"""
import datetime
from mvt.android.artifacts.tombstone_crashes import TombstoneCrashArtifact
TOMBSTONE = b"""\
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Xiaomi/vili_eea/vili:13/TKQ1.220829.002/V14.0.10.0:user/release-keys'
Revision: '0'
ABI: 'arm64'
Timestamp: 2023-08-24 14:54:47.999124034+0300
Process uptime: 12199s
Cmdline: com.example.game
pid: 8044, tid: 26222, name: UnityMain >>> com.example.game <<<
uid: 10235
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: 'No pending exception expected: java.lang.SecurityException: listen
at void android.os.Parcel.readException() (Parcel.java:2920)
Caused by: android.os.RemoteException: Remote stack trace:
\tat com.android.server.TelephonyRegistry.listen(TelephonyRegistry.java:1096)
"""
WITH_CAUSE = TOMBSTONE + b"Cause: null pointer dereference\n"
class TestTombstoneCausedBy:
def _parse(self, content):
artifact = TombstoneCrashArtifact()
artifact.results = []
artifact.parse("tombstone_23", datetime.datetime(2023, 8, 24), content)
return artifact.results
def test_caused_by_line_does_not_discard_the_tombstone(self):
results = self._parse(TOMBSTONE)
assert len(results) == 1
assert results[0]["pid"] == 8044
assert results[0]["process_name"] == "UnityMain"
assert results[0]["uid"] == 10235
def test_the_real_cause_key_is_still_parsed(self):
results = self._parse(WITH_CAUSE)
assert results[0]["cause"] == "null pointer dereference"
@@ -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)