Adds SMS androidqf module and improves tests

This commit is contained in:
tek 2022-10-11 12:41:42 +02:00
parent 41826d7951
commit ba0106c476
12 changed files with 211 additions and 1 deletions

View File

@ -71,6 +71,16 @@ SECURITY_PACKAGES = [
"com.samsung.android.app.omcagent", "com.samsung.android.app.omcagent",
"com.samsung.android.securitylogagent", "com.samsung.android.securitylogagent",
"com.sec.android.soagent", "com.sec.android.soagent",
]
SYSTEM_UPDATE_PACKAGES = [
"com.android.updater",
"com.google.android.gms",
"com.huawei.android.hwouc",
"com.lge.lgdmsclient",
"com.motorola.ccc.ota",
"com.oneplus.opbackup",
"com.oppo.ota",
"com.transsion.systemupdate",
"com.wssyncmldm", "com.wssyncmldm",
] ]
@ -133,6 +143,10 @@ class Packages(AndroidExtraction):
self.log.warning("Found a security package disabled: \"%s\"", self.log.warning("Found a security package disabled: \"%s\"",
result["package_name"]) result["package_name"])
if result["package_name"] in SYSTEM_UPDATE_PACKAGES and result["disabled"]:
self.log.warning("System OTA update package \"%s\" disabled on the phone",
result["package_name"])
if not self.indicators: if not self.indicators:
continue continue

View File

@ -10,6 +10,7 @@ from .dumpsys_receivers import DumpsysReceivers
from .getprop import Getprop from .getprop import Getprop
from .processes import Processes from .processes import Processes
from .settings import Settings from .settings import Settings
from .sms import SMS
ANDROIDQF_MODULES = [DumpsysActivities, DumpsysReceivers, DumpsysAccessibility, ANDROIDQF_MODULES = [DumpsysActivities, DumpsysReceivers, DumpsysAccessibility,
DumpsysAppops, Processes, Getprop, Settings] DumpsysAppops, Processes, Getprop, Settings, SMS]

View File

@ -0,0 +1,85 @@
# Mobile Verification Toolkit (MVT) - Private
# Copyright (c) 2021-2022 Claudio Guarnieri.
# This file is part of MVT Private and its content is confidential.
# Please refer to the project maintainers before sharing with others.
import getpass
import logging
from typing import Optional
from mvt.android.parsers.backup import (AndroidBackupParsingError,
InvalidBackupPassword, parse_ab_header,
parse_backup_file, parse_tar_for_sms)
from .base import AndroidQFModule
class SMS(AndroidQFModule):
"""This module analyse SMS file in backup"""
def __init__(
self,
file_path: Optional[str] = None,
target_path: Optional[str] = None,
results_path: Optional[str] = None,
fast_mode: Optional[bool] = False,
log: logging.Logger = logging.getLogger(__name__),
results: Optional[list] = None
) -> None:
super().__init__(file_path=file_path, target_path=target_path,
results_path=results_path, fast_mode=fast_mode,
log=log, results=results)
def check_indicators(self) -> None:
if not self.indicators:
return
for message in self.results:
if "body" not in message:
continue
if self.indicators.check_domains(message["links"]):
self.detected.append(message)
def parse_backup(self, data):
header = parse_ab_header(data)
if not header["backup"]:
self.log.critical("Invalid backup format, backup.ab was not analysed")
return
password = None
if header["encryption"] != "none":
password = getpass.getpass(prompt="Backup Password: ", stream=None)
try:
tardata = parse_backup_file(data, password=password)
except InvalidBackupPassword:
self.log.critical("Invalid backup password")
return
except AndroidBackupParsingError:
self.log.critical("Impossible to parse this backup file, please use"
" Android Backup Extractor instead")
return
if not tardata:
return
try:
self.results = parse_tar_for_sms(tardata)
except AndroidBackupParsingError:
self.log.info("Impossible to read SMS from the Android Backup, "
"please extract the SMS and try extracting it with "
"Android Backup Extractor")
return
def run(self) -> None:
files = self._get_files_by_pattern("*/backup.ab")
if not files:
self.log.info("No backup data found")
return
with open(files[0], "rb") as handle:
data = handle.read()
self.parse_backup(data)
self.log.info("Identified %d SMS in backup data",
len(self.results))

