Skip to content
Merged

V3 #716

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5d69635
Run bugreport and backup modules during check-androidqf
DonnchaC Feb 7, 2025
a08c24b
Deduplicate modules which are run by the sub-commands.
DonnchaC Feb 10, 2025
4c1cdf5
Raise the proper NoAndroidQFBackup exception when a back-up isn't found
DonnchaC Feb 11, 2025
064b9fb
Remove check-adb command and update docs
DonnchaC Feb 15, 2025
6bac787
Remove check-apk code and old dependencies
DonnchaC Feb 15, 2025
1b03002
Major refactor to add structured alerting and typed indicators
DonnchaC Feb 15, 2025
ca0bc46
Fix up, remove ADB module base
DonnchaC Feb 15, 2025
2d54766
Rework old detections tracking into stuctured alert levels
DonnchaC Feb 19, 2025
70d646a
Quote STIX path in log line
DonnchaC Oct 6, 2025
05ad7d2
Fix profile events log line
DonnchaC Oct 6, 2025
e9e6216
Close open archive (zip/tar) file handles
DonnchaC Oct 6, 2025
2302e74
Merge refactor/structured-alerting into v2
besendorf Nov 7, 2025
af8c566
Fix root_binaries and mounts modules to use alertstore
besendorf Nov 7, 2025
301582d
Update tests to use alertstore instead of detected attribute
besendorf Nov 7, 2025
5b1f4df
Fix alertstore method calls - use high() instead of warning()
besendorf Nov 7, 2025
4b6a101
Fix remaining test errors
besendorf Nov 7, 2025
d4b970c
Log alerts on add
besendorf Nov 7, 2025
d259ab4
Remove slug from alertstore calls
besendorf Nov 7, 2025
b1f0a2d
update alerts.py
besendorf Nov 7, 2025
c6837a4
update alerts.py
besendorf Nov 7, 2025
cc7781e
move indicator_match to alert object
besendorf Nov 7, 2025
6d1d499
.
besendorf Nov 7, 2025
801c464
- Remove timeline_detected and route to alertstore
besendorf Nov 7, 2025
c779009
fix typing for mypy
besendorf Dec 20, 2025
6a76191
Merge branch 'main' into v2
besendorf Jan 27, 2026
088a3f4
Remove unused type imports
besendorf Jan 27, 2026
81d508b
Merge branch 'main' into v2 - resolve conflicts in dumpsys_battery_da…
besendorf Mar 18, 2026
3311dcd
Merge branch 'main' into v2 - resolve formatting conflict in indicato…
besendorf Apr 1, 2026
3882251
Fix check_receiver_prefix and check_android_property_name
DonnchaC Apr 10, 2026
ddb8993
Fix residual self.detected usage in packages and dumpsys_receivers
DonnchaC Apr 10, 2026
5a919ea
Fix SMS module alertstore.high() call passing slug as message
DonnchaC Apr 10, 2026
e885281
Apply suggestions from code review
tesitura Apr 21, 2026
4990916
Merge remote-tracking branch 'origin/main' into v2
Apr 22, 2026
195d073
Remove unsupported ADB modules
Apr 22, 2026
14531f5
Fail removed check-adb command
Apr 22, 2026
a15858e
Fix alert serialization and logging
Apr 22, 2026
0f5a2e8
Close sqlite connections in iOS modules
Apr 22, 2026
644a3c4
Fix DEBUG messages not reaching handlers, save_to_json for dictionary…
tesitura Apr 22, 2026
3ae82fc
add matched_indicator via alertstore instead of directly modifying js…
Apr 27, 2026
a2ae284
Alert on battery daily uninstall and downgrade
Apr 27, 2026
b570668
Lower alert severity to medium for suspicious items
besendorf Apr 28, 2026
e93e825
Switch version to 2026.4.28 CalVer
Apr 28, 2026
97282c1
Merge branch 'main' into v2
besendorf Apr 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# Mobile Verification Toolkit

> [!IMPORTANT]
> [!IMPORTANT]
> Soon we will merge the v3 pull request which will result in breaking changes. If you rely on mvt output in other script make sure to the the branch before we merge. More details: https://github.com/mvt-project/mvt/issues/757

