mirror of
https://github.com/mvt-project/mvt.git
synced 2024-06-26 14:28:54 +00:00
Adds SMS androidqf module and improves tests
This commit is contained in:
parent
41826d7951
commit
ba0106c476
|
@ -71,6 +71,16 @@ SECURITY_PACKAGES = [
|
|||
"com.samsung.android.app.omcagent",
|
||||
"com.samsung.android.securitylogagent",
|
||||
"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",
|
||||
]
|
||||
|
||||
|
@ -133,6 +143,10 @@ class Packages(AndroidExtraction):
|
|||
self.log.warning("Found a security package disabled: \"%s\"",
|
||||
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:
|
||||
continue
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ from .dumpsys_receivers import DumpsysReceivers
|
|||
from .getprop import Getprop
|
||||
from .processes import Processes
|
||||
from .settings import Settings
|
||||
from .sms import SMS
|
||||
|
||||
ANDROIDQF_MODULES = [DumpsysActivities, DumpsysReceivers, DumpsysAccessibility,
|
||||
DumpsysAppops, Processes, Getprop, Settings]
|
||||
DumpsysAppops, Processes, Getprop, Settings, SMS]
|
||||
|
|
85
mvt/android/modules/androidqf/sms.py
Normal file
85
mvt/android/modules/androidqf/sms.py
Normal 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))
|
22
tests/android/test_androidqf_getprop.py
Normal file
22
tests/android/test_androidqf_getprop.py
Normal 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
|
21
tests/android/test_androidqf_processes.py
Normal file
21
tests/android/test_androidqf_processes.py
Normal 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
|
21
tests/android/test_androidqf_sms.py
Normal file
21
tests/android/test_androidqf_sms.py
Normal 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
|
BIN
tests/artifacts/androidqf/backup.ab
Normal file
BIN
tests/artifacts/androidqf/backup.ab
Normal file
Binary file not shown.
10
tests/artifacts/androidqf/getprop.txt
Normal file
10
tests/artifacts/androidqf/getprop.txt
Normal 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]
|
16
tests/artifacts/androidqf/ps.txt
Normal file
16
tests/artifacts/androidqf/ps.txt
Normal 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]
|
20
tests/test_check_android_androidqf.py
Normal file
20
tests/test_check_android_androidqf.py
Normal 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
|
Loading…
Reference in New Issue
Block a user