View File

@ -0,0 +1,22 @@
# Mobile Verification Toolkit (MVT)
# Copyright (c) 2021-2022 Claudio Guarnieri.
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
import os
import logging
from mvt.android.modules.androidqf.getprop import Getprop
from mvt.common.module import run_module
from ..utils import get_artifact_folder
class TestAndroidqfGetpropAnalysis:
def test_androidqf_getprop(self):
m = Getprop(target_path=os.path.join(get_artifact_folder(), "androidqf"), log=logging)
run_module(m)
assert len(m.results) == 10
assert len(m.timeline) == 0
assert len(m.detected) == 0

View File

@ -0,0 +1,21 @@
# Mobile Verification Toolkit (MVT)
# Copyright (c) 2021-2022 Claudio Guarnieri.
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
import os
import logging
from mvt.android.modules.androidqf.processes import Processes
from mvt.common.module import run_module
from ..utils import get_artifact_folder
class TestAndroidqfProcessesAnalysis:
def test_androidqf_processes(self):
m = Processes(target_path=os.path.join(get_artifact_folder(), "androidqf"), log=logging)
run_module(m)
assert len(m.results) == 15
assert len(m.timeline) == 0
assert len(m.detected) == 0

View File

@ -0,0 +1,21 @@
# Mobile Verification Toolkit (MVT)
# Copyright (c) 2021-2022 Claudio Guarnieri.
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
import os
import logging
from mvt.android.modules.androidqf.sms import SMS
from mvt.common.module import run_module
from ..utils import get_artifact_folder
class TestAndroidqfSMSAnalysis:
def test_androidqf_sms(self):
m = SMS(target_path=os.path.join(get_artifact_folder(), "androidqf"), log=logging)
run_module(m)
assert len(m.results) == 2
assert len(m.timeline) == 0
assert len(m.detected) == 0

Binary file not shown.

View File

@ -0,0 +1,10 @@
[dalvik.vm.appimageformat]: [lz4]
[dalvik.vm.dex2oat-Xms]: [64m]
[dalvik.vm.dex2oat-Xmx]: [512m]
[dalvik.vm.dex2oat-max-image-block-size]: [524288]
[dalvik.vm.dex2oat-minidebuginfo]: [true]
[dalvik.vm.dex2oat-resolve-startup-strings]: [true]
[dalvik.vm.dexopt.secondary]: [true]
[dalvik.vm.heapgrowthlimit]: [128m]
[dalvik.vm.heapmaxfree]: [8m]
[dalvik.vm.heapminfree]: [512k]

View File

@ -0,0 +1,16 @@
USER PID PPID VSZ RSS WCHAN ADDR S NAME
root 1 0 57912 2084 0 0 S init
root 2 0 0 0 0 0 S [kthreadd]
root 3 2 0 0 0 0 S [ksoftirqd/0]
root 5 2 0 0 0 0 S [kworker/0:0H]
root 6 2 0 0 0 0 S [kworker/u16:0]
root 7 2 0 0 0 0 S [rcu_preempt]
root 8 2 0 0 0 0 S [rcu_sched]
root 9 2 0 0 0 0 S [rcu_bh]
root 10 2 0 0 0 0 S [migration/0]
root 11 2 0 0 0 0 D [tz_worker_threa]
root 12 2 0 0 0 0 S [watchdog/0]
root 13 2 0 0 0 0 S [watchdog/1]
root 14 2 0 0 0 0 D [tz_worker_threa]
root 15 2 0 0 0 0 S [migration/1]
root 16 2 0 0 0 0 S [ksoftirqd/1]

View File

@ -0,0 +1,20 @@
# Mobile Verification Toolkit (MVT)
# Copyright (c) 2021-2022 Claudio Guarnieri.
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
import os
from click.testing import CliRunner
from mvt.android.cli import check_androidqf
from .utils import get_artifact_folder
class TestCheckAndroidqfCommand:
def test_check(self):
runner = CliRunner()
path = os.path.join(get_artifact_folder(), "androidqf")
result = runner.invoke(check_androidqf, [path])
assert result.exit_code == 0