mirror of
https://github.com/mvt-project/mvt.git
synced 2026-02-14 17:42:46 +00:00
Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbd41b2aff | ||
|
|
0509eaa162 | ||
|
|
59e6dff1e1 | ||
|
|
f1821d1a02 | ||
|
|
6c7ad0ac95 | ||
|
|
3a997d30d2 | ||
|
|
6f56939dd7 | ||
|
|
7a4946e2c6 | ||
|
|
e1c4f4eb7a | ||
|
|
f9d7b550dc | ||
|
|
b738603911 | ||
|
|
5826e6b11c | ||
|
|
54c5d549af | ||
|
|
dded863e58 | ||
|
|
fc7ea5383e | ||
|
|
04b78a4d60 | ||
|
|
4ea53d707b | ||
|
|
da743a2878 | ||
|
|
4681b57adc | ||
|
|
bb7a22ed0b | ||
|
|
b2df17b4a0 | ||
|
|
278611a753 | ||
|
|
cd4d468553 | ||
|
|
1182587094 | ||
|
|
ad3bc3470e | ||
|
|
2c5ae696b1 | ||
|
|
5d2ff32e3a | ||
|
|
2838bac63f | ||
|
|
b7df87a62f | ||
|
|
013282dbba | ||
|
|
ab33789f06 | ||
|
|
a1571c127d | ||
|
|
61f33f7ecb | ||
|
|
4a6b483ce3 | ||
|
|
101098cbb7 | ||
|
|
fd3ef76873 | ||
|
|
fb52f73556 | ||
|
|
acc950377f | ||
|
|
c8a0327768 | ||
|
|
1d075abde9 | ||
|
|
73104814ba | ||
|
|
2098201024 | ||
|
|
4b4cad46ba | ||
|
|
815678dff7 | ||
|
|
bdd0124b80 | ||
|
|
894b99b177 | ||
|
|
8796a0b965 | ||
|
|
f786e2c9bf | ||
|
|
5b0fdd117c | ||
|
|
7b1c0f6443 | ||
|
|
353381a7d6 | ||
|
|
5462c8d6e7 | ||
|
|
63299b530b | ||
|
|
737d17086c | ||
|
|
499ded4e7b | ||
|
|
63c4dea3d0 | ||
|
|
e872e34c5a | ||
|
|
4f3a16daf0 | ||
|
|
eb5bfb7f35 | ||
|
|
a7da992d75 | ||
|
|
652dedd620 | ||
|
|
4bdb97ebcc | ||
|
|
da6116ee20 | ||
|
|
65cee2ae53 | ||
|
|
97af2d3605 | ||
|
|
b39936a060 | ||
|
|
94a98b4f83 | ||
|
|
0c7ea142f7 | ||
|
|
e96ffbb022 | ||
|
|
ba1d9699c3 | ||
|
|
9988887d27 | ||
|
|
04b44826b4 | ||
|
|
2bfe5443c8 |
19
.github/workflows/add-issue-to-project.yml
vendored
Normal file
19
.github/workflows/add-issue-to-project.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Add issue to project
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
|
||||
jobs:
|
||||
add-to-project:
|
||||
name: Add issue to project
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@v0.5.0
|
||||
with:
|
||||
# You can target a project in a different organization
|
||||
# to the issue
|
||||
project-url: https://github.com/orgs/mvt-project/projects/1
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
||||
7
.github/workflows/python-package.yml
vendored
7
.github/workflows/python-package.yml
vendored
@@ -40,10 +40,13 @@ jobs:
|
||||
- name: Safety checks
|
||||
run: safety check
|
||||
- name: Test with pytest and coverage
|
||||
run: pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=mvt tests/ | tee pytest-coverage.txt
|
||||
run: |
|
||||
set -o pipefail
|
||||
pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=mvt tests/ | tee pytest-coverage.txt
|
||||
- name: Pytest coverage comment
|
||||
continue-on-error: true # Workflows running on a fork can't post comments
|
||||
uses: MishaKav/pytest-coverage-comment@main
|
||||
if: github.event_name == 'pull_request'
|
||||
with:
|
||||
pytest-coverage-path: ./pytest-coverage.txt
|
||||
junitxml-path: ./pytest.xml
|
||||
junitxml-path: ./pytest.xml
|
||||
|
||||
2
.github/workflows/ruff.yml
vendored
2
.github/workflows/ruff.yml
vendored
@@ -16,4 +16,4 @@ jobs:
|
||||
pip install --user ruff
|
||||
- name: ruff
|
||||
run: |
|
||||
ruff --format=github .
|
||||
ruff check --output-format github .
|
||||
|
||||
13
.github/workflows/scripts/update-ios-releases.py
vendored
13
.github/workflows/scripts/update-ios-releases.py
vendored
@@ -35,13 +35,20 @@ def parse_latest_ios_versions(rss_feed_text):
|
||||
print("Could not parse iOS build:", title)
|
||||
continue
|
||||
|
||||
# Handle iOS beta releases
|
||||
release_info = build_match.groupdict()
|
||||
if release_info["beta"]:
|
||||
release_beta = release_info.pop("beta")
|
||||
if release_beta:
|
||||
print("Skipping beta release:", title)
|
||||
continue
|
||||
|
||||
release_info.pop("beta")
|
||||
latest_ios_versions.append(release_info)
|
||||
# Some iOS releases have multiple build number for different hardware models.
|
||||
# We will split these into separate entries and record each build number.
|
||||
build_list = release_info.pop("build")
|
||||
build_variants = build_list.split(" | ")
|
||||
for build_number in build_variants:
|
||||
release_info["build"] = build_number
|
||||
latest_ios_versions.append(release_info)
|
||||
|
||||
return latest_ios_versions
|
||||
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
build:
|
||||
os: "ubuntu-22.04"
|
||||
tools:
|
||||
python: "3.11"
|
||||
|
||||
mkdocs:
|
||||
configuration: mkdocs.yml
|
||||
|
||||
# Optionally set the version of Python and requirements required to build your docs
|
||||
python:
|
||||
version: 3.7
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
@@ -57,12 +57,12 @@ RUN git clone https://github.com/libimobiledevice/libplist \
|
||||
|
||||
# Installing MVT
|
||||
# --------------
|
||||
RUN pip3 install mvt
|
||||
RUN pip3 install git+https://github.com/mvt-project/mvt.git@main
|
||||
|
||||
# Installing ABE
|
||||
# --------------
|
||||
RUN mkdir /opt/abe \
|
||||
&& wget https://github.com/nelenkov/android-backup-extractor/releases/download/20210709062403-4c55371/abe.jar -O /opt/abe/abe.jar \
|
||||
&& wget https://github.com/nelenkov/android-backup-extractor/releases/download/master-20221109063121-8fdfc5e/abe.jar -O /opt/abe/abe.jar \
|
||||
# Create alias for abe
|
||||
&& echo 'alias abe="java -jar /opt/abe/abe.jar"' >> ~/.bashrc
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
Mobile Verification Toolkit (MVT) is a collection of utilities to simplify and automate the process of gathering forensic traces helpful to identify a potential compromise of Android and iOS devices.
|
||||
|
||||
It has been developed and released by the [Amnesty International Security Lab](https://www.amnesty.org/en/tech/) in July 2021 in the context of the [Pegasus Project](https://forbiddenstories.org/about-the-pegasus-project/) along with [a technical forensic methodology](https://www.amnesty.org/en/latest/research/2021/07/forensic-methodology-report-how-to-catch-nso-groups-pegasus/). It continues to be maintained by Amnesty International and other contributors.
|
||||
It has been developed and released by the [Amnesty International Security Lab](https://securitylab.amnesty.org) in July 2021 in the context of the [Pegasus Project](https://forbiddenstories.org/about-the-pegasus-project/) along with [a technical forensic methodology](https://www.amnesty.org/en/latest/research/2021/07/forensic-methodology-report-how-to-catch-nso-groups-pegasus/). It continues to be maintained by Amnesty International and other contributors.
|
||||
|
||||
> **Note**
|
||||
> MVT is a forensic research tool intended for technologists and investigators. It requires understanding digital forensics and using command-line tools. This is not intended for end-user self-assessment. If you are concerned with the security of your device please seek reputable expert assistance.
|
||||
@@ -26,13 +26,13 @@ MVT supports using public [indicators of compromise (IOCs)](https://github.com/m
|
||||
>
|
||||
> Reliable and comprehensive digital forensic support and triage requires access to non-public indicators, research and threat intelligence.
|
||||
>
|
||||
>Such support is available to civil society through [Amnesty International's Security Lab](https://www.amnesty.org/en/tech/) or through our forensic partnership with [Access Now’s Digital Security Helpline](https://www.accessnow.org/help/).
|
||||
>Such support is available to civil society through [Amnesty International's Security Lab](https://securitylab.amnesty.org/get-help/?c=mvt_docs) or through our forensic partnership with [Access Now’s Digital Security Helpline](https://www.accessnow.org/help/).
|
||||
|
||||
More information about using indicators of compromise with MVT is available in the [documentation](https://docs.mvt.re/en/latest/iocs/).
|
||||
|
||||
## Installation
|
||||
|
||||
MVT can be installed from sources or from [PyPi](https://pypi.org/project/mvt/) (you will need some dependencies, check the [documentation](https://docs.mvt.re/en/latest/install/)):
|
||||
MVT can be installed from sources or from [PyPI](https://pypi.org/project/mvt/) (you will need some dependencies, check the [documentation](https://docs.mvt.re/en/latest/install/)):
|
||||
|
||||
```
|
||||
pip3 install mvt
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
Mobile Verification Toolkit (MVT) is a tool to facilitate the [consensual forensic analysis](introduction.md#consensual-forensics) of Android and iOS devices, for the purpose of identifying traces of compromise.
|
||||
|
||||
It has been developed and released by the [Amnesty International Security Lab](https://www.amnesty.org/en/tech/) in July 2021 in the context of the [Pegasus Project](https://forbiddenstories.org/about-the-pegasus-project/) along with [a technical forensic methodology](https://www.amnesty.org/en/latest/research/2021/07/forensic-methodology-report-how-to-catch-nso-groups-pegasus/). It continues to be maintained by Amnesty International and other contributors.
|
||||
It has been developed and released by the [Amnesty International Security Lab](https://securitylab.amnesty.org) in July 2021 in the context of the [Pegasus Project](https://forbiddenstories.org/about-the-pegasus-project/) along with [a technical forensic methodology](https://www.amnesty.org/en/latest/research/2021/07/forensic-methodology-report-how-to-catch-nso-groups-pegasus/). It continues to be maintained by Amnesty International and other contributors.
|
||||
|
||||
|
||||
In this documentation you will find instructions on how to install and run the `mvt-ios` and `mvt-android` commands, and guidance on how to interpret the extracted results.
|
||||
|
||||
@@ -7,11 +7,27 @@ Before proceeding, please note that MVT requires Python 3.6+ to run. While it sh
|
||||
First install some basic dependencies that will be necessary to build all required tools:
|
||||
|
||||
```bash
|
||||
sudo apt install python3 python3-pip libusb-1.0-0 sqlite3
|
||||
sudo apt install python3 python3-venv python3-pip sqlite3 libusb-1.0-0
|
||||
```
|
||||
|
||||
*libusb-1.0-0* is not required if you intend to only use `mvt-ios` and not `mvt-android`.
|
||||
|
||||
(Recommended) Set up `pipx`
|
||||
|
||||
For Ubuntu 23.04 or above:
|
||||
```bash
|
||||
sudo apt install pipx
|
||||
pipx ensurepath
|
||||
```
|
||||
|
||||
For Ubuntu 22.04 or below:
|
||||
```
|
||||
python3 -m pip install --user pipx
|
||||
python3 -m pipx ensurepath
|
||||
```
|
||||
|
||||
Other distributions: check for a `pipx` or `python-pipx` via your package manager.
|
||||
|
||||
When working with Android devices you should additionally install [Android SDK Platform Tools](https://developer.android.com/studio/releases/platform-tools). If you prefer to install a package made available by your distribution of choice, please make sure the version is recent to ensure compatibility with modern Android devices.
|
||||
|
||||
## Dependencies on macOS
|
||||
@@ -21,7 +37,7 @@ Running MVT on macOS requires Xcode and [homebrew](https://brew.sh) to be instal
|
||||
In order to install dependencies use:
|
||||
|
||||
```bash
|
||||
brew install python3 libusb sqlite3
|
||||
brew install python3 pipx libusb sqlite3
|
||||
```
|
||||
|
||||
*libusb* is not required if you intend to only use `mvt-ios` and not `mvt-android`.
|
||||
@@ -42,24 +58,43 @@ It is recommended to try installing and running MVT from [Windows Subsystem Linu
|
||||
|
||||
## Installing MVT
|
||||
|
||||
If you haven't done so, you can add this to your `.bashrc` or `.zshrc` file in order to add locally installed Pypi binaries to your `$PATH`:
|
||||
### Installing from PyPI with pipx (recommended)
|
||||
1. Install `pipx` following the instructions above for your OS/distribution. Make sure to run `pipx ensurepath` and open a new terminal window.
|
||||
2. ```bash
|
||||
pipx install mvt
|
||||
```
|
||||
|
||||
You now should have the `mvt-ios` and `mvt-android` utilities installed. If you run into problems with these commands not being found, ensure you have run `pipx ensurepath` and opened a new terminal window.
|
||||
|
||||
### Installing from PyPI directly into a virtual environment
|
||||
You can use `pipenv`, `poetry` etc. for your virtual environment, but the provided example is with the built-in `venv` tool:
|
||||
|
||||
1. Create the virtual environment in a folder in the current directory named `env`:
|
||||
```bash
|
||||
export PATH=$PATH:~/.local/bin
|
||||
python3 -m venv env
|
||||
```
|
||||
|
||||
Then you can install MVT directly from [pypi](https://pypi.org/project/mvt/)
|
||||
|
||||
2. Activate the virtual environment:
|
||||
```bash
|
||||
pip3 install mvt
|
||||
source env/bin/activate
|
||||
```
|
||||
|
||||
If you want to have the latest features in development, you can install MVT directly from the source code. If you installed MVT previously from pypi, you should first uninstall it using `pip3 uninstall mvt` and then install from the source code:
|
||||
3. Install `mvt` into the virtual environment:
|
||||
```bash
|
||||
pip install mvt
|
||||
```
|
||||
|
||||
The `mvt-ios` and `mvt-android` utilities should now be available as commands whenever the virtual environment is active.
|
||||
|
||||
### Installing from git source with pipx
|
||||
If you want to have the latest features in development, you can install MVT directly from the source code in git.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mvt-project/mvt.git
|
||||
cd mvt
|
||||
pip3 install .
|
||||
pipx install --force git+https://github.com/mvt-project/mvt.git
|
||||
```
|
||||
|
||||
You now should have the `mvt-ios` and `mvt-android` utilities installed.
|
||||
|
||||
**Notes:**
|
||||
1. The `--force` flag is necessary to force the reinstallation of the package.
|
||||
2. To revert to using a PyPI version, it will be necessary to `pipx uninstall mvt` first.
|
||||
|
||||
@@ -21,7 +21,7 @@ MVT supports using [indicators of compromise (IOCs)](https://github.com/mvt-proj
|
||||
|
||||
Reliable and comprehensive digital forensic support and triage requires access to non-public indicators, research and threat intelligence.
|
||||
|
||||
Such support is available to civil society through [Amnesty International's Security Lab](https://www.amnesty.org/en/tech/) or [Access Now’s Digital Security Helpline](https://www.accessnow.org/help/).
|
||||
Such support is available to civil society through [Amnesty International's Security Lab](https://securitylab.amnesty.org/get-help/?c=mvt_docs) or [Access Now’s Digital Security Helpline](https://www.accessnow.org/help/).
|
||||
|
||||
More information about using indicators of compromise with MVT is available in the [documentation](iocs.md).
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ To do that:
|
||||
4. If you want to have a more accurate detection, ensure that the encrypted backup option is activated and choose a secure password for the backup.
|
||||
5. Start the backup and wait for it to finish (this may take up to 30 minutes).
|
||||
|
||||

|
||||

|
||||
_Source: [Apple Support](https://support.apple.com/en-us/HT211229)_
|
||||
|
||||
Once the backup is done, find its location and copy it to a place where it can be analyzed by MVT. On Windows, the backup can be stored either in `%USERPROFILE%\Apple\MobileSync\` or `%USERPROFILE%\AppData\Roaming\Apple Computer\MobileSync\`. On macOS, the backup is stored in `~/Library/Application Support/MobileSync/`.
|
||||
@@ -25,13 +25,13 @@ On more recent MacOS versions, this feature is included in Finder. To do a backu
|
||||
4. In the General tab, select `Back up all the data on your iPhone to this Mac` from the options under the Backups section.
|
||||
5. Check the box that says `Encrypt local backup`. If it is your first time selecting this option, you may need to enter a password to encrypt the backup.
|
||||
|
||||

|
||||

|
||||
_Source: [Apple Support](https://support.apple.com/en-us/HT211229)_
|
||||
|
||||
6. Click `Back Up Now` to start the back-up process.
|
||||
7. The encrypted backup for your iPhone should now start. Once the process finishes, you can check the backup by opening `Finder`, clicking on the `General` tab, then click on `Manage Backups`. Now you should see a list of your backups like the image below:
|
||||
|
||||

|
||||

|
||||
_Source: [Apple Support](https://support.apple.com/en-us/HT211229)_
|
||||
|
||||
If your backup has a lock next to it like in the image above, then the backup is encrypted. You should also see the date and time when the encrypted backup was created. The backup files are stored in `~/Library/Application Support/MobileSync/`.
|
||||
|
||||
@@ -45,10 +45,10 @@ Once the idevice tools are available you can check if everything works fine by c
|
||||
ideviceinfo
|
||||
```
|
||||
|
||||
This should some many details on the connected iOS device. If you are connecting the device to your laptop for the first time, it will require to unlock and enter the PIN code on the mobile device. If it complains that no device is connected and the mobile device is indeed plugged in through the USB cable, you might need to do this first, although typically the pairing is automatically done when connecting the device:
|
||||
This should show many details on the connected iOS device. If you are connecting the device to your laptop for the first time, it will require to unlock and enter the PIN code on the mobile device. If it complains that no device is connected and the mobile device is indeed plugged in through the USB cable, you might need to do this first, although typically the pairing is automatically done when connecting the device:
|
||||
|
||||
```bash
|
||||
sudo usbmuxd -f -d
|
||||
sudo usbmuxd -f -v
|
||||
idevicepair pair
|
||||
```
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
203
mvt/android/artifacts/dumpsys_packages.py
Normal file
203
mvt/android/artifacts/dumpsys_packages.py
Normal file
@@ -0,0 +1,203 @@
|
||||
# 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 re
|
||||
from typing import Any, Dict, List, Union
|
||||
|
||||
from mvt.android.utils import ROOT_PACKAGES
|
||||
|
||||
from .artifact import AndroidArtifact
|
||||
|
||||
|
||||
class DumpsysPackagesArtifact(AndroidArtifact):
|
||||
def check_indicators(self) -> None:
|
||||
for result in self.results:
|
||||
if result["package_name"] in ROOT_PACKAGES:
|
||||
self.log.warning(
|
||||
"Found an installed package related to "
|
||||
'rooting/jailbreaking: "%s"',
|
||||
result["package_name"],
|
||||
)
|
||||
self.detected.append(result)
|
||||
continue
|
||||
|
||||
if not self.indicators:
|
||||
continue
|
||||
|
||||
ioc = self.indicators.check_app_id(result.get("package_name", ""))
|
||||
if ioc:
|
||||
result["matched_indicator"] = ioc
|
||||
self.detected.append(result)
|
||||
|
||||
def serialize(self, record: dict) -> Union[dict, list]:
|
||||
records = []
|
||||
|
||||
timestamps = [
|
||||
{"event": "package_install", "timestamp": record["timestamp"]},
|
||||
{
|
||||
"event": "package_first_install",
|
||||
"timestamp": record["first_install_time"],
|
||||
},
|
||||
{"event": "package_last_update", "timestamp": record["last_update_time"]},
|
||||
]
|
||||
|
||||
for timestamp in timestamps:
|
||||
records.append(
|
||||
{
|
||||
"timestamp": timestamp["timestamp"],
|
||||
"module": self.__class__.__name__,
|
||||
"event": timestamp["event"],
|
||||
"data": f"Install or update of package {record['package_name']}",
|
||||
}
|
||||
)
|
||||
|
||||
return records
|
||||
|
||||
@staticmethod
|
||||
def parse_dumpsys_package_for_details(output: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Parse one entry of a dumpsys package information
|
||||
"""
|
||||
details = {
|
||||
"uid": "",
|
||||
"version_name": "",
|
||||
"version_code": "",
|
||||
"timestamp": "",
|
||||
"first_install_time": "",
|
||||
"last_update_time": "",
|
||||
"permissions": [],
|
||||
"requested_permissions": [],
|
||||
}
|
||||
in_install_permissions = False
|
||||
in_runtime_permissions = False
|
||||
in_declared_permissions = False
|
||||
in_requested_permissions = True
|
||||
for line in output.splitlines():
|
||||
if in_install_permissions:
|
||||
if line.startswith(" " * 4) and not line.startswith(" " * 6):
|
||||
in_install_permissions = False
|
||||
else:
|
||||
lineinfo = line.strip().split(":")
|
||||
permission = lineinfo[0]
|
||||
granted = None
|
||||
if "granted=" in lineinfo[1]:
|
||||
granted = "granted=true" in lineinfo[1]
|
||||
|
||||
details["permissions"].append(
|
||||
{"name": permission, "granted": granted, "type": "install"}
|
||||
)
|
||||
if in_runtime_permissions:
|
||||
if not line.startswith(" " * 8):
|
||||
in_runtime_permissions = False
|
||||
else:
|
||||
lineinfo = line.strip().split(":")
|
||||
permission = lineinfo[0]
|
||||
granted = None
|
||||
if "granted=" in lineinfo[1]:
|
||||
granted = "granted=true" in lineinfo[1]
|
||||
|
||||
details["permissions"].append(
|
||||
{"name": permission, "granted": granted, "type": "runtime"}
|
||||
)
|
||||
if in_declared_permissions:
|
||||
if not line.startswith(" " * 6):
|
||||
in_declared_permissions = False
|
||||
else:
|
||||
permission = line.strip().split(":")[0]
|
||||
details["permissions"].append(
|
||||
{"name": permission, "type": "declared"}
|
||||
)
|
||||
if in_requested_permissions:
|
||||
if not line.startswith(" " * 6):
|
||||
in_requested_permissions = False
|
||||
else:
|
||||
details["requested_permissions"].append(line.strip())
|
||||
if line.strip().startswith("userId="):
|
||||
details["uid"] = line.split("=")[1].strip()
|
||||
elif line.strip().startswith("versionName="):
|
||||
details["version_name"] = line.split("=")[1].strip()
|
||||
elif line.strip().startswith("versionCode="):
|
||||
details["version_code"] = line.split("=", 1)[1].strip()
|
||||
elif line.strip().startswith("timeStamp="):
|
||||
details["timestamp"] = line.split("=")[1].strip()
|
||||
elif line.strip().startswith("firstInstallTime="):
|
||||
details["first_install_time"] = line.split("=")[1].strip()
|
||||
elif line.strip().startswith("lastUpdateTime="):
|
||||
details["last_update_time"] = line.split("=")[1].strip()
|
||||
elif line.strip() == "install permissions:":
|
||||
in_install_permissions = True
|
||||
elif line.strip() == "runtime permissions:":
|
||||
in_runtime_permissions = True
|
||||
elif line.strip() == "declared permissions:":
|
||||
in_declared_permissions = True
|
||||
elif line.strip() == "requested permissions:":
|
||||
in_requested_permissions = True
|
||||
|
||||
return details
|
||||
|
||||
def parse_dumpsys_packages(self, output: str) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Parse the dumpsys package service data
|
||||
"""
|
||||
pkg_rxp = re.compile(r" Package \[(.+?)\].*")
|
||||
|
||||
results = []
|
||||
package_name = None
|
||||
package = {}
|
||||
lines = []
|
||||
for line in output.splitlines():
|
||||
if line.startswith(" Package ["):
|
||||
if len(lines) > 0:
|
||||
details = self.parse_dumpsys_package_for_details("\n".join(lines))
|
||||
package.update(details)
|
||||
results.append(package)
|
||||
lines = []
|
||||
package = {}
|
||||
|
||||
matches = pkg_rxp.findall(line)
|
||||
if not matches:
|
||||
continue
|
||||
|
||||
package_name = matches[0]
|
||||
package["package_name"] = package_name
|
||||
continue
|
||||
|
||||
if not package_name:
|
||||
continue
|
||||
|
||||
lines.append(line)
|
||||
|
||||
if len(lines) > 0:
|
||||
details = self.parse_dumpsys_package_for_details("\n".join(lines))
|
||||
package.update(details)
|
||||
results.append(package)
|
||||
|
||||
return results
|
||||
|
||||
def parse(self, content: str):
|
||||
"""
|
||||
Parse the Dumpsys Package section for activities
|
||||
Adds results to self.results
|
||||
|
||||
:param content: content of the package section (string)
|
||||
"""
|
||||
self.results = []
|
||||
package = []
|
||||
|
||||
in_package_list = False
|
||||
for line in content.split("\n"):
|
||||
if line.startswith("Packages:"):
|
||||
in_package_list = True
|
||||
continue
|
||||
|
||||
if not in_package_list:
|
||||
continue
|
||||
|
||||
if line.strip() == "":
|
||||
break
|
||||
|
||||
package.append(line)
|
||||
|
||||
self.results = self.parse_dumpsys_packages("\n".join(package))
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -72,7 +72,7 @@ def version():
|
||||
is_flag=True,
|
||||
help="Extract all packages installed on the phone, including system packages",
|
||||
)
|
||||
@click.option("--virustotal", "-v", is_flag=True, help="Check packages on VirusTotal")
|
||||
@click.option("--virustotal", "-V", is_flag=True, help="Check packages on VirusTotal")
|
||||
@click.option(
|
||||
"--output",
|
||||
"-o",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,89 +1,28 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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 List, Optional, Union
|
||||
from typing import Optional, Union
|
||||
|
||||
from rich.console import Console
|
||||
from rich.progress import track
|
||||
from rich.table import Table
|
||||
from rich.text import Text
|
||||
|
||||
from mvt.android.parsers.dumpsys import parse_dumpsys_package_for_details
|
||||
from mvt.android.artifacts.dumpsys_packages import DumpsysPackagesArtifact
|
||||
from mvt.android.utils import (
|
||||
DANGEROUS_PERMISSIONS,
|
||||
DANGEROUS_PERMISSIONS_THRESHOLD,
|
||||
ROOT_PACKAGES,
|
||||
SECURITY_PACKAGES,
|
||||
SYSTEM_UPDATE_PACKAGES,
|
||||
)
|
||||
from mvt.common.virustotal import VTNoKey, VTQuotaExceeded, virustotal_lookup
|
||||
|
||||
from .base import AndroidExtraction
|
||||
|
||||
DANGEROUS_PERMISSIONS_THRESHOLD = 10
|
||||
DANGEROUS_PERMISSIONS = [
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.AUTHENTICATE_ACCOUNTS",
|
||||
"android.permission.CAMERA",
|
||||
"android.permission.DISABLE_KEYGUARD",
|
||||
"android.permission.PROCESS_OUTGOING_CALLS",
|
||||
"android.permission.READ_CALENDAR",
|
||||
"android.permission.READ_CALL_LOG",
|
||||
"android.permission.READ_CONTACTS",
|
||||
"android.permission.READ_PHONE_STATE",
|
||||
"android.permission.READ_SMS",
|
||||
"android.permission.RECEIVE_MMS",
|
||||
"android.permission.RECEIVE_SMS",
|
||||
"android.permission.RECEIVE_WAP_PUSH",
|
||||
"android.permission.RECORD_AUDIO",
|
||||
"android.permission.SEND_SMS",
|
||||
"android.permission.SYSTEM_ALERT_WINDOW",
|
||||
"android.permission.USE_CREDENTIALS",
|
||||
"android.permission.USE_SIP",
|
||||
"com.android.browser.permission.READ_HISTORY_BOOKMARKS",
|
||||
]
|
||||
ROOT_PACKAGES: List[str] = [
|
||||
"com.noshufou.android.su",
|
||||
"com.noshufou.android.su.elite",
|
||||
"eu.chainfire.supersu",
|
||||
"com.koushikdutta.superuser",
|
||||
"com.thirdparty.superuser",
|
||||
"com.yellowes.su",
|
||||
"com.koushikdutta.rommanager",
|
||||
"com.koushikdutta.rommanager.license",
|
||||
"com.dimonvideo.luckypatcher",
|
||||
"com.chelpus.lackypatch",
|
||||
"com.ramdroid.appquarantine",
|
||||
"com.ramdroid.appquarantinepro",
|
||||
"com.devadvance.rootcloak",
|
||||
"com.devadvance.rootcloakplus",
|
||||
"de.robv.android.xposed.installer",
|
||||
"com.saurik.substrate",
|
||||
"com.zachspong.temprootremovejb",
|
||||
"com.amphoras.hidemyroot",
|
||||
"com.amphoras.hidemyrootadfree",
|
||||
"com.formyhm.hiderootPremium",
|
||||
"com.formyhm.hideroot",
|
||||
"me.phh.superuser",
|
||||
"eu.chainfire.supersu.pro",
|
||||
"com.kingouser.com",
|
||||
"com.topjohnwu.magisk",
|
||||
]
|
||||
SECURITY_PACKAGES = [
|
||||
"com.policydm",
|
||||
"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",
|
||||
]
|
||||
|
||||
|
||||
class Packages(AndroidExtraction):
|
||||
"""This module extracts the list of installed packages."""
|
||||
@@ -105,6 +44,7 @@ class Packages(AndroidExtraction):
|
||||
log=log,
|
||||
results=results,
|
||||
)
|
||||
self._user_needed = False
|
||||
|
||||
def serialize(self, record: dict) -> Union[dict, list]:
|
||||
records = []
|
||||
@@ -233,10 +173,15 @@ class Packages(AndroidExtraction):
|
||||
if line.strip() == "Packages:":
|
||||
in_packages = True
|
||||
|
||||
return parse_dumpsys_package_for_details("\n".join(lines))
|
||||
return DumpsysPackagesArtifact.parse_dumpsys_package_for_details(
|
||||
"\n".join(lines)
|
||||
)
|
||||
|
||||
def _get_files_for_package(self, package_name: str) -> list:
|
||||
output = self._adb_command(f"pm path {package_name}")
|
||||
command = f"pm path {package_name}"
|
||||
if self._user_needed:
|
||||
command += " --user 0"
|
||||
output = self._adb_command(command)
|
||||
output = output.strip().replace("package:", "")
|
||||
if not output:
|
||||
return []
|
||||
@@ -270,6 +215,9 @@ class Packages(AndroidExtraction):
|
||||
self._adb_connect()
|
||||
|
||||
packages = self._adb_command("pm list packages -u -i -f")
|
||||
if "java.lang.SecurityException" in packages or packages.strip() == "":
|
||||
self._user_needed = True
|
||||
packages = self._adb_command("pm list packages -u -i -f --user 0")
|
||||
|
||||
for line in packages.splitlines():
|
||||
line = line.strip()
|
||||
@@ -310,7 +258,10 @@ class Packages(AndroidExtraction):
|
||||
{"field": "third_party", "arg": "-3"},
|
||||
]
|
||||
for cmd in cmds:
|
||||
output = self._adb_command(f"pm list packages {cmd['arg']}")
|
||||
command = f"pm list packages {cmd['arg']}"
|
||||
if self._user_needed:
|
||||
command += " --user 0"
|
||||
output = self._adb_command(command)
|
||||
for line in output.splitlines():
|
||||
line = line.strip()
|
||||
if not line.startswith("package:"):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -12,7 +12,7 @@ from .base import AndroidQFModule
|
||||
|
||||
|
||||
class DumpsysAccessibility(DumpsysAccessibilityArtifact, AndroidQFModule):
|
||||
"""This module analyse dumpsys accessbility"""
|
||||
"""This module analyses dumpsys accessibility"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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 Any, Dict, List, Optional, Union
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from mvt.android.artifacts.dumpsys_packages import DumpsysPackagesArtifact
|
||||
from mvt.android.modules.adb.packages import (
|
||||
DANGEROUS_PERMISSIONS,
|
||||
DANGEROUS_PERMISSIONS_THRESHOLD,
|
||||
ROOT_PACKAGES,
|
||||
)
|
||||
from mvt.android.parsers.dumpsys import parse_dumpsys_packages
|
||||
|
||||
from .base import AndroidQFModule
|
||||
|
||||
|
||||
class DumpsysPackages(AndroidQFModule):
|
||||
class DumpsysPackages(DumpsysPackagesArtifact, AndroidQFModule):
|
||||
"""This module analyse dumpsys packages"""
|
||||
|
||||
def __init__(
|
||||
@@ -37,70 +36,15 @@ class DumpsysPackages(AndroidQFModule):
|
||||
results=results,
|
||||
)
|
||||
|
||||
def serialize(self, record: dict) -> Union[dict, list]:
|
||||
entries = []
|
||||
for entry in ["timestamp", "first_install_time", "last_update_time"]:
|
||||
if entry in record:
|
||||
entries.append(
|
||||
{
|
||||
"timestamp": record[entry],
|
||||
"module": self.__class__.__name__,
|
||||
"event": entry,
|
||||
"data": f"Package {record['package_name']} "
|
||||
f"({record['uid']})",
|
||||
}
|
||||
)
|
||||
|
||||
return entries
|
||||
|
||||
def check_indicators(self) -> None:
|
||||
for result in self.results:
|
||||
if result["package_name"] in ROOT_PACKAGES:
|
||||
self.log.warning(
|
||||
"Found an installed package related to "
|
||||
'rooting/jailbreaking: "%s"',
|
||||
result["package_name"],
|
||||
)
|
||||
self.detected.append(result)
|
||||
continue
|
||||
|
||||
if not self.indicators:
|
||||
continue
|
||||
|
||||
ioc = self.indicators.check_app_id(result.get("package_name", ""))
|
||||
if ioc:
|
||||
result["matched_indicator"] = ioc
|
||||
self.detected.append(result)
|
||||
|
||||
def run(self) -> None:
|
||||
dumpsys_file = self._get_files_by_pattern("*/dumpsys.txt")
|
||||
if len(dumpsys_file) != 1:
|
||||
self.log.info("Dumpsys file not found")
|
||||
return
|
||||
|
||||
data = self._get_file_content(dumpsys_file[0])
|
||||
|
||||
package = []
|
||||
in_service = False
|
||||
in_package_list = False
|
||||
for line in data.decode("utf-8").split("\n"):
|
||||
if line.strip().startswith("DUMP OF SERVICE package:"):
|
||||
in_service = True
|
||||
continue
|
||||
|
||||
if in_service and line.startswith("Packages:"):
|
||||
in_package_list = True
|
||||
continue
|
||||
|
||||
if not in_service or not in_package_list:
|
||||
continue
|
||||
|
||||
if line.strip() == "":
|
||||
break
|
||||
|
||||
package.append(line)
|
||||
|
||||
self.results = parse_dumpsys_packages("\n".join(package))
|
||||
data = self._get_file_content(dumpsys_file[0]).decode("utf-8", errors="replace")
|
||||
content = self.extract_dumpsys_section(data, "DUMP OF SERVICE package:")
|
||||
self.parse(content)
|
||||
|
||||
for result in self.results:
|
||||
dangerous_permissions_count = 0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# Copyright (c) 2021-2023 The MVT Authors.
|
||||
# See the file 'LICENSE' for usage and copying permissions, or find a copy at
|
||||
# https://github.com/mvt-project/mvt/blob/main/LICENSE
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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, Union
|
||||
from typing import Optional
|
||||
|
||||
from mvt.android.modules.adb.packages import (
|
||||
DANGEROUS_PERMISSIONS,
|
||||
DANGEROUS_PERMISSIONS_THRESHOLD,
|
||||
ROOT_PACKAGES,
|
||||
)
|
||||
from mvt.android.parsers.dumpsys import parse_dumpsys_packages
|
||||
from mvt.android.artifacts.dumpsys_packages import DumpsysPackagesArtifact
|
||||
from mvt.android.utils import DANGEROUS_PERMISSIONS, DANGEROUS_PERMISSIONS_THRESHOLD
|
||||
|
||||
from .base import BugReportModule
|
||||
|
||||
|
||||
class Packages(BugReportModule):
|
||||
class Packages(DumpsysPackagesArtifact, BugReportModule):
|
||||
"""This module extracts details on receivers for risky activities."""
|
||||
|
||||
def __init__(
|
||||
@@ -37,83 +33,18 @@ class Packages(BugReportModule):
|
||||
results=results,
|
||||
)
|
||||
|
||||
def serialize(self, record: dict) -> Union[dict, list]:
|
||||
records = []
|
||||
|
||||
timestamps = [
|
||||
{"event": "package_install", "timestamp": record["timestamp"]},
|
||||
{
|
||||
"event": "package_first_install",
|
||||
"timestamp": record["first_install_time"],
|
||||
},
|
||||
{"event": "package_last_update", "timestamp": record["last_update_time"]},
|
||||
]
|
||||
|
||||
for timestamp in timestamps:
|
||||
records.append(
|
||||
{
|
||||
"timestamp": timestamp["timestamp"],
|
||||
"module": self.__class__.__name__,
|
||||
"event": timestamp["event"],
|
||||
"data": f"Install or update of package {record['package_name']}",
|
||||
}
|
||||
)
|
||||
|
||||
return records
|
||||
|
||||
def check_indicators(self) -> None:
|
||||
for result in self.results:
|
||||
if result["package_name"] in ROOT_PACKAGES:
|
||||
self.log.warning(
|
||||
"Found an installed package related to "
|
||||
'rooting/jailbreaking: "%s"',
|
||||
result["package_name"],
|
||||
)
|
||||
self.detected.append(result)
|
||||
continue
|
||||
|
||||
if not self.indicators:
|
||||
continue
|
||||
|
||||
ioc = self.indicators.check_app_id(result.get("package_name"))
|
||||
if ioc:
|
||||
result["matched_indicator"] = ioc
|
||||
self.detected.append(result)
|
||||
continue
|
||||
|
||||
def run(self) -> None:
|
||||
content = self._get_dumpstate_file()
|
||||
if not content:
|
||||
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
|
||||
|
||||
in_package = False
|
||||
in_packages_list = False
|
||||
lines = []
|
||||
for line in content.decode(errors="ignore").splitlines():
|
||||
if line.strip() == "DUMP OF SERVICE package:":
|
||||
in_package = True
|
||||
continue
|
||||
|
||||
if not in_package:
|
||||
continue
|
||||
|
||||
if line.strip() == "Packages:":
|
||||
in_packages_list = True
|
||||
continue
|
||||
|
||||
if not in_packages_list:
|
||||
continue
|
||||
|
||||
if line.strip() == "":
|
||||
break
|
||||
|
||||
lines.append(line)
|
||||
|
||||
self.results = parse_dumpsys_packages("\n".join(lines))
|
||||
data = data.decode("utf-8", errors="replace")
|
||||
content = self.extract_dumpsys_section(data, "DUMP OF SERVICE package:")
|
||||
self.parse(content)
|
||||
|
||||
for result in self.results:
|
||||
dangerous_permissions_count = 0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 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 re
|
||||
from typing import Any, Dict, List
|
||||
|
||||
|
||||
def parse_dumpsys_package_for_details(output: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Parse one entry of a dumpsys package information
|
||||
"""
|
||||
details = {
|
||||
"uid": "",
|
||||
"version_name": "",
|
||||
"version_code": "",
|
||||
"timestamp": "",
|
||||
"first_install_time": "",
|
||||
"last_update_time": "",
|
||||
"permissions": [],
|
||||
"requested_permissions": [],
|
||||
}
|
||||
|
||||
in_install_permissions = False
|
||||
in_runtime_permissions = False
|
||||
in_declared_permissions = False
|
||||
in_requested_permissions = True
|
||||
for line in output.splitlines():
|
||||
if in_install_permissions:
|
||||
if line.startswith(" " * 4) and not line.startswith(" " * 6):
|
||||
in_install_permissions = False
|
||||
else:
|
||||
lineinfo = line.strip().split(":")
|
||||
permission = lineinfo[0]
|
||||
granted = None
|
||||
if "granted=" in lineinfo[1]:
|
||||
granted = "granted=true" in lineinfo[1]
|
||||
|
||||
details["permissions"].append(
|
||||
{"name": permission, "granted": granted, "type": "install"}
|
||||
)
|
||||
|
||||
if in_runtime_permissions:
|
||||
if not line.startswith(" " * 8):
|
||||
in_runtime_permissions = False
|
||||
else:
|
||||
lineinfo = line.strip().split(":")
|
||||
permission = lineinfo[0]
|
||||
granted = None
|
||||
if "granted=" in lineinfo[1]:
|
||||
granted = "granted=true" in lineinfo[1]
|
||||
|
||||
details["permissions"].append(
|
||||
{"name": permission, "granted": granted, "type": "runtime"}
|
||||
)
|
||||
|
||||
if in_declared_permissions:
|
||||
if not line.startswith(" " * 6):
|
||||
in_declared_permissions = False
|
||||
else:
|
||||
permission = line.strip().split(":")[0]
|
||||
details["permissions"].append({"name": permission, "type": "declared"})
|
||||
if in_requested_permissions:
|
||||
if not line.startswith(" " * 6):
|
||||
in_requested_permissions = False
|
||||
else:
|
||||
details["requested_permissions"].append(line.strip())
|
||||
|
||||
if line.strip().startswith("userId="):
|
||||
details["uid"] = line.split("=")[1].strip()
|
||||
elif line.strip().startswith("versionName="):
|
||||
details["version_name"] = line.split("=")[1].strip()
|
||||
elif line.strip().startswith("versionCode="):
|
||||
details["version_code"] = line.split("=", 1)[1].strip()
|
||||
elif line.strip().startswith("timeStamp="):
|
||||
details["timestamp"] = line.split("=")[1].strip()
|
||||
elif line.strip().startswith("firstInstallTime="):
|
||||
details["first_install_time"] = line.split("=")[1].strip()
|
||||
elif line.strip().startswith("lastUpdateTime="):
|
||||
details["last_update_time"] = line.split("=")[1].strip()
|
||||
elif line.strip() == "install permissions:":
|
||||
in_install_permissions = True
|
||||
elif line.strip() == "runtime permissions:":
|
||||
in_runtime_permissions = True
|
||||
elif line.strip() == "declared permissions:":
|
||||
in_declared_permissions = True
|
||||
elif line.strip() == "requested permissions:":
|
||||
in_requested_permissions = True
|
||||
|
||||
return details
|
||||
|
||||
|
||||
def parse_dumpsys_packages(output: str) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Parse the dumpsys package service data
|
||||
"""
|
||||
pkg_rxp = re.compile(r" Package \[(.+?)\].*")
|
||||
|
||||
results = []
|
||||
package_name = None
|
||||
package = {}
|
||||
lines = []
|
||||
for line in output.splitlines():
|
||||
if line.startswith(" Package ["):
|
||||
if len(lines) > 0:
|
||||
details = parse_dumpsys_package_for_details("\n".join(lines))
|
||||
package.update(details)
|
||||
results.append(package)
|
||||
lines = []
|
||||
package = {}
|
||||
|
||||
matches = pkg_rxp.findall(line)
|
||||
if not matches:
|
||||
continue
|
||||
|
||||
package_name = matches[0]
|
||||
package["package_name"] = package_name
|
||||
continue
|
||||
|
||||
if not package_name:
|
||||
continue
|
||||
|
||||
lines.append(line)
|
||||
|
||||
if len(lines) > 0:
|
||||
details = parse_dumpsys_package_for_details("\n".join(lines))
|
||||
package.update(details)
|
||||
results.append(package)
|
||||
|
||||
return results
|
||||
@@ -1,8 +1,9 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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 datetime import datetime, timedelta
|
||||
from typing import List
|
||||
|
||||
|
||||
def warn_android_patch_level(patch_level: str, log) -> bool:
|
||||
@@ -17,3 +18,76 @@ def warn_android_patch_level(patch_level: str, log) -> bool:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
ROOT_PACKAGES: List[str] = [
|
||||
"com.noshufou.android.su",
|
||||
"com.noshufou.android.su.elite",
|
||||
"eu.chainfire.supersu",
|
||||
"com.koushikdutta.superuser",
|
||||
"com.thirdparty.superuser",
|
||||
"com.yellowes.su",
|
||||
"com.koushikdutta.rommanager",
|
||||
"com.koushikdutta.rommanager.license",
|
||||
"com.dimonvideo.luckypatcher",
|
||||
"com.chelpus.lackypatch",
|
||||
"com.ramdroid.appquarantine",
|
||||
"com.ramdroid.appquarantinepro",
|
||||
"com.devadvance.rootcloak",
|
||||
"com.devadvance.rootcloakplus",
|
||||
"de.robv.android.xposed.installer",
|
||||
"com.saurik.substrate",
|
||||
"com.zachspong.temprootremovejb",
|
||||
"com.amphoras.hidemyroot",
|
||||
"com.amphoras.hidemyrootadfree",
|
||||
"com.formyhm.hiderootPremium",
|
||||
"com.formyhm.hideroot",
|
||||
"me.phh.superuser",
|
||||
"eu.chainfire.supersu.pro",
|
||||
"com.kingouser.com",
|
||||
"com.topjohnwu.magisk",
|
||||
]
|
||||
|
||||
DANGEROUS_PERMISSIONS_THRESHOLD = 10
|
||||
|
||||
DANGEROUS_PERMISSIONS = [
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.AUTHENTICATE_ACCOUNTS",
|
||||
"android.permission.CAMERA",
|
||||
"android.permission.DISABLE_KEYGUARD",
|
||||
"android.permission.PROCESS_OUTGOING_CALLS",
|
||||
"android.permission.READ_CALENDAR",
|
||||
"android.permission.READ_CALL_LOG",
|
||||
"android.permission.READ_CONTACTS",
|
||||
"android.permission.READ_PHONE_STATE",
|
||||
"android.permission.READ_SMS",
|
||||
"android.permission.RECEIVE_MMS",
|
||||
"android.permission.RECEIVE_SMS",
|
||||
"android.permission.RECEIVE_WAP_PUSH",
|
||||
"android.permission.RECORD_AUDIO",
|
||||
"android.permission.SEND_SMS",
|
||||
"android.permission.SYSTEM_ALERT_WINDOW",
|
||||
"android.permission.USE_CREDENTIALS",
|
||||
"android.permission.USE_SIP",
|
||||
"com.android.browser.permission.READ_HISTORY_BOOKMARKS",
|
||||
]
|
||||
|
||||
SECURITY_PACKAGES = [
|
||||
"com.policydm",
|
||||
"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",
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -53,7 +53,7 @@ class CmdCheckIOCS(Command):
|
||||
if self.module_name and iocs_module.__name__ != self.module_name:
|
||||
continue
|
||||
|
||||
if iocs_module().get_slug() != name_only:
|
||||
if iocs_module.get_slug() != name_only:
|
||||
continue
|
||||
|
||||
log.info(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -160,6 +160,27 @@ class Command:
|
||||
def finish(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def _show_disable_adb_warning(self) -> None:
|
||||
"""Warn if ADB is enabled"""
|
||||
if type(self).__name__ in ["CmdAndroidCheckADB", "CmdAndroidCheckAndroidQF"]:
|
||||
self.log.info(
|
||||
"Please disable Developer Options and ADB (Android Debug Bridge) on the device once finished with the acquisition. "
|
||||
"ADB is a powerful tool which can allow unauthorized access to the device."
|
||||
)
|
||||
|
||||
def _show_support_message(self) -> None:
|
||||
support_message = "Please seek reputable expert help if you have serious concerns about a possible spyware attack. Such support is available to human rights defenders and civil society through Amnesty International's Security Lab at https://securitylab.amnesty.org/get-help/?c=mvt"
|
||||
if self.detected_count == 0:
|
||||
self.log.info(
|
||||
f"[bold]NOTE:[/bold] Using MVT with public indicators of compromise (IOCs) [bold]WILL NOT[/bold] automatically detect advanced attacks.\n\n{support_message}",
|
||||
extra={"markup": True},
|
||||
)
|
||||
else:
|
||||
self.log.warning(
|
||||
f"[bold]NOTE: Detected indicators of compromise[/bold]. Only expert review can confirm if the detected indicators are signs of an attack.\n\n{support_message}",
|
||||
extra={"markup": True},
|
||||
)
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
self.init()
|
||||
@@ -208,3 +229,6 @@ class Command:
|
||||
|
||||
self._store_timeline()
|
||||
self._store_info()
|
||||
|
||||
self._show_disable_adb_warning()
|
||||
self._show_support_message()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -10,7 +10,7 @@ from .version import MVT_VERSION
|
||||
|
||||
|
||||
def check_updates() -> None:
|
||||
# First we check for MVT version udpates.
|
||||
# First we check for MVT version updates.
|
||||
mvt_updates = MVTUpdates()
|
||||
try:
|
||||
latest_version = mvt_updates.check()
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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 csv
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
import simplejson as json
|
||||
|
||||
from .utils import exec_or_profile
|
||||
from .utils import CustomJSONEncoder, exec_or_profile
|
||||
|
||||
|
||||
class DatabaseNotFoundError(Exception):
|
||||
@@ -75,12 +74,13 @@ class MVTModule:
|
||||
log.info('Loaded %d results from "%s"', len(results), json_path)
|
||||
return cls(results=results, log=log)
|
||||
|
||||
def get_slug(self) -> str:
|
||||
@classmethod
|
||||
def get_slug(cls) -> str:
|
||||
"""Use the module's class name to retrieve a slug"""
|
||||
if self.slug:
|
||||
return self.slug
|
||||
if cls.slug:
|
||||
return cls.slug
|
||||
|
||||
sub = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", self.__class__.__name__)
|
||||
sub = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", cls.__name__)
|
||||
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", sub).lower()
|
||||
|
||||
def check_indicators(self) -> None:
|
||||
@@ -103,7 +103,7 @@ class MVTModule:
|
||||
results_json_path = os.path.join(self.results_path, results_file_name)
|
||||
with open(results_json_path, "w", encoding="utf-8") as handle:
|
||||
try:
|
||||
json.dump(self.results, handle, indent=4, default=str)
|
||||
json.dump(self.results, handle, indent=4, cls=CustomJSONEncoder)
|
||||
except Exception as exc:
|
||||
self.log.error(
|
||||
"Unable to store results of module %s to file %s: %s",
|
||||
@@ -116,7 +116,7 @@ class MVTModule:
|
||||
detected_file_name = f"{name}_detected.json"
|
||||
detected_json_path = os.path.join(self.results_path, detected_file_name)
|
||||
with open(detected_json_path, "w", encoding="utf-8") as handle:
|
||||
json.dump(self.detected, handle, indent=4, default=str)
|
||||
json.dump(self.detected, handle, indent=4, cls=CustomJSONEncoder)
|
||||
|
||||
def serialize(self, record: dict) -> Union[dict, list, None]:
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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/
|
||||
|
||||
@@ -9,47 +9,65 @@ import requests
|
||||
from tld import get_tld
|
||||
|
||||
SHORTENER_DOMAINS = [
|
||||
"0rz.tw",
|
||||
"1drv.ms",
|
||||
"1link.in",
|
||||
"1url.com",
|
||||
"2big.at",
|
||||
"2.gp",
|
||||
"2pl.us",
|
||||
"2tu.us",
|
||||
"2ya.com",
|
||||
"3.ly",
|
||||
"4sq.com",
|
||||
"4url.cc",
|
||||
"6url.com",
|
||||
"a.gg",
|
||||
"a.nf",
|
||||
"7.ly",
|
||||
"a2a.me",
|
||||
"abbrr.com",
|
||||
"adf.ly",
|
||||
"adjix.com",
|
||||
"a.gg",
|
||||
"alturl.com",
|
||||
"a.nf",
|
||||
"anon.to",
|
||||
"apple.news",
|
||||
"atu.ca",
|
||||
"b23.ru",
|
||||
"bacn.me",
|
||||
"bc.vc",
|
||||
"bfy.tw",
|
||||
"binged.it",
|
||||
"bit.do",
|
||||
"bit.ly",
|
||||
"bizj.us",
|
||||
"bkite.com",
|
||||
"bloat.me",
|
||||
"budurl.com",
|
||||
"buff.ly",
|
||||
"buk.me",
|
||||
"burnurl.com",
|
||||
"c-o.in",
|
||||
"chilp.it",
|
||||
"chn.ge",
|
||||
"clck.ru",
|
||||
"cli.gs",
|
||||
"clickmeter.com",
|
||||
"cli.gs",
|
||||
"c-o.in",
|
||||
"cort.as",
|
||||
"cut.ly",
|
||||
"cutt.ly",
|
||||
"cuturl.com",
|
||||
"decenturl.com",
|
||||
"dai.ly",
|
||||
"dailym.ai",
|
||||
"db.tt",
|
||||
"decenturl.com",
|
||||
"dfl8.me",
|
||||
"digbig.com",
|
||||
"digg.com",
|
||||
"disq.us",
|
||||
"dlvr.it",
|
||||
"doiop.com",
|
||||
"do.my",
|
||||
"dwarfurl.com",
|
||||
"dy.fi",
|
||||
"easyuri.com",
|
||||
@@ -58,27 +76,35 @@ SHORTENER_DOMAINS = [
|
||||
"esyurl.com",
|
||||
"ewerl.com",
|
||||
"fa.b",
|
||||
"ff.im",
|
||||
"fa.by",
|
||||
"fb.me",
|
||||
"fff.to",
|
||||
"ff.im",
|
||||
"fhurl.com",
|
||||
"fire.to",
|
||||
"firsturl.de",
|
||||
"firsturl.net",
|
||||
"flic.kr",
|
||||
"flq.us",
|
||||
"fly2.ws",
|
||||
"fon.gs",
|
||||
"forms.gle",
|
||||
"fwd4.me",
|
||||
"gdurl.com",
|
||||
"gg.gg",
|
||||
"gl.am",
|
||||
"go.9nl.com",
|
||||
"go2.me",
|
||||
"go2cut.com",
|
||||
"go2.me",
|
||||
"go.9nl.com",
|
||||
"goo.gl",
|
||||
"goshrink.com",
|
||||
"got.by",
|
||||
"gowat.ch",
|
||||
"gri.ms",
|
||||
"gurl.es",
|
||||
"hellotxt.com",
|
||||
"hex.io",
|
||||
"hongkiat.shorturl.com",
|
||||
"hover.com",
|
||||
"href.in",
|
||||
"ht.ly",
|
||||
@@ -87,13 +113,15 @@ SHORTENER_DOMAINS = [
|
||||
"hurl.it",
|
||||
"hurl.me",
|
||||
"hurl.ws",
|
||||
"ibb.co",
|
||||
"icanhaz.com",
|
||||
"idek.net",
|
||||
"inreply.to",
|
||||
"is.gd",
|
||||
"iscool.net",
|
||||
"is.gd",
|
||||
"iterasi.net",
|
||||
"jijr.com",
|
||||
"j.mp",
|
||||
"jmp2.net",
|
||||
"just.as",
|
||||
"kissa.be",
|
||||
@@ -101,21 +129,23 @@ SHORTENER_DOMAINS = [
|
||||
"klck.me",
|
||||
"korta.nu",
|
||||
"krunchd.com",
|
||||
"lat.ms",
|
||||
"liip.to",
|
||||
"liltext.com",
|
||||
"lin.cr",
|
||||
"linkbee.com",
|
||||
"linkbun.ch",
|
||||
"liurl.cn",
|
||||
"ln-s.net",
|
||||
"ln-s.ru",
|
||||
"lnkd.in",
|
||||
"lnk.gd",
|
||||
"lnk.in",
|
||||
"lnkd.in",
|
||||
"ln-s.net",
|
||||
"ln-s.ru",
|
||||
"loopt.us",
|
||||
"lru.jp",
|
||||
"lt.tl",
|
||||
"lurl.no",
|
||||
"lyhyt.eu",
|
||||
"metamark.net",
|
||||
"migre.me",
|
||||
"minilien.com",
|
||||
@@ -123,52 +153,71 @@ SHORTENER_DOMAINS = [
|
||||
"minurl.fr",
|
||||
"moourl.com",
|
||||
"myurl.in",
|
||||
"nbcnews.to",
|
||||
"ne1.net",
|
||||
"njx.me",
|
||||
"nn.nf",
|
||||
"notlong.com",
|
||||
"n.pr",
|
||||
"nsfw.in",
|
||||
"o-x.fr",
|
||||
"nyti.ms",
|
||||
"om.ly",
|
||||
"onforb.es",
|
||||
"on.mktw.net",
|
||||
"ow.ly",
|
||||
"o-x.fr",
|
||||
"pca.st",
|
||||
"pd.am",
|
||||
"pic.gd",
|
||||
"ping.fm",
|
||||
"piurl.com",
|
||||
"pnt.me",
|
||||
"politi.co",
|
||||
"poprl.com",
|
||||
"post.ly",
|
||||
"posted.at",
|
||||
"post.ly",
|
||||
"profile.to",
|
||||
"q.gs",
|
||||
"qicute.com",
|
||||
"qlnk.net",
|
||||
"qr.ae",
|
||||
"qte.me",
|
||||
"quip-art.com",
|
||||
"rb6.me",
|
||||
"rb.gy",
|
||||
"read.bi",
|
||||
"redir.ec",
|
||||
"redirx.com",
|
||||
"ri.ms",
|
||||
"redr.me",
|
||||
"reut.rs",
|
||||
"rickroll.it",
|
||||
"r.im",
|
||||
"ri.ms",
|
||||
"riz.gd",
|
||||
"rsmonkey.com",
|
||||
"ru.ly",
|
||||
"rubyurl.com",
|
||||
"ru.ly",
|
||||
"s7y.us",
|
||||
"safe.mn",
|
||||
"sharein.com",
|
||||
"sharetabs.com",
|
||||
"shorl.com",
|
||||
"short.ie",
|
||||
"short.to",
|
||||
"shortlinks.co.uk",
|
||||
"shortna.me",
|
||||
"short.to",
|
||||
"shorturl.at",
|
||||
"shorturl.com",
|
||||
"shoturl.us",
|
||||
"shout.to",
|
||||
"shrinkify.com",
|
||||
"shrinkster.com",
|
||||
"shrt.st",
|
||||
"shrten.com",
|
||||
"shrt.st",
|
||||
"shrunkin.com",
|
||||
"shw.me",
|
||||
"simurl.com",
|
||||
"smsh.me",
|
||||
"sn.im",
|
||||
"snipr.com",
|
||||
"snipurl.com",
|
||||
@@ -179,24 +228,30 @@ SHORTENER_DOMAINS = [
|
||||
"starturl.com",
|
||||
"sturly.com",
|
||||
"su.pr",
|
||||
"t.cn",
|
||||
"t.co",
|
||||
"tcrn.ch",
|
||||
"tgr.ph",
|
||||
"thrdl.es",
|
||||
"tighturl.com",
|
||||
"tiny.cc",
|
||||
"tiny.pl",
|
||||
"tiny123.com",
|
||||
"tinyarro.ws",
|
||||
"tiny.cc",
|
||||
"tinylink.in",
|
||||
"tiny.pl",
|
||||
"tiny.tw",
|
||||
"tinytw.it",
|
||||
"tinyuri.ca",
|
||||
"tinyurl.com",
|
||||
"tinyvid.io",
|
||||
"t.me",
|
||||
"tnij.org",
|
||||
"to.ly",
|
||||
"tnw.to",
|
||||
"togoto.us",
|
||||
"to.ly",
|
||||
"traceurl.com",
|
||||
"tr.im",
|
||||
"tr.my",
|
||||
"traceurl.com",
|
||||
"turo.us",
|
||||
"tweetburner.com",
|
||||
"twirl.at",
|
||||
@@ -206,49 +261,62 @@ SHORTENER_DOMAINS = [
|
||||
"twiturl.de",
|
||||
"twurl.cc",
|
||||
"twurl.nl",
|
||||
"u.mavrev.com",
|
||||
"u.nu",
|
||||
"u6e.de",
|
||||
"ub0.cc",
|
||||
"ukl.me.uk",
|
||||
"u.mavrev.com",
|
||||
"u.nu",
|
||||
"updating.me",
|
||||
"ur1.ca",
|
||||
"url.co.uk",
|
||||
"url.ie",
|
||||
"url4.eu",
|
||||
"urlao.com",
|
||||
"urlbrief.com",
|
||||
"url.co.uk",
|
||||
"urlcover.com",
|
||||
"urlcut.com",
|
||||
"urlenco.de",
|
||||
"urlhawk.com",
|
||||
"url.ie",
|
||||
"urlkiss.com",
|
||||
"urlot.com",
|
||||
"urlpire.com",
|
||||
"urlx.ie",
|
||||
"urlx.org",
|
||||
"urlzen.com",
|
||||
"use.my",
|
||||
"u.to",
|
||||
"v.gd",
|
||||
"virl.com",
|
||||
"vl.am",
|
||||
"vurl.com",
|
||||
"vzturl.com",
|
||||
"w3t.org",
|
||||
"wapo.st",
|
||||
"wapurl.co.uk",
|
||||
"wipi.es",
|
||||
"wp.me",
|
||||
"x.co",
|
||||
"x.se",
|
||||
"xaddr.com",
|
||||
"x.co",
|
||||
"xeeurl.com",
|
||||
"xr.com",
|
||||
"xrl.in",
|
||||
"xrl.us",
|
||||
"x.se",
|
||||
"xurl.es",
|
||||
"xurl.jp",
|
||||
"xzb.cc",
|
||||
"ye.pe",
|
||||
"yep.it",
|
||||
"yfrog.com",
|
||||
"yhoo.it",
|
||||
"ymlp.com",
|
||||
"yuarel.com",
|
||||
"yweb.com",
|
||||
"zi.ma",
|
||||
"zi.pe",
|
||||
"zipmyurl.com",
|
||||
"zurl.to",
|
||||
"zurl.ws",
|
||||
"zz.gd",
|
||||
]
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 Claudio Guarnieri.
|
||||
# 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 cProfile
|
||||
import datetime
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
@@ -14,6 +15,28 @@ from typing import Any, Iterator, Union
|
||||
from rich.logging import RichHandler
|
||||
|
||||
|
||||
class CustomJSONEncoder(json.JSONEncoder):
|
||||
"""
|
||||
Custom JSON encoder to handle non-standard types.
|
||||
|
||||
Some modules are storing non-UTF-8 bytes in their results dictionaries.
|
||||
This causes exceptions when the results are being encoded as JSON.
|
||||
|
||||
Of course this means that when MVT is run via `check-iocs` with existing
|
||||
results, the encoded version will be loaded back into the dictionary.
|
||||
Modules should ensure they encode anything that needs to be compared
|
||||
against an indicator in a JSON-friendly type.
|
||||
"""
|
||||
|
||||
def default(self, o):
|
||||
if isinstance(o, bytes):
|
||||
# Decode as utf-8, replace any invalid UTF-8 bytes with escaped hex
|
||||
return o.decode("utf-8", errors="backslashreplace")
|
||||
|
||||
# For all other types try to use the string representation.
|
||||
return str(o)
|
||||
|
||||
|
||||
def convert_chrometime_to_datetime(timestamp: int) -> datetime.datetime:
|
||||
"""Converts Chrome timestamp to a datetime.
|
||||
|
||||
@@ -30,20 +53,20 @@ def convert_chrometime_to_datetime(timestamp: int) -> datetime.datetime:
|
||||
def convert_datetime_to_iso(date_time: datetime.datetime) -> str:
|
||||
"""Converts datetime to ISO string.
|
||||
|
||||
:param datetime: datetime.
|
||||
:param datetime: datetime, naive or timezone aware
|
||||
:type datetime: datetime.datetime
|
||||
:returns: ISO datetime string in YYYY-mm-dd HH:MM:SS.ms format.
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
try:
|
||||
return date_time.strftime("%Y-%m-%d %H:%M:%S.%f")
|
||||
except Exception:
|
||||
return ""
|
||||
if date_time.tzinfo:
|
||||
# Timezone aware object - convert to UTC
|
||||
date_time = date_time.astimezone(tz=datetime.timezone.utc)
|
||||
return date_time.strftime("%Y-%m-%d %H:%M:%S.%f")
|
||||
|
||||
|
||||
def convert_unix_to_utc_datetime(
|
||||
timestamp: Union[int, float, str]
|
||||
timestamp: Union[int, float, str],
|
||||
) -> datetime.datetime:
|
||||
"""Converts a unix epoch timestamp to UTC datetime.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user