diff --git a/src/mvt/android/artifacts/dumpsys_receivers.py b/src/mvt/android/artifacts/dumpsys_receivers.py index c7130ed..b437930 100644 --- a/src/mvt/android/artifacts/dumpsys_receivers.py +++ b/src/mvt/android/artifacts/dumpsys_receivers.py @@ -96,6 +96,18 @@ class DumpsysReceiversArtifact(AndroidArtifact): self.results[intent] = [] continue + parts = line.strip().split(" ") + if len(parts) < 2: + # A single-token line here is not a receiver. Real dumpstate + # output can print an action header mis-indented (observed with + # 15 leading spaces instead of 6), which used to raise + # IndexError and abort the whole module. Treat a trailing-colon + # token as the next action, skip anything else. + if parts[0].endswith(":"): + intent = parts[0][:-1] + self.results.setdefault(intent, []) + continue + # If we are not in an intent block yet, skip. if not intent: continue @@ -109,7 +121,7 @@ class DumpsysReceiversArtifact(AndroidArtifact): # If we got this far, we are processing receivers for the # activities we are interested in. - receiver = line.strip().split(" ")[1] + receiver = parts[1] package_name = receiver.split("/")[0] self.results[intent].append( diff --git a/tests/android/test_artifact_dumpsys_receivers.py b/tests/android/test_artifact_dumpsys_receivers.py index e4bed62..7875a52 100644 --- a/tests/android/test_artifact_dumpsys_receivers.py +++ b/tests/android/test_artifact_dumpsys_receivers.py @@ -31,6 +31,44 @@ class TestDumpsysReceiversArtifact: == "com.android.storagemanager" ) + def test_parsing_misindented_action(self): + dr = DumpsysReceiversArtifact() + data = """\ +Receiver Resolver Table: + Non-Data Actions: + android.app.action.ENTER_CAR_MODE: + b5b40f6 com.google.android.projection.gearhead/.CarModeBroadcastReceiver + android.intent.action.MY_PACKAGE_REPLACED: + e7706c1 com.psycatgames.nhiegame/.ScheduledNotificationBootReceiver +""" + + dr.parse(data) + + assert ( + dr.results["android.intent.action.MY_PACKAGE_REPLACED"][0][ + "package_name" + ] + == "com.psycatgames.nhiegame" + ) + + def test_parsing_misindented_first_action(self): + dr = DumpsysReceiversArtifact() + data = """\ +Receiver Resolver Table: + Non-Data Actions: + android.intent.action.MY_PACKAGE_REPLACED: + e7706c1 com.psycatgames.nhiegame/.ScheduledNotificationBootReceiver +""" + + dr.parse(data) + + assert ( + dr.results["android.intent.action.MY_PACKAGE_REPLACED"][0][ + "package_name" + ] + == "com.psycatgames.nhiegame" + ) + def test_ioc_check(self, indicator_file): dr = DumpsysReceiversArtifact() file = get_artifact("android_data/dumpsys_packages.txt")