[![](https://img.shields.io/pypi/v/mvt)](https://pypi.org/project/mvt/)
Expand Down
57 changes: 15 additions & 42 deletions docs/android/adb.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,29 @@
# Check over ADB
# ADB Analysis Removed

In order to check an Android device over the [Android Debug Bridge (adb)](https://developer.android.com/studio/command-line/adb) you will first need to install [Android SDK Platform Tools](https://developer.android.com/studio/releases/platform-tools). If you have installed [Android Studio](https://developer.android.com/studio/) you should already have access to `adb` and other utilities.
The ability to analyze Android devices directly over the [Android Debug Bridge (adb)](https://developer.android.com/studio/command-line/adb) has been removed from MVT.

While many Linux distributions already package Android Platform Tools (for example `android-platform-tools-base` on Debian), it is preferable to install the most recent version from the official website. Packaged versions might be outdated and incompatible with most recent Android handsets.

Next you will need to enable debugging on the Android device you are testing. [Please follow the official instructions on how to do so.](https://developer.android.com/studio/command-line/adb)

## Connecting over USB

The easiest way to check the device is over a USB transport. You will need to have USB debugging enabled and the device plugged into your computer. If everything is configured appropriately you should see your device when launching the command `adb devices`.

Now you can try launching MVT with:

```bash
mvt-android check-adb --output /path/to/results
```

!!! warning
The `check-adb` command is deprecated and will be removed in a future release.
Whenever possible, prefer acquiring device data using the AndroidQF project (https://github.com/mvt-project/androidqf/) and then analyze those acquisitions with MVT.

Running `mvt-android check-adb` will also emit a runtime deprecation warning advising you to migrate to AndroidQF.

If you have previously started an adb daemon MVT will alert you and require you to kill it with `adb kill-server` and relaunch the command.

!!! warning
MVT relies on the Python library [adb-shell](https://pypi.org/project/adb-shell/) to connect to an Android device, which relies on libusb for the USB transport. Because of known driver issues, Windows users [are recommended](https://github.com/JeffLIrion/adb_shell/issues/118) to install appropriate drivers using [Zadig](https://zadig.akeo.ie/). Alternatively, an easier option might be to use the TCP transport and connect over Wi-Fi as describe next.

## Connecting over Wi-FI

When connecting to the device over USB is not possible or not working properly, an alternative option is to connect over the network. In order to do so, first launch an adb daemon at a fixed port number:
Use [AndroidQF](https://github.com/mvt-project/androidqf) to collect forensic artifacts from an Android device, then analyze the collected output with:

```bash
adb tcpip 5555
mvt-android check-androidqf /path/to/androidqf-output
```

Then you can specify the IP address of the phone with the adb port number to MVT like so:
For a standalone Android bug report, use:

```bash
mvt-android check-adb --serial 192.168.1.20:5555 --output /path/to/results
mvt-android check-bugreport /path/to/bugreport.zip
```

Where `192.168.1.20` is the correct IP address of your device.
## Reasons for Removal

!!! warning
The `check-adb` workflow shown above is deprecated. If you can acquire an AndroidQF acquisition from the device (recommended), use the AndroidQF project to create that acquisition: https://github.com/mvt-project/androidqf/

AndroidQF acquisitions provide a more stable, reproducible analysis surface and are the preferred workflow going forward.
1. **Inconsistent Data Collection Across Devices**
Android devices vary significantly in system architecture, security policy, and diagnostic log availability. This made it difficult to collect reliable forensic data across devices.

## MVT modules requiring root privileges
2. **Incomplete Forensic Data Acquisition**
Direct ADB analysis did not retrieve a complete forensic snapshot. Critical artifacts such as full bug reports could be missing.

!!! warning
Deprecated: many `mvt-android check-adb` workflows are deprecated and will be removed in a future release. Whenever possible, prefer acquiring an AndroidQF acquisition using the AndroidQF project (https://github.com/mvt-project/androidqf/).
3. **Duplicated Analysis Paths**
Similar artifacts were parsed through separate ADB, AndroidQF, and bugreport modules, which made behavior harder to keep consistent.

Of the currently available `mvt-android check-adb` modules a handful require root privileges to function correctly. This is because certain files, such as browser history and SMS messages databases are not accessible with user privileges through adb. These modules are to be considered OPTIONALLY available in case the device was already jailbroken. **Do NOT jailbreak your own device unless you are sure of what you are doing!** Jailbreaking your phone exposes it to considerable security risks!
4. **Workflow Consistency**
MVT now focuses on analyzing acquired artifacts rather than interacting with live devices directly.
28 changes: 0 additions & 28 deletions docs/android/download_apks.md

This file was deleted.

46 changes: 37 additions & 9 deletions docs/android/methodology.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,51 @@
# Methodology for Android forensic

Unfortunately Android devices provide much less observability than their iOS cousins. Android stores very little diagnostic information useful to triage potential compromises, and because of this `mvt-android` capabilities are limited as well.
Unfortunately Android devices provide fewer complete forensically useful datasources than their iOS cousins. Unlike iOS, the Android backup feature only provides a limited about of relevant data.

Android diagnostic logs such as *bugreport files* can be inconsistent in format and structure across different Android versions and device vendors. The limited diagnostic information available makes it difficult to triage potential compromises, and because of this `mvt-android` capabilities are limited as well.

However, not all is lost.

## Check installed Apps
## Check Android devices with AndroidQF and MVT

The [AndroidQF](https://github.com/mvt-project/androidqf) tool can be used to collect a wide range of forensic artifacts from an Android device including an Android backup, a bugreport file, and a range of system logs. MVT natively supports analyzing the generated AndroidQF output for signs of device compromise.

### Why Use AndroidQF?

- **Complete and raw data extraction**
AndroidQF collects full forensic artifacts using an on-device forensic collection agent, ensuring that no crucial data is overlooked. The data collection does not depended on the shell environment or utilities available on the device.

- **Consistent and standardized output**
By collecting a predefined and complete set of forensic files, AndroidQF ensures consistency in data acquisition across different Android devices.

- **Future-proof analysis**
Since the full forensic artifacts are preserved, analysts can extract new evidence or apply updated analysis techniques without requiring access to the original device.

Because malware attacks over Android typically take the form of malicious or backdoored apps, the very first thing you might want to do is to extract and verify all installed Android packages and triage quickly if there are any which stand out as malicious or which might be atypical.
- **Cross-platform tool without dependencies**
AndroidQF is a standalone Go binary which can be used to remotely collect data from an Android device without the device owner needing to install MVT or a Python environment.

While it is out of the scope of this documentation to dwell into details on how to analyze Android apps, MVT does allow to easily and automatically extract information about installed apps, download copies of them, and quickly look them up on services such as [VirusTotal](https://www.virustotal.com).
### Workflow for Android Forensic Analysis with AndroidQF

!!! info "Using VirusTotal"
Please note that in order to use VirusTotal lookups you are required to provide your own API key through the `MVT_VT_API_KEY` environment variable. You should also note that VirusTotal enforces strict API usage. Be mindful that MVT might consume your hourly search quota.
With AndroidQF the analysis process is split into a separate data collection and data analysis stages.

## Check the device over Android Debug Bridge
1. **Extract Data Using AndroidQF**
Deploy the AndroidQF forensic collector to acquire all relevant forensic artifacts from the Android device.

Some additional diagnostic information can be extracted from the phone using the [Android Debug Bridge (adb)](https://developer.android.com/studio/command-line/adb). `mvt-android` allows to automatically extract information including [dumpsys](https://developer.android.com/studio/command-line/dumpsys) results, details on installed packages (without download), running processes, presence of root binaries and packages, and more.
2. **Analyze Extracted Data with MVT**
Use the `mvt-android check-androidqf` command to perform forensic analysis on the extracted artifacts.

By separating artifact collection from forensic analysis, this approach ensures a more reliable and scalable methodology for Android forensic investigations.

For more information, refer to the [AndroidQF project documentation](https://github.com/mvt-project/androidqf).

## Android Debug Bridge analysis removed

The ability to analyze Android devices directly over ADB has been removed from MVT. Use AndroidQF for device acquisition and `mvt-android check-androidqf` for analysis.

## Check an Android Backup (SMS messages)

Although Android backups are becoming deprecated, it is still possible to generate one. Unfortunately, because apps these days typically favor backup over the cloud, the amount of data available is limited. Currently, `mvt-android check-backup` only supports checking SMS messages containing links.
Although Android backups are becoming deprecated, it is still possible to generate one. Unfortunately, because apps these days typically favor backup over the cloud, the amount of data available is limited.

The `mvt-android check-androidqf` command will automatically check an Android backup and SMS messages if an SMS backup is included in the AndroidQF extraction.

The `mvt-android check-backup` command can also be used directly with an Android backup file.
19 changes: 1 addition & 18 deletions docs/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,4 @@ Test if the image was created successfully:
docker run -it mvt
```

If a prompt is spawned successfully, you can close it with `exit`.


## Docker usage with Android devices

If you wish to use MVT to test an Android device you will need to enable the container's access to the host's USB devices. You can do so by enabling the `--privileged` flag and mounting the USB bus device as a volume:

```bash
docker run -it --privileged -v /dev/bus/usb:/dev/bus/usb mvt
```

**Please note:** the `--privileged` parameter is generally regarded as a security risk. If you want to learn more about this check out [this explainer on container escapes](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/) as it gives access to the whole system.

Recent versions of Docker provide a `--device` parameter allowing to specify a precise USB device without enabling `--privileged`:

```bash
docker run -it --device=/dev/<your_usb_port> mvt
```
If a prompt is spawned successfully, you can close it with `exit`.
2 changes: 0 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ nav:
- Records extracted by mvt-ios: "ios/records.md"
- MVT for Android:
- Android Forensic Methodology: "android/methodology.md"
- Check over ADB: "android/adb.md"
- Check an Android Backup (SMS messages): "android/backup.md"
- Download APKs: "android/download_apks.md"
- Indicators of Compromise: "iocs.md"
- Development: "development.md"
- License: "license.md"
42 changes: 29 additions & 13 deletions src/mvt/android/artifacts/artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,39 @@ def extract_dumpsys_section(
:param binary: whether the dumpsys should be pared as binary or not (bool)
:return: section extracted (string or bytes)
"""
lines = []
in_section = False
delimiter = "------------------------------------------------------------------------------"
delimiter_str = "------------------------------------------------------------------------------"
delimiter_bytes = b"------------------------------------------------------------------------------"

if binary:
delimiter = delimiter.encode("utf-8")
lines_bytes = []
for line in dumpsys.splitlines(): # type: ignore[union-attr]
if line.strip() == separator: # type: ignore[arg-type]
in_section = True
continue

if not in_section:
continue

if line.strip().startswith(delimiter_bytes): # type: ignore[arg-type]
break

lines_bytes.append(line) # type: ignore[arg-type]

for line in dumpsys.splitlines():
if line.strip() == separator:
in_section = True
continue
return b"\n".join(lines_bytes) # type: ignore[return-value,arg-type]
else:
lines_str = []
for line in dumpsys.splitlines(): # type: ignore[union-attr]
if line.strip() == separator: # type: ignore[arg-type]
in_section = True
continue

if not in_section:
continue
if not in_section:
continue

if line.strip().startswith(delimiter):
break
if line.strip().startswith(delimiter_str): # type: ignore[arg-type]
break

lines.append(line)
lines_str.append(line) # type: ignore[arg-type]

return b"\n".join(lines) if binary else "\n".join(lines)
return "\n".join(lines_str) # type: ignore[return-value,arg-type]
9 changes: 5 additions & 4 deletions src/mvt/android/artifacts/dumpsys_accessibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ def check_indicators(self) -> None:
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)
ioc_match = self.indicators.check_app_id(result["package_name"])
if ioc_match:
self.alertstore.critical(
ioc_match.message, "", result, matched_indicator=ioc_match.ioc
)
continue

def parse(self, content: str) -> None:
Expand Down
2 changes: 1 addition & 1 deletion src/mvt/android/artifacts/dumpsys_adb.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def parse_xml(self, xml_data):
return keystore

@staticmethod
def calculate_key_info(user_key: bytes) -> str:
def calculate_key_info(user_key: bytes) -> dict:
if b" " in user_key:
key_base64, user = user_key.split(b" ", 1)
else:
Expand Down
Loading
Loading