1
mirror of https://github.com/mvt-project/mvt synced 2025-10-21 22:42:15 +02:00

Compare commits

..

21 Commits

Author SHA1 Message Date
Nex
02bf903411 Bumped version 2021-10-30 13:40:25 +02:00
Nex
7019375767 Merge pull request #210 from hurtcrushing/main
Search for entries in ZPROCESS but not in ZLIVEUSAGE
2021-10-27 14:22:40 +02:00
Nex
34dd27c5d2 Added iPhone 13 2021-10-26 18:33:07 +02:00
Nex
a4d6a08a8b Added iOS 15.1 2021-10-26 18:09:31 +02:00
hurtcrushing
635d3a392d change warning to info 2021-10-25 14:54:03 +02:00
hurtcrushing
2d78bddbba Search for entries in ZPROCESS but not in ZLIVEUSAGE 2021-10-25 14:34:18 +02:00
Nex
c1938d2ead Merge branch 'main' of github.com:mvt-project/mvt 2021-10-25 11:18:12 +02:00
Nex
104b01e5cd Fixed links to docs 2021-10-25 09:19:10 +02:00
Nex
7087e8adb2 Merge pull request #209 from mvt-project/dependabot/pip/docs/mkdocs-1.2.3
Bump mkdocs from 1.2.1 to 1.2.3 in /docs
2021-10-23 20:17:18 +02:00
dependabot[bot]
67608ac02b Bump mkdocs from 1.2.1 to 1.2.3 in /docs
Bumps [mkdocs](https://github.com/mkdocs/mkdocs) from 1.2.1 to 1.2.3.
- [Release notes](https://github.com/mkdocs/mkdocs/releases)
- [Commits](https://github.com/mkdocs/mkdocs/compare/1.2.1...1.2.3)

---
updated-dependencies:
- dependency-name: mkdocs
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-23 11:56:25 +00:00
Nex
6d8de5b461 Bumped version 2021-10-23 13:51:44 +02:00
Nex
b0177d6104 Upgraded adb-shell 2021-10-23 13:51:33 +02:00
tek
e0c9a44b10 Merge branch 'main' of github.com:mvt-project/mvt 2021-10-21 21:17:31 +02:00
tek
ef8c1ae895 Adds recent iOS versions 2021-10-21 21:17:09 +02:00
Nex
3165801e2b Bumped version 2021-10-18 13:40:30 +02:00
Nex
1aa371a398 Upgraded dependencies 2021-10-18 12:57:27 +02:00
Nex
f8e380baa1 Minor style fixes 2021-10-18 12:51:20 +02:00
Nex
35559b09a8 Merge pull request #206 from colossalzippy/main
improve Filesystem module
2021-10-18 12:48:58 +02:00
Nex
daf5c1f3de Merge pull request #205 from witchbuild/main
New artefact, networking_analytics.db
2021-10-18 12:46:39 +02:00
colossalzippy
f601db2174 improve Filesystem 2021-10-15 14:58:50 +02:00
witchbuild
3ce9641c23 add NetworkingAnalytics 2021-10-15 11:53:06 +02:00
9 changed files with 147 additions and 21 deletions

View File

@@ -15,15 +15,15 @@ It has been developed and released by the [Amnesty International Security Lab](h
## 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.html)):
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
```
Alternatively, you can decide to run MVT and all relevant tools through a [Docker container](https://docs.mvt.re/en/latest/docker.html).
Alternatively, you can decide to run MVT and all relevant tools through a [Docker container](https://docs.mvt.re/en/latest/docker/).
**Please note:** MVT is best run on Linux or Mac systems. [It does not currently support running natively on Windows.](https://docs.mvt.re/en/latest/install.html#mvt-on-windows)
**Please note:** MVT is best run on Linux or Mac systems. [It does not currently support running natively on Windows.](https://docs.mvt.re/en/latest/install/#mvt-on-windows)
## Usage
@@ -31,4 +31,4 @@ MVT provides two commands `mvt-ios` and `mvt-android`. [Check out the documentat
## License
The purpose of MVT is to facilitate the ***consensual forensic analysis*** of devices of those who might be targets of sophisticated mobile spyware attacks, especially members of civil society and marginalized communities. We do not want MVT to enable privacy violations of non-consenting individuals. In order to achieve this, MVT is released under its own license. [Read more here.](https://docs.mvt.re/en/latest/license.html)
The purpose of MVT is to facilitate the ***consensual forensic analysis*** of devices of those who might be targets of sophisticated mobile spyware attacks, especially members of civil society and marginalized communities. We do not want MVT to enable privacy violations of non-consenting individuals. In order to achieve this, MVT is released under its own license. [Read more here.](https://docs.mvt.re/en/latest/license/)

View File

@@ -1,4 +1,4 @@
mkdocs==1.2.1
mkdocs==1.2.3
mkdocs-autorefs
mkdocs-material
mkdocs-material-extensions

View File

@@ -6,7 +6,7 @@
import requests
from packaging import version
MVT_VERSION = "1.2.11"
MVT_VERSION = "1.2.14"
def check_for_updates():
res = requests.get("https://pypi.org/pypi/mvt/json")

View File

@@ -6,6 +6,7 @@
from .cache_files import CacheFiles
from .filesystem import Filesystem
from .net_netusage import Netusage
from .networking_analytics import NetworkingAnalytics
from .safari_favicon import SafariFavicon
from .shutdownlog import ShutdownLog
from .version_history import IOSVersionHistory
@@ -13,6 +14,6 @@ from .webkit_indexeddb import WebkitIndexedDB
from .webkit_localstorage import WebkitLocalStorage
from .webkit_safariviewservice import WebkitSafariViewService
FS_MODULES = [CacheFiles, Filesystem, Netusage, SafariFavicon, ShutdownLog,
FS_MODULES = [CacheFiles, Filesystem, Netusage, NetworkingAnalytics, SafariFavicon, ShutdownLog,
IOSVersionHistory, WebkitIndexedDB, WebkitLocalStorage,
WebkitSafariViewService,]

View File

@@ -28,8 +28,8 @@ class Filesystem(IOSExtraction):
return {
"timestamp": record["modified"],
"module": self.__class__.__name__,
"event": "file_modified",
"data": record["file_path"],
"event": "entry_modified",
"data": record["path"],
}
def check_indicators(self):
@@ -37,16 +37,39 @@ class Filesystem(IOSExtraction):
return
for result in self.results:
if self.indicators.check_file(result["file_path"]):
if self.indicators.check_file(result["path"]):
self.log.warning("Found a known malicious file at path: %s", result["path"])
self.detected.append(result)
# If we are instructed to run fast, we skip this.
if self.fast_mode:
self.log.info("Flag --fast was enabled: skipping extended search for suspicious files/processes")
else:
for ioc in self.indicators.ioc_processes:
parts = result["path"].split("/")
if ioc in parts:
self.log.warning("Found a known malicious file/process at path: %s", result["path"])
self.detected.append(result)
def run(self):
for root, dirs, files in os.walk(self.base_folder):
for dir_name in dirs:
try:
dir_path = os.path.join(root, dir_name)
result = {
"path": os.path.relpath(dir_path, self.base_folder),
"modified": convert_timestamp_to_iso(datetime.datetime.utcfromtimestamp(os.stat(dir_path).st_mtime)),
}
except:
continue
else:
self.results.append(result)
for file_name in files:
try:
file_path = os.path.join(root, file_name)
result = {
"file_path": os.path.relpath(file_path, self.base_folder),
"path": os.path.relpath(file_path, self.base_folder),
"modified": convert_timestamp_to_iso(datetime.datetime.utcfromtimestamp(os.stat(file_path).st_mtime)),
}
except:

View File

@@ -0,0 +1,91 @@
# Mobile Verification Toolkit (MVT)
# Copyright (c) 2021 The MVT Project 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 plistlib
import sqlite3
from mvt.common.utils import convert_mactime_to_unix, convert_timestamp_to_iso
from ..base import IOSExtraction
NETWORKING_ANALYTICS_DB_PATH = [
"private/var/Keychains/Analytics/networking_analytics.db",
]
class NetworkingAnalytics(IOSExtraction):
"""This module extracts information from the networking_analytics.db file."""
def __init__(self, file_path=None, base_folder=None, output_folder=None,
fast_mode=False, log=None, results=[]):
super().__init__(file_path=file_path, base_folder=base_folder,
output_folder=output_folder, fast_mode=fast_mode,
log=log, results=results)
def serialize(self, record):
return {
"timestamp": record["timestamp"],
"module": self.__class__.__name__,
"event": "network_crash",
"data": f"{record}",
}
def check_indicators(self):
if not self.indicators:
return
for result in self.results:
for ioc in self.indicators.ioc_processes:
for key in result.keys():
if ioc == result[key]:
self.log.warning("Found mention of a known malicious process \"%s\" in networking_analytics.db at %s",
ioc, result["timestamp"])
self.detected.append(result)
break
def _extract_networking_analytics_data(self):
conn = sqlite3.connect(self.file_path)
cur = conn.cursor()
cur.execute("""
SELECT
timestamp,
data
FROM hard_failures
UNION
SELECT
timestamp,
data
FROM soft_failures;
""")
for row in cur:
if row[0] and row[1]:
timestamp = convert_timestamp_to_iso(convert_mactime_to_unix(row[0], False))
data = plistlib.loads(row[1])
data["timestamp"] = timestamp
elif row[0]:
timestamp = convert_timestamp_to_iso(convert_mactime_to_unix(row[0], False))
data = {}
data["timestamp"] = timestamp
elif row[1]:
timestamp = ""
data = plistlib.loads(row[1])
data["timestamp"] = timestamp
self.results.append(data)
self.results = sorted(self.results, key=lambda entry: entry["timestamp"])
cur.close()
conn.close()
self.log.info("Extracted information on %d network crashes", len(self.results))
def run(self):
self._find_ios_database(root_paths=NETWORKING_ANALYTICS_DB_PATH)
if self.file_path:
self.log.info("Found networking_analytics.db log at path: %s", self.file_path)
self._extract_networking_analytics_data()
else:
self.log.info("networking_analytics.db not found")

View File

@@ -39,7 +39,9 @@ class NetBase(IOSExtraction):
ZLIVEUSAGE.ZHASPROCESS,
ZLIVEUSAGE.ZTIMESTAMP
FROM ZLIVEUSAGE
LEFT JOIN ZPROCESS ON ZLIVEUSAGE.ZHASPROCESS = ZPROCESS.Z_PK;
LEFT JOIN ZPROCESS ON ZLIVEUSAGE.ZHASPROCESS = ZPROCESS.Z_PK
UNION
SELECT ZFIRSTTIMESTAMP, ZTIMESTAMP, ZPROCNAME, ZBUNDLENAME, Z_PK, NULL, NULL, NULL, NULL, NULL, NULL, NULL FROM ZPROCESS WHERE Z_PK NOT IN (SELECT ZHASPROCESS FROM ZLIVEUSAGE);
""")
for row in cur:
@@ -68,7 +70,7 @@ class NetBase(IOSExtraction):
"wwan_out": row[8],
"live_id": row[9],
"live_proc_id": row[10],
"live_isodate": live_timestamp,
"live_isodate": live_timestamp if row[10] else first_isodate,
})
cur.close()
@@ -89,7 +91,7 @@ class NetBase(IOSExtraction):
}]
# Only included first_usage and current_usage records when a ZPROCESS entry exists.
if "MANIPULATED" not in record["proc_name"] and "MISSING" not in record["proc_name"]:
if "MANIPULATED" not in record["proc_name"] and "MISSING" not in record["proc_name"] and record["live_proc_id"] is not None:
records.extend([
{
"timestamp": record["first_isodate"],
@@ -151,6 +153,8 @@ class NetBase(IOSExtraction):
msg = msg + " (However, the process name might have been truncated in the database)"
self.log.warning(msg)
if not proc["live_proc_id"]:
self.log.info(f"Found process entry in ZPROCESS but not in ZLIVEUSAGE : {proc['proc_name']} at {proc['live_isodate']}")
def check_manipulated(self):
"""Check for missing or manipulate DB entries"""

View File

@@ -38,6 +38,10 @@ IPHONE_MODELS = [
{"identifier": "iPhone13,2", "description": "iPhone 12"},
{"identifier": "iPhone13,3", "description": "iPhone 12 Pro"},
{"identifier": "iPhone13,4", "description": "iPhone 12 Pro Max"},
{"identifier": "iPhone14,4", "description": "iPhone 13 Mini"},
{"identifier": "iPhone14,5", "description": "iPhone 13"},
{"identifier": "iPhone14,2", "description": "iPhone 13 Pro"},
{"identifier": "iPhone14,3", "description": "iPhone 13 Pro Max"},
]
IPHONE_IOS_VERSIONS = [
@@ -224,6 +228,9 @@ IPHONE_IOS_VERSIONS = [
{"build": "18G82", "version": "14.7.1"},
{"build": "18H17", "version": "14.8"},
{"build": "19A346", "version": "15.0"},
{"build": "19A348", "version": "15.0.1"},
{"build": "19A404", "version": "15.0.2"},
{"build": "19B74", "version": "15.1"},
]
def get_device_desc_from_id(identifier, devices_list=IPHONE_MODELS):

View File

@@ -16,18 +16,18 @@ with open(readme_path, encoding="utf-8") as handle:
requires = (
# Base dependencies:
"click>=8.0.1",
"rich>=10.6.0",
"click>=8.0.3",
"rich>=10.12.0",
"tld>=0.12.6",
"tqdm>=4.61.2",
"tqdm>=4.62.3",
"requests>=2.26.0",
"simplejson>=3.17.3",
"simplejson>=3.17.5",
"packaging>=21.0",
# iOS dependencies:
"iOSbackup>=0.9.912",
"iOSbackup>=0.9.921",
# Android dependencies:
"adb-shell>=0.4.1",
"libusb1>=1.9.3",
"adb-shell>=0.4.2",
"libusb1>=2.0.1",
)
def get_package_data(package):