mirror of
https://github.com/mvt-project/mvt.git
synced 2026-02-15 18:02:44 +00:00
Compare commits
13 Commits
Te-k-featu
...
ios_lockdo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a30d7b2871 | ||
|
|
459ff8c51c | ||
|
|
88665cf7dd | ||
|
|
0a749da85f | ||
|
|
f81604133a | ||
|
|
cdd9b74cbc | ||
|
|
3fb37b4f30 | ||
|
|
2fe8b58c09 | ||
|
|
61d0c4134d | ||
|
|
6b36fe5fca | ||
|
|
c9f54947e3 | ||
|
|
ae6fec5ac5 | ||
|
|
298726ab2b |
@@ -7,7 +7,7 @@ In this page you can find a (reasonably) up-to-date breakdown of the files creat
|
||||
### `analytics.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup (if encrypted): :material-close:
|
||||
Backup (if encrypted): :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `Analytics` module. The module extracts records from the plists inside the SQLite databases located at *private/var/Keychains/Analytics/\*.db*, which contain various analytics information regarding networking, certificate-pinning, TLS, etc. failures.
|
||||
@@ -19,7 +19,7 @@ If indicators are provided through the command-line, processes and domains are c
|
||||
### `backup_info.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-close:
|
||||
|
||||
This JSON file is created by mvt-ios' `BackupInfo` module. The module extracts some details about the backup and the device, such as name, phone number, IMEI, product type and version.
|
||||
@@ -29,7 +29,7 @@ This JSON file is created by mvt-ios' `BackupInfo` module. The module extracts s
|
||||
### `cache_files.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-close:
|
||||
Backup: :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `CacheFiles` module. The module extracts records from all SQLite database files stored on disk with the name *Cache.db*. These databases typically contain data from iOS' [internal URL caching](https://developer.apple.com/documentation/foundation/nsurlcache). Through this module you might be able to recover records of HTTP requests and responses performed my applications as well as system services, that would otherwise be unavailable. For example, you might see HTTP requests part of an exploitation chain performed by an iOS service attempting to download a first stage malicious payload.
|
||||
@@ -41,7 +41,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `calls.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup (if encrypted): :material-check:
|
||||
Backup (if encrypted): :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `Calls` module. The module extracts records from a SQLite database located at */private/var/mobile/Library/CallHistoryDB/CallHistory.storedata*, which contains records of incoming and outgoing calls, including from messaging apps such as WhatsApp or Skype.
|
||||
@@ -51,7 +51,7 @@ This JSON file is created by mvt-ios' `Calls` module. The module extracts record
|
||||
### `chrome_favicon.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `ChromeFavicon` module. The module extracts records from a SQLite database located at */private/var/mobile/Containers/Data/Application/\*/Library/Application Support/Google/Chrome/Default/Favicons*, which contains a mapping of favicons' URLs and the visited URLs which loaded them.
|
||||
@@ -63,7 +63,7 @@ If indicators are provided through the command-line, they are checked against bo
|
||||
### `chrome_history.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `ChromeHistory` module. The module extracts records from a SQLite database located at */private/var/mobile/Containers/Data/Application/\*/Library/Application Support/Google/Chrome/Default/History*, which contains a history of URL visits.
|
||||
@@ -75,7 +75,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `configuration_profiles.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-close:
|
||||
|
||||
This JSON file is created by mvt-ios' `ConfigurationProfiles` module. The module extracts details about iOS configuration profiles that have been installed on the device. These should include both default iOS as well as third-party profiles.
|
||||
@@ -87,7 +87,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `contacts.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `Contacts` module. The module extracts records from a SQLite database located at */private/var/mobile/Library/AddressBook/AddressBook.sqlitedb*, which contains records from the phone's address book. While this database obviously would not contain any malicious indicators per se, you might want to use it to compare records from other apps (such as iMessage, SMS, etc.) to filter those originating from unknown origins.
|
||||
@@ -97,7 +97,7 @@ This JSON file is created by mvt-ios' `Contacts` module. The module extracts rec
|
||||
### `firefox_favicon.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `FirefoxFavicon` module. The module extracts records from a SQLite database located at */private/var/mobile/profile.profile/browser.db*, which contains a mapping of favicons' URLs and the visited URLs which loaded them.
|
||||
@@ -109,7 +109,7 @@ If indicators are provided through the command-line, they are checked against bo
|
||||
### `firefox_history.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `FirefoxHistory` module. The module extracts records from a SQLite database located at */private/var/mobile/profile.profile/browser.db*, which contains a history of URL visits.
|
||||
@@ -121,7 +121,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `id_status_cache.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup (before iOS 14.7): :material-check:
|
||||
Backup (before iOS 14.7): :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `IDStatusCache` module. The module extracts records from a plist file located at */private/var/mobile/Library/Preferences/com.apple.identityservices.idstatuscache.plist*, which contains a cache of Apple user ID authentication. This chance will indicate when apps like Facetime and iMessage first established contacts with other registered Apple IDs. This is significant because it might contain traces of malicious accounts involved in exploitation of those apps.
|
||||
@@ -133,7 +133,7 @@ Starting from iOS 14.7.0, this file is empty or absent.
|
||||
### `shortcuts.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `Shortcuts` module. The module extracts records from an SQLite database located at */private/var/mobile/Library/Shortcuts/Shortcuts.sqlite*, which contains records about the Shortcuts application. Shortcuts are a built-in iOS feature which allows users to automation certain actions on their device. In some cases the legitimate Shortcuts app may be abused by spyware to maintain persistence on an infected devices.
|
||||
@@ -143,7 +143,7 @@ This JSON file is created by mvt-ios' `Shortcuts` module. The module extracts re
|
||||
### `interaction_c.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup (if encrypted): :material-check:
|
||||
Backup (if encrypted): :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `InteractionC` module. The module extracts records from a SQLite database located at */private/var/mobile/Library/CoreDuet/People/interactionC.db*, which contains details about user interactions with installed apps.
|
||||
@@ -153,7 +153,7 @@ This JSON file is created by mvt-ios' `InteractionC` module. The module extracts
|
||||
### `locationd_clients.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `LocationdClients` module. The module extracts records from a plist file located at */private/var/mobile/Library/Caches/locationd/clients.plist*, which contains a cache of apps which requested access to location services.
|
||||
@@ -163,7 +163,7 @@ This JSON file is created by mvt-ios' `LocationdClients` module. The module extr
|
||||
### `manifest.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-close:
|
||||
|
||||
This JSON file is created by mvt-ios' `Manifest` module. The module extracts records from the SQLite database *Manifest.db* contained in iTunes backups, and which indexes the locally backed-up files to the original paths on the iOS device.
|
||||
@@ -175,7 +175,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `os_analytics_ad_daily.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `OSAnalyticsADDaily` module. The module extracts records from a plist located *private/var/mobile/Library/Preferences/com.apple.osanalytics.addaily.plist*, which contains a history of data usage by processes running on the system. Besides the network statistics, these records are particularly important because they might show traces of malicious process executions and the relevant timeframe.
|
||||
@@ -187,7 +187,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `datausage.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `Datausage` module. The module extracts records from a SQLite database located */private/var/wireless/Library/Databases/DataUsage.sqlite*, which contains a history of network data usage by processes running on the system. It does not log network traffic through WiFi (the fields `WIFI_IN` and `WIFI_OUT` are always empty), and the `WWAN_IN` and `WWAN_OUT` fields are stored in bytes. Besides the network statistics, these records are particularly important because they might show traces of malicious process executions and the relevant timeframe. In particular, processes which do not have a valid bundle ID might require particular attention.
|
||||
@@ -199,7 +199,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `netusage.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-close:
|
||||
Backup: :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `Netusage` module. The module extracts records from a SQLite database located */private/var/networkd/netusage.sqlite*, which contains a history of data usage by processes running on the system. Besides the network statistics, these records are particularly important because they might show traces of malicious process executions and the relevant timeframe. In particular, processes which do not have a valid bundle ID might require particular attention.
|
||||
@@ -211,7 +211,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `profile_events.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-close:
|
||||
|
||||
This JSON file is created by mvt-ios' `ProfileEvents` module. The module extracts a timeline of configuration profile operations. For example, it should indicate when a new profile was installed from the Settings app, or when one was removed.
|
||||
@@ -221,7 +221,7 @@ This JSON file is created by mvt-ios' `ProfileEvents` module. The module extract
|
||||
### `safari_browser_state.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup (if encrypted): :material-check:
|
||||
Backup (if encrypted): :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `SafariBrowserState` module. The module extracts records from the SQLite databases located at */private/var/mobile/Library/Safari/BrowserState.db* or */private/var/mobile/Containers/Data/Application/\*/Library/Safari/BrowserState.db*, which contain records of opened tabs.
|
||||
@@ -233,7 +233,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `safari_favicon.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-close:
|
||||
Backup: :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `SafariFavicon` module. The module extracts records from the SQLite databases located at */private/var/mobile/Library/Image Cache/Favicons/Favicons.db* or */private/var/mobile/Containers/Data/Application/\*/Library/Image Cache/Favicons/Favicons.db*, which contain mappings of favicons' URLs and the visited URLs which loaded them.
|
||||
@@ -245,7 +245,7 @@ If indicators are provided through the command-line, they are checked against bo
|
||||
### `safari_history.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup (if encrypted): :material-check:
|
||||
Backup (if encrypted): :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `SafariHistory` module. The module extracts records from the SQLite databases located at */private/var/mobile/Library/Safari/History.db* or */private/var/mobile/Containers/Data/Application/\*/Library/Safari/History.db*, which contain a history of URL visits.
|
||||
@@ -257,7 +257,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `shutdown_log.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup (if encrypted): :material-close:
|
||||
Backup (if encrypted): :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `ShutdownLog` module. The module extracts records from the shutdown log located at *private/var/db/diagnostics/shutdown.log*. When shutting down an iPhone, a SIGTERM will be sent to all processes runnning. The `shutdown.log` file will log any process (with its pid and path) that did not shut down after the SIGTERM was sent.
|
||||
@@ -269,7 +269,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `sms.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `SMS` module. The module extracts a list of SMS messages containing HTTP links from the SQLite database located at */private/var/mobile/Library/SMS/sms.db*.
|
||||
@@ -281,7 +281,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `sms_attachments.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `SMSAttachments` module. The module extracts details about attachments sent via SMS or iMessage from the same database used by the `SMS` module. These records might be useful to indicate unique patterns that might be indicative of exploitation attempts leveraging potential vulnerabilities in file format parsers or other forms of file handling by the Messages app.
|
||||
@@ -291,7 +291,7 @@ This JSON file is created by mvt-ios' `SMSAttachments` module. The module extrac
|
||||
### `tcc.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `TCC` module. The module extracts records from a SQLite database located at */private/var/mobile/Library/TCC/TCC.db*, which contains a list of which services such as microphone, camera, or location, apps have been granted or denied access to.
|
||||
@@ -301,7 +301,7 @@ This JSON file is created by mvt-ios' `TCC` module. The module extracts records
|
||||
### `version_history.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-close:
|
||||
Backup: :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `IOSVersionHistory` module. The module extracts records of iOS software updates from analytics plist files located at */private/var/db/analyticsd/Analytics-Journal-\*.ips*.
|
||||
@@ -311,7 +311,7 @@ This JSON file is created by mvt-ios' `IOSVersionHistory` module. The module ext
|
||||
### `webkit_indexeddb.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-close:
|
||||
Backup: :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `WebkitIndexedDB` module. The module extracts a list of file and folder names located at the following path */private/var/mobile/Containers/Data/Application/\*/Library/WebKit/WebsiteData/IndexedDB*, which contains IndexedDB files created by any app installed on the device.
|
||||
@@ -323,7 +323,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `webkit_local_storage.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-close:
|
||||
Backup: :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `WebkitLocalStorage` module. The module extracts a list of file and folder names located at the following path */private/var/mobile/Containers/Data/Application/\*/Library/WebKit/WebsiteData/LocalStorage/*, which contains local storage files created by any app installed on the device.
|
||||
@@ -335,7 +335,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `webkit_resource_load_statistics.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios `WebkitResourceLoadStatistics` module. The module extracts records from available WebKit ResourceLoadStatistics *observations.db* SQLite3 databases. These records should indicate domain names contacted by apps, including a timestamp.
|
||||
@@ -347,7 +347,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `webkit_safari_view_service.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-close:
|
||||
Backup: :material-close:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `WebkitSafariViewService` module. The module extracts a list of file and folder names located at the following path */private/var/mobile/Containers/Data/Application/\*/SystemData/com.apple.SafariViewService/Library/WebKit/WebsiteData/*, which contains files cached by SafariVewService.
|
||||
@@ -359,7 +359,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `webkit_session_resource_log.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `WebkitSessionResourceLog` module. The module extracts records from plist files with the name *full_browsing_session_resourceLog.plist*, which contain records of resources loaded by different domains visited.
|
||||
@@ -371,7 +371,7 @@ If indicators are provided through the command-line, they are checked against th
|
||||
### `whatsapp.json`
|
||||
|
||||
!!! info "Availability"
|
||||
Backup: :material-check:
|
||||
Backup: :material-check:
|
||||
Full filesystem dump: :material-check:
|
||||
|
||||
This JSON file is created by mvt-ios' `WhatsApp` module. The module extracts a list of WhatsApp messages containing HTTP links from the SQLite database located at *private/var/mobile/Containers/Shared/AppGroup/\*/ChatStorage.sqlite*.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
import getpass
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
@@ -11,6 +10,8 @@ import sys
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
|
||||
from rich.prompt import Prompt
|
||||
|
||||
from mvt.android.parsers.backup import (AndroidBackupParsingError,
|
||||
InvalidBackupPassword, parse_ab_header,
|
||||
parse_backup_file)
|
||||
@@ -50,7 +51,7 @@ class CmdAndroidCheckBackup(Command):
|
||||
|
||||
password = None
|
||||
if header["encryption"] != "none":
|
||||
password = getpass.getpass(prompt="Backup Password: ", stream=None)
|
||||
password = Prompt.ask("Enter backup password", password=True)
|
||||
try:
|
||||
tardata = parse_backup_file(data, password=password)
|
||||
except InvalidBackupPassword:
|
||||
|
||||
@@ -44,11 +44,12 @@ class DownloadAPKs(AndroidExtraction):
|
||||
or filter known-goods
|
||||
:param packages: Provided list of packages, typically for JSON checks
|
||||
"""
|
||||
super().__init__(output_folder=output_folder, log=log)
|
||||
super().__init__(log=log)
|
||||
|
||||
self.packages = packages
|
||||
self.all_apks = all_apks
|
||||
self.output_folder_apk = None
|
||||
self.output_folder = output_folder
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, json_path):
|
||||
@@ -114,6 +115,7 @@ class DownloadAPKs(AndroidExtraction):
|
||||
|
||||
m = Packages()
|
||||
m.log = self.log
|
||||
m.serial = self.serial
|
||||
m.run()
|
||||
|
||||
self.packages = m.results
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
import base64
|
||||
import getpass
|
||||
import logging
|
||||
import os
|
||||
import random
|
||||
@@ -19,6 +18,7 @@ from adb_shell.auth.keygen import keygen, write_public_keyfile
|
||||
from adb_shell.auth.sign_pythonrsa import PythonRSASigner
|
||||
from adb_shell.exceptions import (AdbCommandFailureException, DeviceAuthError,
|
||||
UsbDeviceNotFoundError, UsbReadFailedError)
|
||||
from rich.prompt import Prompt
|
||||
from usb1 import USBErrorAccess, USBErrorBusy
|
||||
|
||||
from mvt.android.parsers.backup import (InvalidBackupPassword, parse_ab_header,
|
||||
@@ -270,7 +270,7 @@ class AndroidExtraction(MVTModule):
|
||||
return parse_backup_file(backup_output, password=None)
|
||||
|
||||
for password_retry in range(0, 3):
|
||||
backup_password = getpass.getpass(prompt="Backup password: ", stream=None)
|
||||
backup_password = Prompt.ask("Enter backup password", password=True)
|
||||
try:
|
||||
decrypted_backup_tar = parse_backup_file(backup_output, backup_password)
|
||||
return decrypted_backup_tar
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
import logging
|
||||
import re
|
||||
|
||||
from mvt.android.modules.adb.packages import (DANGEROUS_PERMISSIONS,
|
||||
DANGEROUS_PERMISSIONS_THRESHOLD,
|
||||
ROOT_PACKAGES)
|
||||
|
||||
from .base import BugReportModule
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -41,11 +45,17 @@ class Packages(BugReportModule):
|
||||
return records
|
||||
|
||||
def check_indicators(self) -> None:
|
||||
if not self.indicators:
|
||||
return
|
||||
|
||||
for result in self.results:
|
||||
ioc = self.indicators.check_app_id(result["package_name"])
|
||||
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)
|
||||
@@ -165,4 +175,14 @@ class Packages(BugReportModule):
|
||||
|
||||
self.results = self.parse_packages_list("\n".join(lines))
|
||||
|
||||
for result in self.results:
|
||||
dangerous_permissions_count = 0
|
||||
for perm in result["requested_permissions"]:
|
||||
if perm 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))
|
||||
|
||||
@@ -136,6 +136,9 @@ class Command(object):
|
||||
def module_init(self, module: Callable) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def finish(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def run(self) -> None:
|
||||
self._create_storage()
|
||||
self._add_log_file_handler(self.log)
|
||||
@@ -176,3 +179,8 @@ class Command(object):
|
||||
|
||||
self._store_timeline()
|
||||
self._store_info()
|
||||
|
||||
try:
|
||||
self.finish()
|
||||
except NotImplementedError:
|
||||
pass
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import datetime
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
@@ -119,3 +120,14 @@ def keys_bytes_to_string(obj) -> str:
|
||||
new_obj[key] = value
|
||||
|
||||
return new_obj
|
||||
|
||||
|
||||
def secure_delete(file_path, rounds=10):
|
||||
file_size = os.path.getsize(file_path)
|
||||
|
||||
with open(file_path, "br+", buffering=-1) as handle:
|
||||
for i in range(rounds):
|
||||
handle.seek(0)
|
||||
handle.write(os.urandom(file_size))
|
||||
|
||||
os.remove(file_path)
|
||||
|
||||
112
mvt/ios/cli.py
112
mvt/ios/cli.py
@@ -8,7 +8,8 @@ import os
|
||||
|
||||
import click
|
||||
from rich.logging import RichHandler
|
||||
from rich.prompt import Prompt
|
||||
from rich.prompt import Confirm, Prompt
|
||||
from simple_term_menu import TerminalMenu
|
||||
|
||||
from mvt.common.cmd_check_iocs import CmdCheckIOCS
|
||||
from mvt.common.help import (HELP_MSG_FAST, HELP_MSG_IOC,
|
||||
@@ -22,6 +23,7 @@ from .cmd_check_backup import CmdIOSCheckBackup
|
||||
from .cmd_check_fs import CmdIOSCheckFS
|
||||
from .cmd_check_usb import CmdIOSCheckUSB
|
||||
from .decrypt import DecryptBackup
|
||||
from .lockdown import Lockdown
|
||||
from .modules.backup import BACKUP_MODULES
|
||||
from .modules.fs import FS_MODULES
|
||||
from .modules.mixed import MIXED_MODULES
|
||||
@@ -188,6 +190,83 @@ def check_fs(ctx, iocs, output, fast, list_modules, module, dump_path):
|
||||
len(cmd.timeline_detected))
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Command: check-usb
|
||||
#==============================================================================
|
||||
@cli.command("check-usb", help="Extract artifacts from a live iPhone through USB")
|
||||
@click.option("--serial", "-s", type=str, help=HELP_MSG_SERIAL)
|
||||
@click.option("--iocs", "-i", type=click.Path(exists=True), multiple=True,
|
||||
default=[], help=HELP_MSG_IOC)
|
||||
@click.option("--output", "-o", type=click.Path(exists=False), help=HELP_MSG_OUTPUT)
|
||||
@click.option("--fast", "-f", is_flag=True, help=HELP_MSG_FAST)
|
||||
@click.option("--list-modules", "-l", is_flag=True, help=HELP_MSG_LIST_MODULES)
|
||||
@click.option("--module", "-m", help=HELP_MSG_MODULE)
|
||||
@click.pass_context
|
||||
def check_usb(ctx, serial, iocs, output, fast, list_modules, module):
|
||||
cmd = CmdIOSCheckUSB(results_path=output, ioc_files=iocs,
|
||||
module_name=module, fast_mode=fast,
|
||||
serial=serial)
|
||||
|
||||
if list_modules:
|
||||
cmd.list_modules()
|
||||
return
|
||||
|
||||
log.info("Checking iPhone through USB, this may take a while")
|
||||
cmd.run()
|
||||
|
||||
if len(cmd.timeline_detected) > 0:
|
||||
log.warning("The analysis of the data produced %d detections!",
|
||||
len(cmd.timeline_detected))
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Command: clear-certs
|
||||
#==============================================================================
|
||||
@cli.command("clear-certs", help="Clear iOS lockdown certificates")
|
||||
@click.pass_context
|
||||
def clear_certs(ctx):
|
||||
lock = Lockdown()
|
||||
certs = lock.find_certs()
|
||||
|
||||
if not certs:
|
||||
log.info("No iOS lockdown certificates found")
|
||||
return
|
||||
|
||||
choices = []
|
||||
for cert in certs:
|
||||
choices.append(os.path.basename(cert))
|
||||
log.info("Found lockdown certificate at %s", cert)
|
||||
|
||||
choices.append("Cancel")
|
||||
|
||||
terminal_menu = TerminalMenu(
|
||||
choices,
|
||||
title="Select which certificates to delete:",
|
||||
multi_select=True,
|
||||
show_multi_select_hint=True,
|
||||
)
|
||||
terminal_menu.show()
|
||||
|
||||
if "Cancel" in terminal_menu.chosen_menu_entries:
|
||||
log.info("Cancel, not proceeding")
|
||||
return
|
||||
|
||||
confirmed = Confirm.ask(f"You have selected {', '.join(terminal_menu.chosen_menu_entries)}. "
|
||||
"Are you sure you want to proceed deleting them?")
|
||||
if not confirmed:
|
||||
log.info("Not proceeding")
|
||||
return
|
||||
|
||||
for choice in terminal_menu.chosen_menu_entries:
|
||||
try:
|
||||
lock.delete_cert(choice)
|
||||
except PermissionError:
|
||||
log.error("Not enough permissions to delete certificate at \"%s\": "
|
||||
"try launching this command with sudo", choice)
|
||||
else:
|
||||
log.info("Deleted lockdown certificate \"%s\"", choice)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Command: check-iocs
|
||||
#==============================================================================
|
||||
@@ -216,34 +295,3 @@ def check_iocs(ctx, iocs, list_modules, module, folder):
|
||||
def download_iocs():
|
||||
ioc_updates = IndicatorsUpdates()
|
||||
ioc_updates.update()
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Command: check-usb
|
||||
#==============================================================================
|
||||
@cli.command("check-usb", help="Extract artifacts from a live iPhone through USB / lockdown")
|
||||
@click.option("--serial", "-s", type=str, help=HELP_MSG_SERIAL)
|
||||
@click.option("--iocs", "-i", type=click.Path(exists=True), multiple=True,
|
||||
default=[], help=HELP_MSG_IOC)
|
||||
@click.option("--output", "-o", type=click.Path(exists=False), help=HELP_MSG_OUTPUT)
|
||||
@click.option("--fast", "-f", is_flag=True, help=HELP_MSG_FAST)
|
||||
@click.option("--list-modules", "-l", is_flag=True, help=HELP_MSG_LIST_MODULES)
|
||||
@click.option("--module", "-m", help=HELP_MSG_MODULE)
|
||||
# TODO: serial
|
||||
# @click.argument("BACKUP_PATH", type=click.Path(exists=True))
|
||||
@click.pass_context
|
||||
def check_usb(ctx, serial, iocs, output, fast, list_modules, module):
|
||||
cmd = CmdIOSCheckUSB(results_path=output, ioc_files=iocs,
|
||||
module_name=module, fast_mode=fast,
|
||||
serial=serial)
|
||||
|
||||
if list_modules:
|
||||
cmd.list_modules()
|
||||
return
|
||||
|
||||
log.info("Checking iPhone through USB, this may take a while")
|
||||
cmd.run()
|
||||
|
||||
if len(cmd.timeline_detected) > 0:
|
||||
log.warning("The analysis of the data produced %d detections!",
|
||||
len(cmd.timeline_detected))
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from pymobiledevice3.exceptions import ConnectionFailedError
|
||||
from pymobiledevice3.exceptions import (ConnectionFailedError,
|
||||
FatalPairingError, NotTrustedError)
|
||||
from pymobiledevice3.lockdown import LockdownClient
|
||||
|
||||
from mvt.common.command import Command
|
||||
@@ -35,11 +36,11 @@ class CmdIOSCheckUSB(Command):
|
||||
self.lockdown = LockdownClient(udid=self.serial)
|
||||
else:
|
||||
self.lockdown = LockdownClient()
|
||||
except ConnectionRefusedError:
|
||||
log.error("Unable to connect to the device over USB. Try to unplug, plug the device and start again.")
|
||||
except NotTrustedError:
|
||||
log.error("Trust this computer from the prompt appearing on the iOS device and try again")
|
||||
sys.exit(-1)
|
||||
except ConnectionFailedError:
|
||||
log.error("Unable to connect to the device %s", self.serial)
|
||||
except (ConnectionRefusedError, ConnectionFailedError, FatalPairingError):
|
||||
log.error("Unable to connect to the device over USB: try to unplug, plug the device and start again")
|
||||
sys.exit(-1)
|
||||
|
||||
def module_init(self, module):
|
||||
|
||||
58
mvt/ios/lockdown.py
Normal file
58
mvt/ios/lockdown.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# 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 platform
|
||||
|
||||
from mvt.common.utils import secure_delete
|
||||
|
||||
|
||||
class Lockdown:
|
||||
|
||||
def __init__(self, uuids: list = []) -> None:
|
||||
self.uuids = uuids
|
||||
self.lockdown_folder = self._get_lockdown_folder()
|
||||
|
||||
@staticmethod
|
||||
def _get_lockdown_folder():
|
||||
system = platform.system()
|
||||
if system == "Linux":
|
||||
return "/var/lib/lockdown/"
|
||||
elif system == "Darwin":
|
||||
return "/var/db/lockdown/"
|
||||
elif system == "Windows":
|
||||
return os.path.join(os.environ.get("ALLUSERSPROFILE", ""),
|
||||
"Apple", "Lockdown")
|
||||
|
||||
@staticmethod
|
||||
def _get_pymobiledevice_folder():
|
||||
return os.path.expanduser("~/.pymobiledevice3")
|
||||
|
||||
def delete_cert(self, cert_file) -> None:
|
||||
if not self.lockdown_folder:
|
||||
return
|
||||
|
||||
cert_path = os.path.join(self.lockdown_folder, cert_file)
|
||||
if not os.path.exists(cert_path):
|
||||
return
|
||||
|
||||
secure_delete(cert_path)
|
||||
|
||||
def find_certs(self) -> list:
|
||||
if not self.lockdown_folder or not os.path.exists(self.lockdown_folder):
|
||||
return []
|
||||
|
||||
lockdown_certs = []
|
||||
for file_name in os.listdir(self.lockdown_folder):
|
||||
if not file_name.endswith(".plist"):
|
||||
continue
|
||||
|
||||
if file_name == "SystemConfiguration.plist":
|
||||
continue
|
||||
|
||||
file_path = os.path.join(self.lockdown_folder, file_name)
|
||||
lockdown_certs.append(file_path)
|
||||
|
||||
return sorted(lockdown_certs)
|
||||
@@ -13,6 +13,7 @@ from .base import IOSUSBExtraction
|
||||
|
||||
class Applications(IOSUSBExtraction):
|
||||
"""This class extracts all applications installed on the phone"""
|
||||
|
||||
def __init__(self, file_path: str = None, target_path: str = None,
|
||||
results_path: str = None, fast_mode: bool = False,
|
||||
log: logging.Logger = None, results: list = []) -> None:
|
||||
@@ -32,13 +33,14 @@ class Applications(IOSUSBExtraction):
|
||||
|
||||
def run(self) -> None:
|
||||
user_apps = InstallationProxyService(lockdown=self.lockdown).get_apps("User")
|
||||
for u in user_apps:
|
||||
u["type"] = "user"
|
||||
for user_app in user_apps:
|
||||
user_app["type"] = "user"
|
||||
|
||||
system_apps = InstallationProxyService(lockdown=self.lockdown).get_apps("System")
|
||||
for s in system_apps:
|
||||
s["type"] = "system"
|
||||
for system_app in system_apps:
|
||||
system_app["type"] = "system"
|
||||
|
||||
self.results = user_apps + system_apps
|
||||
|
||||
self.log.info("{} applications identified on the phone".format(len(self.results)))
|
||||
self.log.info("Identified %d applications installed on the device",
|
||||
len(self.results))
|
||||
|
||||
@@ -13,6 +13,7 @@ from .base import IOSUSBExtraction
|
||||
|
||||
class DeviceInfo(IOSUSBExtraction):
|
||||
"""This class extracts all processes running on the phone."""
|
||||
|
||||
def __init__(self, file_path: str = None, target_path: str = None,
|
||||
results_path: str = None, fast_mode: bool = False,
|
||||
log: logging.Logger = None, results: list = []) -> None:
|
||||
@@ -23,7 +24,6 @@ class DeviceInfo(IOSUSBExtraction):
|
||||
def run(self) -> None:
|
||||
self.results = self.lockdown.all_values
|
||||
|
||||
# Base64 encoding of bytes
|
||||
for entry in self.results:
|
||||
if isinstance(self.results[entry], bytes):
|
||||
self.results[entry] = base64.b64encode(self.results[entry])
|
||||
|
||||
@@ -12,6 +12,7 @@ from .base import IOSUSBExtraction
|
||||
|
||||
class Processes(IOSUSBExtraction):
|
||||
"""This class extracts all processes running on the phone."""
|
||||
|
||||
def __init__(self, file_path: str = None, target_path: str = None,
|
||||
results_path: str = None, fast_mode: bool = False,
|
||||
log: logging.Logger = None, results: list = []) -> None:
|
||||
@@ -30,11 +31,12 @@ class Processes(IOSUSBExtraction):
|
||||
self.detected.append(result)
|
||||
|
||||
def run(self) -> None:
|
||||
processes = OsTraceService(lockdown=self.lockdown).get_pid_list().get('Payload')
|
||||
for p in processes:
|
||||
processes = OsTraceService(lockdown=self.lockdown).get_pid_list().get("Payload")
|
||||
for pid in processes:
|
||||
self.results.append({
|
||||
"pid": p,
|
||||
"name": processes[p]["ProcessName"]
|
||||
"pid": pid,
|
||||
"name": processes[pid]["ProcessName"]
|
||||
})
|
||||
|
||||
self.log.info("{} running processes identified on the phone".format(len(self.results)))
|
||||
self.log.info("Identified %d processes running on the device",
|
||||
len(self.results))
|
||||
|
||||
Reference in New Issue
Block a user