mirror of
https://github.com/mvt-project/mvt.git
synced 2026-08-17 16:37:23 +02:00
235 lines
7.9 KiB
Python
235 lines
7.9 KiB
Python
# 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/
|
|
|
|
from mvt.android.artifacts.dumpsys_adb import DumpsysADBArtifact
|
|
from mvt.android.modules.bugreport.dumpsys_adb_state import DumpsysADBState
|
|
from mvt.common.alerts import AlertLevel
|
|
|
|
from ..utils import get_artifact
|
|
|
|
|
|
class TestDumpsysADBArtifact:
|
|
def test_parsing(self):
|
|
da_adb = DumpsysADBArtifact()
|
|
file = get_artifact("android_data/dumpsys_adb.txt")
|
|
with open(file, "rb") as f:
|
|
data = f.read()
|
|
|
|
assert len(da_adb.results) == 0
|
|
da_adb.parse(data)
|
|
|
|
assert len(da_adb.results) == 1
|
|
adb_data = da_adb.results[0]
|
|
assert "user_keys" in adb_data
|
|
assert len(adb_data["user_keys"]) == 1
|
|
|
|
# Check key and fingerprint parsed successfully.
|
|
user_key = adb_data["user_keys"][0]
|
|
assert (
|
|
user_key["fingerprint"] == "F0:A1:3D:8C:B3:F4:7B:09:9F:EE:8B:D8:38:2E:BD:C6"
|
|
)
|
|
assert user_key["user"] == "user@linux"
|
|
|
|
def test_parsing_adb_wifi(self):
|
|
da_adb = DumpsysADBArtifact()
|
|
file = get_artifact("android_data/dumpsys_adb_wifi.txt")
|
|
with open(file, "rb") as f:
|
|
data = f.read()
|
|
|
|
da_adb.parse(data)
|
|
|
|
assert len(da_adb.results) == 1
|
|
adb_data = da_adb.results[0]
|
|
assert "user_keys" in adb_data
|
|
assert len(adb_data["user_keys"]) == 1
|
|
|
|
user_key = adb_data["user_keys"][0]
|
|
assert (
|
|
user_key["fingerprint"] == "F0:A1:3D:8C:B3:F4:7B:09:9F:EE:8B:D8:38:2E:BD:C6"
|
|
)
|
|
assert user_key["user"] == "user@linux"
|
|
|
|
# The adb_wifi block following the keystore is not part of the keystore.
|
|
assert b"adb_wifi" not in adb_data["keystore"]
|
|
|
|
def test_parsing_multiline_terminated_by_structural_line(self):
|
|
dump_data = (
|
|
b"debugging_manager={\n"
|
|
b" keystore=ABX\x00\x0bkeyStore\x00\x02\x11\n"
|
|
b" connected_to_adb=true\n"
|
|
b" adb_wifi={\n"
|
|
b" enabled=false\n"
|
|
b" tls_port=0\n"
|
|
b" }\n"
|
|
)
|
|
|
|
parsed = DumpsysADBArtifact().indented_dump_parser(dump_data)
|
|
|
|
debugging_manager = parsed["debugging_manager"]
|
|
assert debugging_manager["keystore"] == [b"ABX\x00\x0bkeyStore\x00\x02\x11"]
|
|
assert debugging_manager["connected_to_adb"] == b"true"
|
|
assert debugging_manager["adb_wifi"] == {
|
|
"enabled": b"false",
|
|
"tls_port": b"0",
|
|
}
|
|
|
|
def test_parsing_multiline_terminated_by_closing_brace(self):
|
|
dump_data = (
|
|
b"debugging_manager={\n"
|
|
b" keystore=ABX\x00\x0bkeyStore\x00\x02\x11\n"
|
|
b"}\n"
|
|
b"other={\n"
|
|
b" value=true\n"
|
|
b"}\n"
|
|
)
|
|
|
|
parsed = DumpsysADBArtifact().indented_dump_parser(dump_data)
|
|
|
|
assert parsed["debugging_manager"]["keystore"] == [
|
|
b"ABX\x00\x0bkeyStore\x00\x02\x11"
|
|
]
|
|
assert parsed["other"] == {"value": b"true"}
|
|
|
|
def test_parsing_adb_xml(self):
|
|
da_adb = DumpsysADBArtifact()
|
|
file = get_artifact("android_data/dumpsys_adb_xml.txt")
|
|
with open(file, "rb") as f:
|
|
data = f.read()
|
|
|
|
da_adb.parse(data)
|
|
|
|
assert len(da_adb.results) == 1
|
|
|
|
adb_data = da_adb.results[0]
|
|
assert "user_keys" in adb_data
|
|
assert len(adb_data["user_keys"]) == 1
|
|
|
|
# Check key and fingerprint parsed successfully.
|
|
expected_fingerprint = "F0:0B:27:08:E3:68:7B:FA:4C:79:A2:B4:BF:0E:CF:70"
|
|
user_key = adb_data["user_keys"][0]
|
|
user_key["fingerprint"] == expected_fingerprint
|
|
assert user_key["user"] == "user@laptop"
|
|
|
|
key_store_entry = adb_data["keystore"][0]
|
|
assert key_store_entry["user"] == "user@laptop"
|
|
assert key_store_entry["fingerprint"] == expected_fingerprint
|
|
assert key_store_entry["last_connected"] == "1628501829898"
|
|
|
|
|
|
class TestDumpsysADBStateAlerts:
|
|
def test_no_androidqf_context_preserves_existing_behavior(self):
|
|
module = DumpsysADBState(
|
|
results=[
|
|
{
|
|
"user_keys": [
|
|
{
|
|
"key": b"QUJDRA==",
|
|
"user": "host@example",
|
|
"fingerprint": "fingerprint",
|
|
}
|
|
]
|
|
}
|
|
]
|
|
)
|
|
|
|
module.check_indicators()
|
|
|
|
assert module.alertstore.alerts == []
|
|
|
|
def test_androidqf_trusted_keys_create_expected_alerts(self):
|
|
module = DumpsysADBState(
|
|
module_options={
|
|
"androidqf_acquisition": {
|
|
"started": "2025-06-20T18:00:00Z",
|
|
"adb_host_public_key": "QUJDRA== acquisition@host",
|
|
}
|
|
},
|
|
results=[
|
|
{
|
|
"user_keys": [
|
|
{
|
|
"key": b"QUJDRA==",
|
|
"user": "acquisition@host",
|
|
"fingerprint": "acquisition-fingerprint",
|
|
},
|
|
{
|
|
"key": b"RUZHSA==",
|
|
"user": "other@host",
|
|
"fingerprint": "other-fingerprint",
|
|
},
|
|
{
|
|
"key": b"not-base64",
|
|
"user": "invalid@host",
|
|
"fingerprint": "",
|
|
},
|
|
],
|
|
"keystore": [
|
|
{
|
|
"key": b"QUJDRA==",
|
|
"user": "acquisition@host",
|
|
"fingerprint": "acquisition-fingerprint",
|
|
"last_connected": "1750266000000",
|
|
}
|
|
],
|
|
}
|
|
],
|
|
)
|
|
|
|
module.check_indicators()
|
|
|
|
assert [alert.level for alert in module.alertstore.alerts] == [
|
|
AlertLevel.INFORMATIONAL,
|
|
AlertLevel.LOW,
|
|
AlertLevel.LOW,
|
|
]
|
|
informational, different, invalid = module.alertstore.alerts
|
|
assert "at least one day before" in informational.message
|
|
assert informational.event_time == "2025-06-18 17:00:00.000000"
|
|
assert "different from the AndroidQF acquisition host" in different.message
|
|
assert "invalid trusted ADB host key" in invalid.message
|
|
|
|
def test_missing_androidqf_host_key_creates_low_alert(self):
|
|
trusted_key = {
|
|
"key": b"QUJDRA==",
|
|
"user": "host@example",
|
|
"fingerprint": "fingerprint",
|
|
}
|
|
module = DumpsysADBState(
|
|
module_options={"androidqf_acquisition": {}},
|
|
results=[{"user_keys": [trusted_key]}],
|
|
)
|
|
|
|
module.check_indicators()
|
|
|
|
assert len(module.alertstore.alerts) == 1
|
|
assert module.alertstore.alerts[0].level == AlertLevel.LOW
|
|
assert "does not include its host key" in module.alertstore.alerts[0].message
|
|
|
|
def test_recent_acquisition_host_key_does_not_create_alert(self):
|
|
module = DumpsysADBState(
|
|
module_options={
|
|
"androidqf_acquisition": {
|
|
"started": "2025-06-20T18:00:00Z",
|
|
"adb_host_public_key": "QUJDRA== acquisition@host",
|
|
}
|
|
},
|
|
results=[
|
|
{
|
|
"keystore": [
|
|
{
|
|
"key": b"QUJDRA==",
|
|
"user": "acquisition@host",
|
|
"fingerprint": "fingerprint",
|
|
"last_connected": "1750438800000",
|
|
}
|
|
]
|
|
}
|
|
],
|
|
)
|
|
|
|
module.check_indicators()
|
|
|
|
assert module.alertstore.alerts == []
|