From 911115b0c8e7769e7f4bcaf505012cb2380ef9b5 Mon Sep 17 00:00:00 2001 From: besendorf Date: Wed, 15 Jul 2026 08:32:13 +0200 Subject: [PATCH] Match receiver indicators by package ID (#836) --- .../modules/bugreport/dumpsys_receivers.py | 18 ------------- src/mvt/common/indicators.py | 23 ---------------- tests/android_bugreport/test_bugreport.py | 26 +++++++++++++++++++ 3 files changed, 26 insertions(+), 41 deletions(-) diff --git a/src/mvt/android/modules/bugreport/dumpsys_receivers.py b/src/mvt/android/modules/bugreport/dumpsys_receivers.py index ded9069..8907d5e 100644 --- a/src/mvt/android/modules/bugreport/dumpsys_receivers.py +++ b/src/mvt/android/modules/bugreport/dumpsys_receivers.py @@ -35,24 +35,6 @@ class DumpsysReceivers(DumpsysReceiversArtifact, BugReportModule): self.results = results if results else {} - def check_indicators(self) -> None: - for result in self.results: - if self.indicators: - receiver_name = self.results[result][0]["receiver"] - - # return IoC if the stix2 process name a substring of the receiver name - ioc_match = self.indicators.check_receiver_prefix(receiver_name) - if ioc_match: - self.alertstore.critical( - ioc_match.message, - "", - self.results[result][0], - matched_indicator=ioc_match.ioc, - ) - continue - - - def run(self) -> None: content = self._get_dumpstate_file() if not content: diff --git a/src/mvt/common/indicators.py b/src/mvt/common/indicators.py index 39334a6..215c1ef 100644 --- a/src/mvt/common/indicators.py +++ b/src/mvt/common/indicators.py @@ -727,29 +727,6 @@ class Indicators: return None - def check_receiver_prefix( - self, receiver_name: str - ) -> Optional[IndicatorMatch]: - """Check the provided receiver name against the list of indicators. - An IoC match is detected when a substring of the receiver matches the indicator. - - :param receiver_name: Receiver name to check against app ID indicators - :type receiver_name: str - :returns: IndicatorMatch if matched, otherwise None - - """ - if not receiver_name: - return None - - for ioc in self.get_iocs("app_ids"): - if ioc.value.lower() in receiver_name.lower(): - return IndicatorMatch( - ioc=ioc, - message=f'Found a known suspicious receiver with name "{receiver_name}" matching indicators from "{ioc.name}"', - ) - - return None - def check_android_property_name( self, property_name: str ) -> Optional[IndicatorMatch]: diff --git a/tests/android_bugreport/test_bugreport.py b/tests/android_bugreport/test_bugreport.py index a2c5e37..2bfaef5 100644 --- a/tests/android_bugreport/test_bugreport.py +++ b/tests/android_bugreport/test_bugreport.py @@ -9,6 +9,7 @@ from pathlib import Path from mvt.android.modules.bugreport.dumpsys_appops import DumpsysAppops from mvt.android.modules.bugreport.dumpsys_getprop import DumpsysGetProp from mvt.android.modules.bugreport.dumpsys_packages import DumpsysPackages +from mvt.android.modules.bugreport.dumpsys_receivers import DumpsysReceivers from mvt.android.modules.bugreport.tombstones import Tombstones from mvt.common.module import run_module @@ -60,6 +61,31 @@ class TestBugreportAnalysis: m = self.launch_bug_report_module(DumpsysGetProp) assert len(m.results) == 0 + def test_receivers_match_exact_package_name(self, indicators_factory): + intent = "android.intent.action.PHONE_STATE" + false_positive = { + "package_name": "com.android.phone", + "receiver": ( + "com.android.phone/" + "com.android.services.telephony.sip.SipIncomingCallReceiver" + ), + } + malicious_receiver = { + "package_name": "com.android.services", + "receiver": "com.android.services/com.example.SomeReceiver", + } + module = DumpsysReceivers( + results={intent: [false_positive, malicious_receiver]} + ) + module.indicators = indicators_factory(app_ids=["com.android.services"]) + + module.check_indicators() + + assert len(module.alertstore.alerts) == 1 + alert = module.alertstore.alerts[0] + assert alert.event == {intent: malicious_receiver} + assert alert.matched_indicator.value == "com.android.services" + def test_tombstones_modules(self): m = self.launch_bug_report_module(Tombstones) assert len(m.results) == 2