-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a module to parse uninstalled apps from dumpsys data, for both bu…
…greport and AndroidQF output, and match them against package name IoCs.
- Loading branch information
Showing
12 changed files
with
257 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# 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 .artifact import AndroidArtifact | ||
|
||
|
||
class DumpsysPlatformCompatArtifact(AndroidArtifact): | ||
""" | ||
Parser for uninstalled apps listed in platform_compat section. | ||
""" | ||
|
||
def check_indicators(self) -> None: | ||
if not self.indicators: | ||
return | ||
|
||
for result in self.results: | ||
ioc = self.indicators.check_app_id(result["package_name"]) | ||
if ioc: | ||
result["matched_indicator"] = ioc | ||
self.detected.append(result) | ||
continue | ||
|
||
def parse(self, data: str) -> None: | ||
for line in data.splitlines(): | ||
if not line.startswith("ChangeId(168419799; name=DOWNSCALED;"): | ||
continue | ||
|
||
if line.strip() == "": | ||
break | ||
|
||
# Look for rawOverrides field | ||
if "rawOverrides={" in line: | ||
# Extract the content inside the braces for rawOverrides | ||
overrides_field = line.split("rawOverrides={", 1)[1].split("};", 1)[0] | ||
|
||
for entry in overrides_field.split(", "): | ||
# Extract app name | ||
uninstall_app = entry.split("=")[0].strip() | ||
|
||
self.results.append( | ||
{"package_name": uninstall_app} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
src/mvt/android/modules/androidqf/dumpsys_platform_compat.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# 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/ | ||
|
||
import logging | ||
from typing import Optional | ||
|
||
from mvt.android.artifacts.dumpsys_platform_compat import DumpsysPlatformCompatArtifact | ||
|
||
from .base import AndroidQFModule | ||
|
||
|
||
class DumpsysPlatformCompat(DumpsysPlatformCompatArtifact, AndroidQFModule): | ||
"""This module extracts details on uninstalled apps.""" | ||
|
||
def __init__( | ||
self, | ||
file_path: Optional[str] = None, | ||
target_path: Optional[str] = None, | ||
results_path: Optional[str] = None, | ||
module_options: Optional[dict] = None, | ||
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, | ||
module_options=module_options, | ||
log=log, | ||
results=results, | ||
) | ||
|
||
def run(self) -> None: | ||
dumpsys_file = self._get_files_by_pattern("*/dumpsys.txt") | ||
if not dumpsys_file: | ||
return | ||
|
||
data = self._get_file_content(dumpsys_file[0]).decode("utf-8", errors="replace") | ||
content = self.extract_dumpsys_section(data, "DUMP OF SERVICE platform_compat:") | ||
self.parse(content) | ||
|
||
self.log.info("Found %d uninstalled apps", len(self.results)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# 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/ | ||
|
||
import logging | ||
from typing import Optional | ||
|
||
from mvt.android.artifacts.dumpsys_platform_compat import DumpsysPlatformCompatArtifact | ||
|
||
from mvt.android.modules.bugreport.base import BugReportModule | ||
|
||
|
||
class PlatformCompat(DumpsysPlatformCompatArtifact, BugReportModule): | ||
"""This module extracts details on uninstalled apps.""" | ||
|
||
def __init__( | ||
self, | ||
file_path: Optional[str] = None, | ||
target_path: Optional[str] = None, | ||
results_path: Optional[str] = None, | ||
module_options: Optional[dict] = None, | ||
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, | ||
module_options=module_options, | ||
log=log, | ||
results=results, | ||
) | ||
|
||
def run(self) -> None: | ||
data = self._get_dumpstate_file() | ||
if not data: | ||
self.log.error( | ||
"Unable to find dumpstate file. " | ||
"Did you provide a valid bug report archive?" | ||
) | ||
return | ||
|
||
data = data.decode("utf-8", errors="replace") | ||
content = self.extract_dumpsys_section(data, "DUMP OF SERVICE platform_compat:") | ||
self.parse(content) | ||
|
||
self.log.info("Found %d uninstalled apps", len(self.results)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# 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/ | ||
import logging | ||
|
||
from mvt.android.artifacts.dumpsys_platform_compat import DumpsysPlatformCompatArtifact | ||
from mvt.common.indicators import Indicators | ||
|
||
from ..utils import get_artifact | ||
|
||
|
||
class TestDumpsysPlatformCompatArtifact: | ||
def test_parsing(self): | ||
dbi = DumpsysPlatformCompatArtifact() | ||
file = get_artifact("android_data/dumpsys_platform_compat.txt") | ||
with open(file) as f: | ||
data = f.read() | ||
|
||
assert len(dbi.results) == 0 | ||
dbi.parse(data) | ||
assert len(dbi.results) == 2 | ||
assert dbi.results[0]["package_name"] == "org.torproject.torbrowser" | ||
assert dbi.results[1]["package_name"] == "org.article19.circulo.next" | ||
|
||
def test_ioc_check(self, indicator_file): | ||
dbi = DumpsysPlatformCompatArtifact() | ||
file = get_artifact("android_data/dumpsys_platform_compat.txt") | ||
with open(file) as f: | ||
data = f.read() | ||
dbi.parse(data) | ||
|
||
ind = Indicators(log=logging.getLogger()) | ||
ind.parse_stix2(indicator_file) | ||
ind.ioc_collections[0]["app_ids"].append("org.torproject.torbrowser") | ||
ind.ioc_collections[0]["app_ids"].append("org.article19.circulo.next") | ||
dbi.indicators = ind | ||
assert len(dbi.detected) == 0 | ||
dbi.check_indicators() | ||
assert len(dbi.detected) == 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# 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 pathlib import Path | ||
|
||
from mvt.android.modules.androidqf.dumpsys_platform_compat import DumpsysPlatformCompat | ||
from mvt.common.module import run_module | ||
|
||
from ..utils import get_android_androidqf, list_files | ||
|
||
|
||
class TestDumpsysPlatformCompatModule: | ||
def test_parsing(self): | ||
data_path = get_android_androidqf() | ||
m = DumpsysPlatformCompat(target_path=data_path) | ||
files = list_files(data_path) | ||
parent_path = Path(data_path).absolute().parent.as_posix() | ||
m.from_folder(parent_path, files) | ||
run_module(m) | ||
assert len(m.results) == 2 | ||
assert len(m.detected) == 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
DUMP OF SERVICE platform_compat: | ||
ChangeId(180326845; name=OVERRIDE_MIN_ASPECT_RATIO_MEDIUM; disabled; overridable) | ||
ChangeId(189969744; name=DOWNSCALE_65; disabled; overridable) | ||
ChangeId(183372781; name=ENABLE_RAW_SYSTEM_GALLERY_ACCESS; enableSinceTargetSdk=30) | ||
ChangeId(150939131; name=ADD_CONTENT_OBSERVER_FLAGS; enableSinceTargetSdk=30) | ||
ChangeId(226439802; name=SCHEDULE_EXACT_ALARM_DENIED_BY_DEFAULT; disabled) | ||
ChangeId(270674727; name=ENABLE_STRICT_FORMATTER_VALIDATION; enableSinceTargetSdk=35) | ||
ChangeId(183155436; name=ALWAYS_USE_CONTEXT_USER; enableSinceTargetSdk=33) | ||
ChangeId(303742236; name=ROLE_MANAGER_USER_HANDLE_AWARE; enableSinceTargetSdk=35) | ||
ChangeId(203800354; name=MEDIA_CONTROL_SESSION_ACTIONS; enableSinceTargetSdk=33) | ||
ChangeId(144027538; name=BLOCK_GPS_STATUS_USAGE; enableSinceTargetSdk=31) | ||
ChangeId(189969749; name=DOWNSCALE_35; disabled; overridable) | ||
ChangeId(143539591; name=SELINUX_LATEST_CHANGES; disabled) | ||
ChangeId(247079863; name=DISALLOW_INVALID_GROUP_REFERENCE; enableSinceTargetSdk=34) | ||
ChangeId(174227820; name=FORCE_DISABLE_HEVC_SUPPORT; disabled) | ||
ChangeId(168419799; name=DOWNSCALED; disabled; packageOverrides={com.google.android.apps.tachyon=false, org.torproject.torbrowser=false}; rawOverrides={org.torproject.torbrowser=false, org.article19.circulo.next=false}; overridable) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters