mirror of
https://github.com/mvt-project/mvt
synced 2025-10-21 22:42:15 +02:00
Compare commits
99 Commits
v2.5.0
...
feature/io
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b12eaa4007 | ||
|
|
a3a7789547 | ||
|
|
d3fcc686ff | ||
|
|
4bcc0e5f27 | ||
|
|
22fce280af | ||
|
|
4739d8853e | ||
|
|
ace01ff7fb | ||
|
|
7e4f0aec4d | ||
|
|
57647583cc | ||
|
|
cd99b293ed | ||
|
|
5fe8238ef0 | ||
|
|
1d44ae3987 | ||
|
|
bb68e41c07 | ||
|
|
787b0c1f48 | ||
|
|
83c1bbf714 | ||
|
|
17b625f311 | ||
|
|
7772d2de72 | ||
|
|
37705d11fa | ||
|
|
319bc7e9cd | ||
|
|
62cdfa1b59 | ||
|
|
cbb78b7ade | ||
|
|
4598293c82 | ||
|
|
6e0cd23bbc | ||
|
|
d6f3561995 | ||
|
|
19b3b97571 | ||
|
|
2c72d80e7c | ||
|
|
720aeff6e9 | ||
|
|
863de4f543 | ||
|
|
3afe218c7c | ||
|
|
665806db98 | ||
|
|
a03f4e55ff | ||
|
|
81b647beac | ||
|
|
5ef19a327c | ||
|
|
f4bf3f362b | ||
|
|
7575315966 | ||
|
|
9678eb17e5 | ||
|
|
7303bc06e5 | ||
|
|
477f9a7f6b | ||
|
|
aced1aa74d | ||
|
|
052c4e207b | ||
|
|
821943a859 | ||
|
|
f4437b30b1 | ||
|
|
d4946b04bf | ||
|
|
a15d9f721d | ||
|
|
10e7599c6e | ||
|
|
a44688c501 | ||
|
|
c66a38e5c0 | ||
|
|
ee2fab8d87 | ||
|
|
f8e2b0921a | ||
|
|
5225600396 | ||
|
|
2c4c92f510 | ||
|
|
656feb1da7 | ||
|
|
79dd5b8bad | ||
|
|
f79938b082 | ||
|
|
822536a1cb | ||
|
|
69fb8c236f | ||
|
|
5dfa0153ee | ||
|
|
d79f6cbd7d | ||
|
|
617c5d9e1c | ||
|
|
ae9f874e1b | ||
|
|
b58351bfbd | ||
|
|
287a11a2ee | ||
|
|
efe46d7b49 | ||
|
|
102dd31bd6 | ||
|
|
e00895aa9d | ||
|
|
79dbf999a9 | ||
|
|
89d31f3212 | ||
|
|
caeeec2816 | ||
|
|
9e19abb5d3 | ||
|
|
cf5cf3b85d | ||
|
|
f0dbe0bfa6 | ||
|
|
555e49fda7 | ||
|
|
a6d32e1c88 | ||
|
|
f155146f1e | ||
|
|
9d47acc228 | ||
|
|
cbd41b2aff | ||
|
|
0509eaa162 | ||
|
|
59e6dff1e1 | ||
|
|
f1821d1a02 | ||
|
|
6c7ad0ac95 | ||
|
|
3a997d30d2 | ||
|
|
6f56939dd7 | ||
|
|
7a4946e2c6 | ||
|
|
e1c4f4eb7a | ||
|
|
f9d7b550dc | ||
|
|
b738603911 | ||
|
|
5826e6b11c | ||
|
|
54c5d549af | ||
|
|
dded863e58 | ||
|
|
fc7ea5383e | ||
|
|
04b78a4d60 | ||
|
|
4ea53d707b | ||
|
|
da743a2878 | ||
|
|
4681b57adc | ||
|
|
bb7a22ed0b | ||
|
|
b2df17b4a0 | ||
|
|
278611a753 | ||
|
|
cd4d468553 | ||
|
|
1182587094 |
11
.github/workflows/black.yml
vendored
11
.github/workflows/black.yml
vendored
@@ -1,11 +0,0 @@
|
||||
name: Black
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
black:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: psf/black@stable
|
||||
with:
|
||||
options: "--check"
|
||||
23
.github/workflows/mypy.yml
vendored
Normal file
23
.github/workflows/mypy.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Mypy
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
mypy_py3:
|
||||
name: Mypy check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.9
|
||||
cache: 'pip'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
pip install mypy
|
||||
- name: mypy
|
||||
run: |
|
||||
make mypy
|
||||
61
.github/workflows/publish-release-docker.yml
vendored
Normal file
61
.github/workflows/publish-release-docker.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
#
|
||||
name: Create and publish a Docker image
|
||||
|
||||
# Configures this workflow to run every time a release is published.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
runs-on: ubuntu-latest
|
||||
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
#
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
|
||||
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
|
||||
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v1
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
|
||||
50
.github/workflows/python-package.yml
vendored
50
.github/workflows/python-package.yml
vendored
@@ -1,50 +0,0 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.8', '3.9', '3.10'] # , '3.11']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade setuptools
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install flake8 pytest safety stix2 pytest-mock pytest-cov
|
||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||
python -m pip install .
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
- 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
|
||||
- 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
|
||||
12
.github/workflows/ruff.yml
vendored
12
.github/workflows/ruff.yml
vendored
@@ -4,16 +4,24 @@ on:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
ruff_py3:
|
||||
name: Ruff syntax check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.9
|
||||
cache: 'pip'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
pip install --user ruff
|
||||
pip install ruff
|
||||
- name: ruff
|
||||
run: |
|
||||
ruff check --output-format github .
|
||||
make ruff
|
||||
|
||||
@@ -54,7 +54,7 @@ def parse_latest_ios_versions(rss_feed_text):
|
||||
|
||||
|
||||
def update_mvt(mvt_checkout_path, latest_ios_versions):
|
||||
version_path = os.path.join(mvt_checkout_path, "mvt/ios/data/ios_versions.json")
|
||||
version_path = os.path.join(mvt_checkout_path, "src/mvt/ios/data/ios_versions.json")
|
||||
with open(version_path, "r") as version_file:
|
||||
current_versions = json.load(version_file)
|
||||
|
||||
|
||||
38
.github/workflows/tests.yml
vendored
Normal file
38
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Tests
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Run Python Tests
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ['3.8', '3.9', '3.10'] # , '3.11']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
make install
|
||||
make test-requirements
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
set -o pipefail
|
||||
make test-ci | 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
|
||||
11
.safety-policy.yml
Normal file
11
.safety-policy.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
# Safety Security and License Configuration file
|
||||
# We recommend checking this file into your source control in the root of your Python project
|
||||
# If this file is named .safety-policy.yml and is in the same directory where you run `safety check` it will be used by default.
|
||||
# Otherwise, you can use the flag `safety check --policy-file <path-to-this-file>` to specify a custom location and name for the file.
|
||||
# To validate and review your policy file, run the validate command: `safety validate policy_file --path <path-to-this-file>`
|
||||
security: # configuration for the `safety check` command
|
||||
ignore-vulnerabilities: # Here you can list multiple specific vulnerabilities you want to ignore (optionally for a time period)
|
||||
67599: # Example vulnerability ID
|
||||
reason: disputed, inapplicable
|
||||
70612:
|
||||
reason: disputed, inapplicable
|
||||
@@ -1,19 +1,65 @@
|
||||
# Contributing
|
||||
# Contributing to Mobile Verification Toolkit (MVT)
|
||||
|
||||
Thank you for your interest in contributing to Mobile Verification Toolkit (MVT)! Your help is very much appreciated.
|
||||
We greatly appreciate contributions to MVT!
|
||||
|
||||
Your involvement, whether through identifying issues, improving functionality, or enhancing documentation, is very much appreciated. To ensure smooth collaboration and a welcoming environment, we've outlined some key guidelines for contributing below.
|
||||
|
||||
## Getting started
|
||||
|
||||
Contributing to an open-source project like MVT might seem overwhelming at first, but we're here to support you!
|
||||
|
||||
Whether you're a technologist, a frontline human rights defender, a field researcher, or someone new to consensual spyware forensics, there are many ways to make meaningful contributions.
|
||||
|
||||
Here's how you can get started:
|
||||
|
||||
1. **Explore the codebase:**
|
||||
- Browse the repository to get familar with MVT. Many MVT modules are simple in functionality and easy to understand.
|
||||
- Look for `TODO:` or `FIXME:` comments in the code for areas that need attention.
|
||||
|
||||
2. **Check Github issues:**
|
||||
- Look for issues tagged with ["help wanted"](https://github.com/mvt-project/mvt/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) or ["good first issue"](https://github.com/mvt-project/mvt/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to find tasks that are beginner-friendly or where input from the community would be helpful.
|
||||
|
||||
3. **Ask for guidance:**
|
||||
|
||||
- If you're unsure where to start, feel free to open a [discussion](https://github.com/mvt-project/mvt/discussions) or comment on an issue.
|
||||
|
||||
## How to contribute:
|
||||
|
||||
1. **Report issues:**
|
||||
|
||||
- Found a bug? Please check existing issues to see if it's already reported. If not, open a new issue. Mobile operating systems and databases are constantly evolving, an new errors may appear spontaniously in new app versions.
|
||||
|
||||
**Please provide as much information as possible about the prodblem including: any error messages, steps to reproduce the problem, and any logs or screenshots that can help.**
|
||||
|
||||
|
||||
## Where to start
|
||||
2. **Suggest features:**
|
||||
- If you have an idea for new functionality, create a feature request issue and describe your proposal.
|
||||
|
||||
Starting to contribute to a somewhat complex project like MVT might seem intimidating. Unless you have specific ideas of new functionality you would like to submit, some good starting points are searching for `TODO:` and `FIXME:` comments throughout the code. Alternatively you can check if any GitHub issues existed marked with the ["help wanted"](https://github.com/mvt-project/mvt/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) tag.
|
||||
3. **Submit code:**
|
||||
- Fork the repository and create a new branch for your changes.
|
||||
- Ensure your changes align with the code style guidelines (see below).
|
||||
- Open a pull request (PR) with a clear description of your changes and link it to any relevant issues.
|
||||
|
||||
4. **Documentation contributions:**
|
||||
- Improving documentation is just as valuable as contributing code! If you notice gaps or inaccuracies in the documentation, feel free to submit changes or suggest updates.
|
||||
|
||||
## Code style
|
||||
Please follow these code style guidelines for consistency and readability:
|
||||
|
||||
When contributing code to
|
||||
- **Indentation**: use 4 spaces per tab.
|
||||
- **Quotes**: Use double quotes (`"`) by default. Use single quotes (`'`) for nested strings instead of escaping (`\"`), or when using f-formatting.
|
||||
- **Maximum line length**:
|
||||
- Aim for lines no longer than 80 characters.
|
||||
- Exceptions are allowed for long log lines or strings, which may extend up to 100 characters.
|
||||
- Wrap lines that exceed 100 characters.
|
||||
|
||||
- **Indentation**: we use 4-spaces tabs.
|
||||
Follow [PEP 8 guidelines](https://peps.python.org/pep-0008/) for indentation and overall Python code style. All MVT code is automatically linted with [Ruff](https://github.com/astral-sh/ruff) before merging.
|
||||
|
||||
- **Quotes**: we use double quotes (`"`) as a default. Single quotes (`'`) can be favored with nested strings instead of escaping (`\"`), or when using f-formatting.
|
||||
Please check your code before opening a pull request by running `make ruff`
|
||||
|
||||
- **Maximum line length**: we strongly encourage to respect a 80 characters long lines and to follow [PEP8 indentation guidelines](https://peps.python.org/pep-0008/#indentation) when having to wrap. However, if breaking at 80 is not possible or is detrimental to the readability of the code, exceptions are tolerated. For example, long log lines, or long strings can be extended to 100 characters long. Please hard wrap anything beyond 100 characters.
|
||||
|
||||
## Community and support
|
||||
|
||||
We aim to create a supportive and collaborative environment for all contributors. If you run into any challenges, feel free to reach out through the discussions or issues section of the repository.
|
||||
|
||||
Your contributions, big or small, help improve MVT and are always appreciated.
|
||||
180
Dockerfile
180
Dockerfile
@@ -1,79 +1,159 @@
|
||||
FROM ubuntu:22.04
|
||||
# Base image for building libraries
|
||||
# ---------------------------------
|
||||
FROM ubuntu:22.04 as build-base
|
||||
|
||||
# Ref. https://github.com/mvt-project/mvt
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
LABEL url="https://mvt.re"
|
||||
LABEL vcs-url="https://github.com/mvt-project/mvt"
|
||||
LABEL description="MVT is a forensic tool to look for signs of infection in smartphone devices."
|
||||
|
||||
ENV PIP_NO_CACHE_DIR=1
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Fixing major OS dependencies
|
||||
# ----------------------------
|
||||
RUN apt update \
|
||||
&& apt install -y python3 python3-pip libusb-1.0-0-dev wget unzip default-jre-headless adb \
|
||||
|
||||
# Install build tools for libimobiledevice
|
||||
# ----------------------------------------
|
||||
# Install build tools and dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
build-essential \
|
||||
checkinstall \
|
||||
git \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool-bin \
|
||||
libplist-dev \
|
||||
libusbmuxd-dev \
|
||||
libssl-dev \
|
||||
sqlite3 \
|
||||
pkg-config \
|
||||
libcurl4-openssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
libssl-dev \
|
||||
udev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Clean up
|
||||
|
||||
# libplist
|
||||
# --------
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /var/cache/apt
|
||||
FROM build-base as build-libplist
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libplist && cd libplist \
|
||||
&& ./autogen.sh && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libplist
|
||||
|
||||
|
||||
# Build libimobiledevice
|
||||
# ----------------------
|
||||
RUN git clone https://github.com/libimobiledevice/libplist \
|
||||
&& git clone https://github.com/libimobiledevice/libimobiledevice-glue \
|
||||
&& git clone https://github.com/libimobiledevice/libusbmuxd \
|
||||
&& git clone https://github.com/libimobiledevice/libimobiledevice \
|
||||
&& git clone https://github.com/libimobiledevice/usbmuxd \
|
||||
# libimobiledevice-glue
|
||||
# ---------------------
|
||||
FROM build-base as build-libimobiledevice-glue
|
||||
|
||||
&& cd libplist && ./autogen.sh && make && make install && ldconfig \
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
|
||||
&& cd ../libimobiledevice-glue && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./autogen.sh --prefix=/usr && make && make install && ldconfig \
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libimobiledevice-glue && cd libimobiledevice-glue \
|
||||
&& ./autogen.sh && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libimobiledevice-glue
|
||||
|
||||
&& cd ../libusbmuxd && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./autogen.sh && make && make install && ldconfig \
|
||||
|
||||
&& cd ../libimobiledevice && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./autogen.sh --enable-debug && make && make install && ldconfig \
|
||||
# libtatsu
|
||||
# --------
|
||||
FROM build-base as build-libtatsu
|
||||
|
||||
&& cd ../usbmuxd && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --runstatedir=/run && make && make install \
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
|
||||
# Clean up.
|
||||
&& cd .. && rm -rf libplist libimobiledevice-glue libusbmuxd libimobiledevice usbmuxd
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libtatsu && cd libtatsu \
|
||||
&& ./autogen.sh && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libtatsu
|
||||
|
||||
# Installing MVT
|
||||
# --------------
|
||||
RUN pip3 install git+https://github.com/mvt-project/mvt.git@main
|
||||
|
||||
# libusbmuxd
|
||||
# ----------
|
||||
FROM build-base as build-libusbmuxd
|
||||
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
COPY --from=build-libimobiledevice-glue /build /
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libusbmuxd && cd libusbmuxd \
|
||||
&& ./autogen.sh && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libusbmuxd
|
||||
|
||||
|
||||
# libimobiledevice
|
||||
# ----------------
|
||||
FROM build-base as build-libimobiledevice
|
||||
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
COPY --from=build-libtatsu /build /
|
||||
COPY --from=build-libimobiledevice-glue /build /
|
||||
COPY --from=build-libusbmuxd /build /
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libimobiledevice && cd libimobiledevice \
|
||||
&& ./autogen.sh --enable-debug && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libimobiledevice
|
||||
|
||||
|
||||
# usbmuxd
|
||||
# -------
|
||||
FROM build-base as build-usbmuxd
|
||||
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
COPY --from=build-libimobiledevice-glue /build /
|
||||
COPY --from=build-libusbmuxd /build /
|
||||
COPY --from=build-libimobiledevice /build /
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/usbmuxd && cd usbmuxd \
|
||||
&& ./autogen.sh --sysconfdir=/etc --localstatedir=/var --runstatedir=/run && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf usbmuxd && mv /build/lib /build/usr/lib
|
||||
|
||||
|
||||
# Create main image
|
||||
FROM ubuntu:22.04 as main
|
||||
|
||||
LABEL org.opencontainers.image.url="https://mvt.re"
|
||||
LABEL org.opencontainers.image.documentation="https://docs.mvt.re"
|
||||
LABEL org.opencontainers.image.source="https://github.com/mvt-project/mvt"
|
||||
LABEL org.opencontainers.image.title="Mobile Verification Toolkit"
|
||||
LABEL org.opencontainers.image.description="MVT is a forensic tool to look for signs of infection in smartphone devices."
|
||||
LABEL org.opencontainers.image.licenses="MVT License 1.1"
|
||||
LABEL org.opencontainers.image.base.name=docker.io/library/ubuntu:22.04
|
||||
|
||||
# Install runtime dependencies
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
adb \
|
||||
default-jre-headless \
|
||||
libcurl4 \
|
||||
libssl3 \
|
||||
libusb-1.0-0 \
|
||||
python3 \
|
||||
sqlite3
|
||||
COPY --from=build-libplist /build /
|
||||
COPY --from=build-libimobiledevice-glue /build /
|
||||
COPY --from=build-libtatsu /build /
|
||||
COPY --from=build-libusbmuxd /build /
|
||||
COPY --from=build-libimobiledevice /build /
|
||||
COPY --from=build-usbmuxd /build /
|
||||
|
||||
# Install mvt using the locally checked out source
|
||||
COPY . mvt/
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y git python3-pip \
|
||||
&& PIP_NO_CACHE_DIR=1 pip3 install --upgrade pip \
|
||||
&& PIP_NO_CACHE_DIR=1 pip3 install ./mvt \
|
||||
&& apt-get remove -y python3-pip git && apt-get autoremove -y \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& rm -rf mvt
|
||||
|
||||
# Installing ABE
|
||||
# --------------
|
||||
RUN mkdir /opt/abe \
|
||||
&& wget https://github.com/nelenkov/android-backup-extractor/releases/download/master-20221109063121-8fdfc5e/abe.jar -O /opt/abe/abe.jar \
|
||||
ADD --checksum=sha256:a20e07f8b2ea47620aff0267f230c3f1f495f097081fd709eec51cf2a2e11632 \
|
||||
https://github.com/nelenkov/android-backup-extractor/releases/download/master-20221109063121-8fdfc5e/abe.jar /opt/abe/abe.jar
|
||||
# Create alias for abe
|
||||
&& echo 'alias abe="java -jar /opt/abe/abe.jar"' >> ~/.bashrc
|
||||
RUN echo 'alias abe="java -jar /opt/abe/abe.jar"' >> ~/.bashrc
|
||||
|
||||
# Generate adb key folder
|
||||
# ------------------------------
|
||||
RUN mkdir /root/.android && adb keygen /root/.android/adbkey
|
||||
# Generate adb key folder
|
||||
RUN echo 'if [ ! -f /root/.android/adbkey ]; then adb keygen /root/.android/adbkey 2&>1 > /dev/null; fi' >> ~/.bashrc
|
||||
RUN mkdir /root/.android
|
||||
|
||||
# Setup investigations environment
|
||||
# --------------------------------
|
||||
RUN mkdir /home/cases
|
||||
WORKDIR /home/cases
|
||||
WORKDIR /home/cases
|
||||
RUN echo 'echo "Mobile Verification Toolkit @ Docker\n------------------------------------\n\nYou can find information about how to use this image for Android (https://github.com/mvt-project/mvt/tree/master/docs/android) and iOS (https://github.com/mvt-project/mvt/tree/master/docs/ios) in the official docs of the project.\n"' >> ~/.bashrc \
|
||||
&& echo 'echo "Note that to perform the debug via USB you might need to give the Docker image access to the USB using \"docker run -it --privileged -v /dev/bus/usb:/dev/bus/usb mvt\" or, preferably, the \"--device=\" parameter.\n"' >> ~/.bashrc
|
||||
|
||||
|
||||
36
Dockerfile.android
Normal file
36
Dockerfile.android
Normal file
@@ -0,0 +1,36 @@
|
||||
# Create main image
|
||||
FROM python:3.10.14-alpine3.20 as main
|
||||
|
||||
LABEL org.opencontainers.image.url="https://mvt.re"
|
||||
LABEL org.opencontainers.image.documentation="https://docs.mvt.re"
|
||||
LABEL org.opencontainers.image.source="https://github.com/mvt-project/mvt"
|
||||
LABEL org.opencontainers.image.title="Mobile Verification Toolkit (Android)"
|
||||
LABEL org.opencontainers.image.description="MVT is a forensic tool to look for signs of infection in smartphone devices."
|
||||
LABEL org.opencontainers.image.licenses="MVT License 1.1"
|
||||
LABEL org.opencontainers.image.base.name=docker.io/library/python:3.10.14-alpine3.20
|
||||
|
||||
# Install runtime dependencies
|
||||
RUN apk add --no-cache \
|
||||
android-tools \
|
||||
git \
|
||||
libusb \
|
||||
openjdk11-jre-headless \
|
||||
sqlite
|
||||
|
||||
# Install mvt
|
||||
COPY ./ mvt
|
||||
RUN apk add --no-cache --virtual .build-deps gcc musl-dev \
|
||||
&& PIP_NO_CACHE_DIR=1 pip3 install ./mvt \
|
||||
&& apk del .build-deps gcc musl-dev && rm -rf ./mvt
|
||||
|
||||
# Installing ABE
|
||||
ADD --checksum=sha256:a20e07f8b2ea47620aff0267f230c3f1f495f097081fd709eec51cf2a2e11632 \
|
||||
https://github.com/nelenkov/android-backup-extractor/releases/download/master-20221109063121-8fdfc5e/abe.jar /opt/abe/abe.jar
|
||||
# Create alias for abe
|
||||
RUN echo 'alias abe="java -jar /opt/abe/abe.jar"' >> ~/.bashrc
|
||||
|
||||
# Generate adb key folder
|
||||
RUN echo 'if [ ! -f /root/.android/adbkey ]; then adb keygen /root/.android/adbkey 2&>1 > /dev/null; fi' >> ~/.bashrc
|
||||
RUN mkdir /root/.android
|
||||
|
||||
ENTRYPOINT [ "/usr/local/bin/mvt-android" ]
|
||||
137
Dockerfile.ios
Normal file
137
Dockerfile.ios
Normal file
@@ -0,0 +1,137 @@
|
||||
# Base image for building libraries
|
||||
# ---------------------------------
|
||||
FROM ubuntu:22.04 as build-base
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install build tools and dependencies
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
build-essential \
|
||||
git \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool-bin \
|
||||
pkg-config \
|
||||
libcurl4-openssl-dev \
|
||||
libusb-1.0-0-dev \
|
||||
libssl-dev \
|
||||
udev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# libplist
|
||||
# --------
|
||||
FROM build-base as build-libplist
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libplist && cd libplist \
|
||||
&& ./autogen.sh && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libplist
|
||||
|
||||
|
||||
# libimobiledevice-glue
|
||||
# ---------------------
|
||||
FROM build-base as build-libimobiledevice-glue
|
||||
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libimobiledevice-glue && cd libimobiledevice-glue \
|
||||
&& ./autogen.sh && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libimobiledevice-glue
|
||||
|
||||
|
||||
# libtatsu
|
||||
# --------
|
||||
FROM build-base as build-libtatsu
|
||||
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libtatsu && cd libtatsu \
|
||||
&& ./autogen.sh && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libtatsu
|
||||
|
||||
|
||||
# libusbmuxd
|
||||
# ----------
|
||||
FROM build-base as build-libusbmuxd
|
||||
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
COPY --from=build-libimobiledevice-glue /build /
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libusbmuxd && cd libusbmuxd \
|
||||
&& ./autogen.sh && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libusbmuxd
|
||||
|
||||
|
||||
# libimobiledevice
|
||||
# ----------------
|
||||
FROM build-base as build-libimobiledevice
|
||||
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
COPY --from=build-libtatsu /build /
|
||||
COPY --from=build-libimobiledevice-glue /build /
|
||||
COPY --from=build-libusbmuxd /build /
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/libimobiledevice && cd libimobiledevice \
|
||||
&& ./autogen.sh --enable-debug && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf libimobiledevice
|
||||
|
||||
|
||||
# usbmuxd
|
||||
# -------
|
||||
FROM build-base as build-usbmuxd
|
||||
|
||||
# Install dependencies
|
||||
COPY --from=build-libplist /build /
|
||||
COPY --from=build-libimobiledevice-glue /build /
|
||||
COPY --from=build-libusbmuxd /build /
|
||||
COPY --from=build-libimobiledevice /build /
|
||||
|
||||
# Build
|
||||
RUN git clone https://github.com/libimobiledevice/usbmuxd && cd usbmuxd \
|
||||
&& ./autogen.sh --sysconfdir=/etc --localstatedir=/var --runstatedir=/run && make -j "$(nproc)" && make install DESTDIR=/build \
|
||||
&& cd .. && rm -rf usbmuxd && mv /build/lib /build/usr/lib
|
||||
|
||||
|
||||
# Main image
|
||||
# ----------
|
||||
FROM python:3.10.14-alpine3.20 as main
|
||||
|
||||
LABEL org.opencontainers.image.url="https://mvt.re"
|
||||
LABEL org.opencontainers.image.documentation="https://docs.mvt.re"
|
||||
LABEL org.opencontainers.image.source="https://github.com/mvt-project/mvt"
|
||||
LABEL org.opencontainers.image.title="Mobile Verification Toolkit (iOS)"
|
||||
LABEL org.opencontainers.image.description="MVT is a forensic tool to look for signs of infection in smartphone devices."
|
||||
LABEL org.opencontainers.image.licenses="MVT License 1.1"
|
||||
LABEL org.opencontainers.image.base.name=docker.io/library/python:3.10.14-alpine3.20
|
||||
|
||||
# Install runtime dependencies
|
||||
RUN apk add --no-cache \
|
||||
gcompat \
|
||||
libcurl \
|
||||
libssl3 \
|
||||
libusb \
|
||||
sqlite
|
||||
COPY --from=build-libplist /build /
|
||||
COPY --from=build-libimobiledevice-glue /build /
|
||||
COPY --from=build-libtatsu /build /
|
||||
COPY --from=build-libusbmuxd /build /
|
||||
COPY --from=build-libimobiledevice /build /
|
||||
COPY --from=build-usbmuxd /build /
|
||||
|
||||
# Install mvt using the locally checked out source
|
||||
COPY ./ mvt
|
||||
RUN apk add --no-cache --virtual .build-deps git gcc musl-dev \
|
||||
&& PIP_NO_CACHE_DIR=1 pip3 install ./mvt \
|
||||
&& apk del .build-deps git gcc musl-dev && rm -rf ./mvt
|
||||
|
||||
ENTRYPOINT [ "/usr/local/bin/mvt-ios" ]
|
||||
36
Makefile
36
Makefile
@@ -1,23 +1,39 @@
|
||||
PWD = $(shell pwd)
|
||||
|
||||
check:
|
||||
flake8
|
||||
ruff check -q .
|
||||
black --check .
|
||||
pytest -q
|
||||
autofix:
|
||||
ruff format .
|
||||
ruff check --fix .
|
||||
|
||||
check: ruff mypy
|
||||
|
||||
ruff:
|
||||
ruff format --check .
|
||||
ruff check -q .
|
||||
|
||||
mypy:
|
||||
mypy
|
||||
|
||||
test:
|
||||
python3 -m pytest
|
||||
|
||||
test-ci:
|
||||
python3 -m pytest -v
|
||||
|
||||
install:
|
||||
python3 -m pip install --upgrade -e .
|
||||
|
||||
test-requirements:
|
||||
python3 -m pip install --upgrade -r test-requirements.txt
|
||||
|
||||
clean:
|
||||
rm -rf $(PWD)/build $(PWD)/dist $(PWD)/mvt.egg-info
|
||||
rm -rf $(PWD)/build $(PWD)/dist $(PWD)/src/mvt.egg-info
|
||||
|
||||
dist:
|
||||
python3 setup.py sdist bdist_wheel
|
||||
python3 -m pip install --upgrade build
|
||||
python3 -m build
|
||||
|
||||
upload:
|
||||
python3 -m twine upload dist/*
|
||||
|
||||
test-upload:
|
||||
python3 -m twine upload --repository testpypi dist/*
|
||||
|
||||
pylint:
|
||||
pylint --rcfile=setup.cfg mvt
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
[](https://pypi.org/project/mvt/)
|
||||
[](https://docs.mvt.re/en/latest/?badge=latest)
|
||||
[](https://github.com/mvt-project/mvt/actions/workflows/python-package.yml)
|
||||
[](https://github.com/mvt-project/mvt/actions/workflows/tests.yml)
|
||||
[](https://pepy.tech/project/mvt)
|
||||
|
||||
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.
|
||||
@@ -26,7 +26,7 @@ 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/).
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2022 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 os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from mvt import android
|
||||
|
||||
android.cli()
|
||||
14
dev/mvt-ios
14
dev/mvt-ios
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2022 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 os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from mvt import ios
|
||||
|
||||
ios.cli()
|
||||
@@ -1,6 +1,6 @@
|
||||
# Downloading APKs from an Android phone
|
||||
|
||||
MVT allows to attempt to download all available installed packages (APKs) in order to further inspect them and potentially identify any which might be malicious in nature.
|
||||
MVT allows you to attempt to download all available installed packages (APKs) from a device in order to further inspect them and potentially identify any which might be malicious in nature.
|
||||
|
||||
You can do so by launching the following command:
|
||||
|
||||
|
||||
@@ -2,7 +2,22 @@ Using Docker simplifies having all the required dependencies and tools (includin
|
||||
|
||||
Install Docker following the [official documentation](https://docs.docker.com/get-docker/).
|
||||
|
||||
Once installed, you can clone MVT's repository and build its Docker image:
|
||||
Once Docker is installed, you can run MVT by downloading a prebuilt MVT Docker image, or by building a Docker image yourself from the MVT source repo.
|
||||
|
||||
### Using the prebuilt Docker image
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/mvt-project/mvt
|
||||
```
|
||||
|
||||
You can then run the Docker container with:
|
||||
|
||||
```
|
||||
docker run -it ghcr.io/mvt-project/mvt
|
||||
```
|
||||
|
||||
|
||||
### Build and run Docker image from source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/mvt-project/mvt.git
|
||||
@@ -18,6 +33,9 @@ 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
|
||||
|
||||
@@ -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://securitylab.amnesty.org/contact-us/) 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
docs/iocs.md
10
docs/iocs.md
@@ -34,6 +34,13 @@ It is also possible to load STIX2 files automatically from the environment varia
|
||||
export MVT_STIX2="/home/user/IOC1.stix2:/home/user/IOC2.stix2"
|
||||
```
|
||||
|
||||
## STIX2 Support
|
||||
|
||||
So far MVT implements only a subset of [STIX2 specifications](https://docs.oasis-open.org/cti/stix/v2.1/csprd01/stix-v2.1-csprd01.html):
|
||||
|
||||
* It only supports checks for one value (such as `[domain-name:value='DOMAIN']`) and not boolean expressions over multiple comparisons
|
||||
* It only supports the following types: `domain-name:value`, `process:name`, `email-addr:value`, `file:name`, `file:path`, `file:hashes.md5`, `file:hashes.sha1`, `file:hashes.sha256`, `app:id`, `configuration-profile:id`, `android-property:name`, `url:value` (but each type will only be checked by a module if it is relevant to the type of data obtained)
|
||||
|
||||
## Known repositories of STIX2 IOCs
|
||||
|
||||
- The [Amnesty International investigations repository](https://github.com/AmnestyTech/investigations) contains STIX-formatted IOCs for:
|
||||
@@ -46,3 +53,6 @@ export MVT_STIX2="/home/user/IOC1.stix2:/home/user/IOC2.stix2"
|
||||
You can automaticallly download the latest public indicator files with the command `mvt-ios download-iocs` or `mvt-android download-iocs`. These commands download the list of indicators from the [mvt-indicators](https://github.com/mvt-project/mvt-indicators/blob/main/indicators.yaml) repository and store them in the [appdir](https://pypi.org/project/appdirs/) folder. They are then loaded automatically by MVT.
|
||||
|
||||
Please [open an issue](https://github.com/mvt-project/mvt/issues/) to suggest new sources of STIX-formatted IOCs.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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,5 +1,5 @@
|
||||
mkdocs==1.2.3
|
||||
mkdocs-autorefs
|
||||
mkdocs-material
|
||||
mkdocs-material-extensions
|
||||
mkdocstrings
|
||||
mkdocs==1.6.1
|
||||
mkdocs-autorefs==1.2.0
|
||||
mkdocs-material==9.5.42
|
||||
mkdocs-material-extensions==1.3.1
|
||||
mkdocstrings==0.23.0
|
||||
@@ -7,8 +7,8 @@ markdown_extensions:
|
||||
- attr_list
|
||||
- admonition
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
- pymdownx.superfences
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.highlight:
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 The MVT Authors.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
from mvt.common.artifact import Artifact
|
||||
|
||||
|
||||
class AndroidArtifact(Artifact):
|
||||
@staticmethod
|
||||
def extract_dumpsys_section(dumpsys: str, separator: str) -> str:
|
||||
"""
|
||||
Extract a section from a full dumpsys file.
|
||||
|
||||
:param dumpsys: content of the full dumpsys file (string)
|
||||
:param separator: content of the first line separator (string)
|
||||
:return: section extracted (string)
|
||||
"""
|
||||
lines = []
|
||||
in_section = False
|
||||
for line in dumpsys.splitlines():
|
||||
if line.strip() == separator:
|
||||
in_section = True
|
||||
continue
|
||||
|
||||
if not in_section:
|
||||
continue
|
||||
|
||||
if line.strip().startswith(
|
||||
"------------------------------------------------------------------------------"
|
||||
):
|
||||
break
|
||||
|
||||
lines.append(line)
|
||||
|
||||
return "\n".join(lines)
|
||||
@@ -1,118 +0,0 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 The MVT Authors.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
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):
|
||||
"""This module analyse dumpsys packages"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_path: Optional[str] = None,
|
||||
target_path: Optional[str] = None,
|
||||
results_path: Optional[str] = None,
|
||||
module_options: Optional[dict] = None,
|
||||
log: logging.Logger = logging.getLogger(__name__),
|
||||
results: Optional[List[Dict[str, Any]]] = None,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
file_path=file_path,
|
||||
target_path=target_path,
|
||||
results_path=results_path,
|
||||
module_options=module_options,
|
||||
log=log,
|
||||
results=results,
|
||||
)
|
||||
|
||||
def 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))
|
||||
|
||||
for result in self.results:
|
||||
dangerous_permissions_count = 0
|
||||
for perm in result["permissions"]:
|
||||
if perm["name"] in DANGEROUS_PERMISSIONS:
|
||||
dangerous_permissions_count += 1
|
||||
|
||||
if dangerous_permissions_count >= DANGEROUS_PERMISSIONS_THRESHOLD:
|
||||
self.log.info(
|
||||
'Found package "%s" requested %d potentially dangerous permissions',
|
||||
result["package_name"],
|
||||
dangerous_permissions_count,
|
||||
)
|
||||
|
||||
self.log.info("Extracted details on %d packages", len(self.results))
|
||||
@@ -1,131 +0,0 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 The MVT Authors.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
import logging
|
||||
from typing import Optional, Union
|
||||
|
||||
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 BugReportModule
|
||||
|
||||
|
||||
class Packages(BugReportModule):
|
||||
"""This module extracts details on receivers for risky activities."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file_path: Optional[str] = None,
|
||||
target_path: Optional[str] = None,
|
||||
results_path: Optional[str] = None,
|
||||
module_options: Optional[dict] = None,
|
||||
log: logging.Logger = logging.getLogger(__name__),
|
||||
results: Optional[list] = None,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
file_path=file_path,
|
||||
target_path=target_path,
|
||||
results_path=results_path,
|
||||
module_options=module_options,
|
||||
log=log,
|
||||
results=results,
|
||||
)
|
||||
|
||||
def 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:
|
||||
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))
|
||||
|
||||
for result in self.results:
|
||||
dangerous_permissions_count = 0
|
||||
for perm in result["permissions"]:
|
||||
if perm["name"] in DANGEROUS_PERMISSIONS:
|
||||
dangerous_permissions_count += 1
|
||||
|
||||
if dangerous_permissions_count >= DANGEROUS_PERMISSIONS_THRESHOLD:
|
||||
self.log.info(
|
||||
'Found package "%s" requested %d potentially dangerous permissions',
|
||||
result["package_name"],
|
||||
dangerous_permissions_count,
|
||||
)
|
||||
|
||||
self.log.info("Extracted details on %d packages", len(self.results))
|
||||
@@ -1,131 +0,0 @@
|
||||
# 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
|
||||
|
||||
|
||||
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,19 +0,0 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 The MVT Authors.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
def warn_android_patch_level(patch_level: str, log) -> bool:
|
||||
"""Alert if Android patch level out-of-date"""
|
||||
patch_date = datetime.strptime(patch_level, "%Y-%m-%d")
|
||||
if (datetime.now() - patch_date) > timedelta(days=6 * 31):
|
||||
log.warning(
|
||||
"This phone has not received security updates "
|
||||
"for more than six months (last update: %s)",
|
||||
patch_level,
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -1,18 +0,0 @@
|
||||
# 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/
|
||||
|
||||
# Help messages of repeating options.
|
||||
HELP_MSG_OUTPUT = "Specify a path to a folder where you want to store JSON results"
|
||||
HELP_MSG_IOC = "Path to indicators file (can be invoked multiple time)"
|
||||
HELP_MSG_FAST = "Avoid running time/resource consuming features"
|
||||
HELP_MSG_LIST_MODULES = "Print list of available modules and exit"
|
||||
HELP_MSG_MODULE = "Name of a single module you would like to run instead of all"
|
||||
HELP_MSG_NONINTERACTIVE = "Don't ask interactive questions during processing"
|
||||
HELP_MSG_ANDROID_BACKUP_PASSWORD = "The backup password to use for an Android backup"
|
||||
HELP_MSG_HASHES = "Generate hashes of all the files analyzed"
|
||||
HELP_MSG_VERBOSE = "Verbose mode"
|
||||
|
||||
# Android-specific.
|
||||
HELP_MSG_SERIAL = "Specify a device serial number or HOST:PORT connection string"
|
||||
102
pyproject.toml
Normal file
102
pyproject.toml
Normal file
@@ -0,0 +1,102 @@
|
||||
[project]
|
||||
name = "mvt"
|
||||
dynamic = ["version"]
|
||||
authors = [
|
||||
{name = "Claudio Guarnieri", email = "nex@nex.sx"}
|
||||
]
|
||||
maintainers = [
|
||||
{name = "Etienne Maynier", email = "tek@randhome.io"},
|
||||
{name = "Donncha Ó Cearbhaill", email = "donncha.ocearbhaill@amnesty.org"},
|
||||
{name = "Rory Flynn", email = "rory.flynn@amnesty.org"}
|
||||
]
|
||||
description = "Mobile Verification Toolkit"
|
||||
readme = "README.md"
|
||||
keywords = ["security", "mobile", "forensics", "malware"]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Information Technology",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python"
|
||||
]
|
||||
dependencies = [
|
||||
"click >=8.1.3",
|
||||
"rich >=12.6.0",
|
||||
"tld >=0.12.6",
|
||||
"requests >=2.28.1",
|
||||
"simplejson >=3.17.6",
|
||||
"packaging >=21.3",
|
||||
"appdirs >=1.4.4",
|
||||
"iOSbackup >=0.9.923",
|
||||
"adb-shell[usb] >=0.4.3",
|
||||
"libusb1 >=3.0.0",
|
||||
"cryptography >=42.0.5",
|
||||
"pyyaml >=6.0",
|
||||
"pyahocorasick >= 2.0.0",
|
||||
]
|
||||
requires-python = ">= 3.8"
|
||||
|
||||
[project.urls]
|
||||
homepage = "https://docs.mvt.re/en/latest/"
|
||||
repository = "https://github.com/mvt-project/mvt"
|
||||
|
||||
[project.scripts]
|
||||
mvt-ios = "mvt.ios:cli"
|
||||
mvt-android = "mvt.android:cli"
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.coverage.run]
|
||||
omit = [
|
||||
"tests/*",
|
||||
]
|
||||
|
||||
[tool.coverage.html]
|
||||
directory= "htmlcov"
|
||||
|
||||
[tool.mypy]
|
||||
install_types = true
|
||||
non_interactive = true
|
||||
ignore_missing_imports = true
|
||||
packages = "src"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "-ra -q --cov=mvt --cov-report html --junitxml=pytest.xml --cov-report=term-missing:skip-covered"
|
||||
testpaths = [
|
||||
"tests"
|
||||
]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["C90", "E", "F", "W"] # flake8 default set
|
||||
ignore = [
|
||||
"E501", # don't enforce line length violations
|
||||
"C901", # complex-structure
|
||||
|
||||
# These were previously ignored but don't seem to be required:
|
||||
# "E265", # no-space-after-block-comment
|
||||
# "F401", # unused-import
|
||||
# "E127", # not included in ruff
|
||||
# "W503", # not included in ruff
|
||||
# "E226", # missing-whitespace-around-arithmetic-operator
|
||||
# "E203", # whitespace-before-punctuation
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"__init__.py" = ["F401"] # unused-import
|
||||
|
||||
[tool.ruff.lint.mccabe]
|
||||
max-complexity = 10
|
||||
|
||||
[tool.setuptools]
|
||||
include-package-data = true
|
||||
package-dir = {"" = "src"}
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["src"]
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
mvt = ["ios/data/*.json"]
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
version = {attr = "mvt.common.version.MVT_VERSION"}
|
||||
@@ -1,6 +0,0 @@
|
||||
# Never enforce `E501` (line length violations).
|
||||
ignore = ["E501"]
|
||||
|
||||
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
||||
[per-file-ignores]
|
||||
"__init__.py" = ["F401"]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user