Compare commits

..

1 Commits

Author SHA1 Message Date
Donncha Ó Cearbhaill
ccca58de63 Add dumpsys parser for 'ip link'/network interfaces 2023-05-20 21:22:18 +01:00
17 changed files with 375 additions and 1386 deletions

View File

@@ -1,80 +0,0 @@
"""
Python script to download the Apple RSS feed and parse it.
"""
import os
import json
import urllib.request
from xml.dom.minidom import parseString
from packaging import version
def download_apple_rss(feed_url):
with urllib.request.urlopen(feed_url) as f:
rss_feed = f.read().decode('utf-8')
print("Downloaded RSS feed from Apple.")
return rss_feed
def parse_latest_ios_versions(rss_feed_text):
latest_ios_versions = []
parsed_feed = parseString(rss_feed_text)
for item in parsed_feed.getElementsByTagName("item"):
title = item.getElementsByTagName("title")[0].firstChild.data
if not title.startswith("iOS"):
continue
import re
build_match = re.match(r"iOS (?P<version>[\d\.]+) (?P<beta>beta )?(\S*)?\((?P<build>.*)\)", title)
if not build_match:
print("Could not parse iOS build:", title)
continue
release_info = build_match.groupdict()
if release_info["beta"]:
print("Skipping beta release:", title)
continue
release_info.pop("beta")
latest_ios_versions.append(release_info)
return latest_ios_versions
def update_mvt(mvt_checkout_path, latest_ios_versions):
version_path = os.path.join(mvt_checkout_path, "mvt/ios/data/ios_versions.json")
with open(version_path, "r") as version_file:
current_versions = json.load(version_file)
new_entry_count = 0
for new_version in latest_ios_versions:
for current_version in current_versions:
if new_version["build"] == current_version["build"]:
break
else:
# New version that does not exist in current data
current_versions.append(new_version)
new_entry_count += 1
if not new_entry_count:
print("No new iOS versions found.")
else:
print("Found {} new iOS versions.".format(new_entry_count))
new_version_list = sorted(current_versions, key=lambda x: version.Version(x["version"]))
with open(version_path, "w") as version_file:
json.dump(new_version_list, version_file, indent=4)
def main():
print("Downloading RSS feed...")
mvt_checkout_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../"))
rss_feed = download_apple_rss("https://developer.apple.com/news/releases/rss/releases.rss")
latest_ios_version = parse_latest_ios_versions(rss_feed)
update_mvt(mvt_checkout_path, latest_ios_version)
if __name__ == "__main__":
main()

View File

@@ -1,29 +0,0 @@
name: Update iOS releases and version numbers
run-name: ${{ github.actor }} is finding the latest iOS release version and build numbers
on:
workflow_dispatch:
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '0 */6 * * *'
jobs:
update-ios-version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- name: Run script to fetch latest iOS releases from Apple RSS feed.
run: python3 .github/workflows/scripts/update-ios-releases.py
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
title: '[auto] Update iOS releases and versions'
commit-message: Add new iOS versions and build numbers
branch: auto/add-new-ios-releases
body: |
This is an automated pull request to update the iOS releases and version numbers.
add-paths: |
*.json
labels: |
automated pr

View File

@@ -12,6 +12,8 @@ from .dbinfo import DBInfo
from .getprop import Getprop
from .packages import Packages
from .receivers import Receivers
from .network_interfaces import NetworkInterfaces
BUGREPORT_MODULES = [Accessibility, Activities, Appops, BatteryDaily,
BatteryHistory, DBInfo, Getprop, Packages, Receivers]
BatteryHistory, DBInfo, Getprop, Packages, Receivers,
NetworkInterfaces]

View File

@@ -0,0 +1,58 @@
# Mobile Verification Toolkit (MVT)
# Copyright (c) 2021-2023 Claudio Guarnieri.
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
import logging
from typing import Optional
from mvt.android.parsers import parse_dumpsys_network_interfaces
from .base import BugReportModule
class NetworkInterfaces(BugReportModule):
"""This module extracts network interfaces from 'ip link' command."""
def __init__(
self,
file_path: Optional[str] = None,
target_path: Optional[str] = None,
results_path: Optional[str] = None,
fast_mode: Optional[bool] = False,
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, fast_mode=fast_mode,
log=log, results=results)
self.results = {} if not results else results
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
lines = []
in_getprop = False
for line in content.decode(errors="ignore").splitlines():
if line.strip().startswith("------ NETWORK INTERFACES"):
in_getprop = True
continue
if not in_getprop:
continue
if line.strip().startswith("------"):
break
lines.append(line)
self.results = parse_dumpsys_network_interfaces("\n".join(lines))
self.log.info("Extracted information about %d Android network interfaces",
len(self.results))

View File

@@ -7,5 +7,7 @@ from .dumpsys import (parse_dumpsys_accessibility,
parse_dumpsys_activity_resolver_table,
parse_dumpsys_appops, parse_dumpsys_battery_daily,
parse_dumpsys_battery_history, parse_dumpsys_dbinfo,
parse_dumpsys_receiver_resolver_table)
parse_dumpsys_receiver_resolver_table,
parse_dumpsys_network_interfaces,
)
from .getprop import parse_getprop

View File

@@ -519,3 +519,39 @@ def parse_dumpsys_packages(output: str) -> List[Dict[str, Any]]:
results.append(package)
return results
def parse_dumpsys_network_interfaces(output: str) -> List[Dict[str, str]]:
"""
Parse network interfaces (output of the 'ip link' command)
"""
results = []
interface_rxp = re.compile(r"(?P<if_number>\d+): (?P<if_name>[\S\d]+): (?P<if_options>\<.*)")
mac_or_ip_line_rxp = re.compile(r"\W+ (?P<link_type>[\S]+) (?P<mac_or_ip_address>[a-f0-9\:\.\/]+) (.*)")
interface = None
for line in output.splitlines():
interface_match = re.match(interface_rxp, line)
if interface_match:
interface = {
"interface_number": interface_match.group("if_number"),
"name": interface_match.group("if_name"),
"options": interface_match.group("if_options"),
}
continue
elif interface:
mac_line_match = re.match(mac_or_ip_line_rxp, line)
mac_or_ip_address = mac_line_match.group("mac_or_ip_address")
if len(mac_or_ip_address) == 17:
interface["mac_address"] = mac_or_ip_address
else:
interface["address"] = mac_or_ip_address
interface["link_type"] = mac_line_match.group("link_type")
interface["link_line"] = line
results.append(interface)
interface = None
return results

View File

@@ -7,7 +7,6 @@ import logging
import os
from typing import Optional
from mvt.common.module import PostAnalysisModule
from mvt.common.command import Command
log = logging.getLogger(__name__)
@@ -33,7 +32,6 @@ class CmdCheckIOCS(Command):
def run(self) -> None:
assert self.target_path is not None
all_modules = []
post_modules = []
for entry in self.modules:
if entry not in all_modules:
all_modules.append(entry)
@@ -45,24 +43,18 @@ class CmdCheckIOCS(Command):
name_only, _ = os.path.splitext(file_name)
file_path = os.path.join(self.target_path, file_name)
for module in all_modules:
if self.module_name and module.__name__ != self.module_name:
for iocs_module in all_modules:
if self.module_name and iocs_module.__name__ != self.module_name:
continue
# Handle post-analysis modules at the end
if issubclass(module, PostAnalysisModule) and module not in post_modules:
post_modules.append(module)
continue
# Skip if the current result file does not match the module name
if module().get_slug() != name_only:
if iocs_module().get_slug() != name_only:
continue
log.info("Loading results from \"%s\" with module %s",
file_name, module.__name__)
file_name, iocs_module.__name__)
m = module.from_json(file_path,
log=logging.getLogger(module.__module__))
m = iocs_module.from_json(file_path,
log=logging.getLogger(iocs_module.__module__))
if self.iocs.total_ioc_count > 0:
m.indicators = self.iocs
m.indicators.log = m.log
@@ -74,13 +66,6 @@ class CmdCheckIOCS(Command):
else:
total_detections += len(m.detected)
# Run post-analysis modules at end
for post_module in post_modules:
m = post_module.from_results(self.target_path, log=log)
m.run()
total_detections += len(m.detected)
if total_detections > 0:
log.warning("The check of the results produced %d detections!",
total_detections)

View File

@@ -33,7 +33,6 @@ class Command:
) -> None:
self.name = ""
self.modules = []
self.modules_post = []
self.target_path = target_path
self.results_path = results_path
@@ -140,7 +139,7 @@ class Command:
def list_modules(self) -> None:
self.log.info("Following is the list of available %s modules:",
self.name)
for module in (self.modules + self.modules_post):
for module in self.modules:
self.log.info(" - %s", module.__name__)
def init(self) -> None:

View File

@@ -7,7 +7,6 @@ import csv
import logging
import os
import re
import glob
from typing import Any, Dict, List, Optional, Union
import simplejson as json
@@ -226,51 +225,3 @@ def save_timeline(timeline: list, timeline_path: str) -> None:
event.get("event"),
event.get("data"),
])
class PostAnalysisModule(MVTModule):
"""
Base module for implementing post-processing rules against the output of
multiple MVT modules
"""
@classmethod
def from_results(cls, results_path: str, log: logging.Logger):
results = cls.load_results(results_path, log=log)
return cls(results=results, log=log)
@classmethod
def load_results(cls, results_path: str, log: logging.Logger):
"""Load the results from a directory of json file."""
# TODO: Move this to run once before loading all post-processing modules
module_results = {}
for json_path in glob.glob(os.path.join(results_path, "*.json")):
module_name, _ = os.path.splitext(os.path.basename(json_path))
with open(json_path, "r", encoding="utf-8") as handle:
try:
module_results[module_name] = json.load(handle)
except Exception as exc:
log.error("Unable to load results from file %s: %s",
json_path, exc)
if not module_results:
log.error("Did not find any MVT results at %s", results_path)
return module_results
def load_timeline(self):
"""Load timeline from CSV file"""
timeline = []
timeline_path = os.path.join(self.results_path, "timeline.csv")
with open(timeline_path, "r", encoding="utf-8") as handle:
csvinput = csv.reader(handle, delimiter=",", quotechar="\"",
quoting=csv.QUOTE_ALL, escapechar='\\')
for row in csvinput:
if row[0] == "UTC Timestamp":
continue
timeline.append({
"timestamp": row[0],
"module": row[1],
"event": row[2],
"data": row[3],
})
return timeline

View File

@@ -26,7 +26,6 @@ from .decrypt import DecryptBackup
from .modules.backup import BACKUP_MODULES
from .modules.fs import FS_MODULES
from .modules.mixed import MIXED_MODULES
from .modules.post_analysis import POST_ANALYSIS_MODULES
init_logging()
log = logging.getLogger("mvt")
@@ -235,7 +234,7 @@ def check_fs(ctx, iocs, output, fast, list_modules, module, hashes, verbose, dum
@click.pass_context
def check_iocs(ctx, iocs, list_modules, module, folder):
cmd = CmdCheckIOCS(target_path=folder, ioc_files=iocs, module_name=module)
cmd.modules = BACKUP_MODULES + FS_MODULES + MIXED_MODULES + POST_ANALYSIS_MODULES
cmd.modules = BACKUP_MODULES + FS_MODULES + MIXED_MODULES
if list_modules:
cmd.list_modules()

View File

@@ -1,166 +0,0 @@
[
{
"identifier": "iPhone4,1",
"description": "iPhone 4S"
},
{
"identifier": "iPhone5,1",
"description": "iPhone 5"
},
{
"identifier": "iPhone5,2",
"description": "iPhone 5"
},
{
"identifier": "iPhone5,3",
"description": "iPhone 5c"
},
{
"identifier": "iPhone5,4",
"description": "iPhone 5c"
},
{
"identifier": "iPhone6,1",
"description": "iPhone 5s"
},
{
"identifier": "iPhone6,2",
"description": "iPhone 5s"
},
{
"identifier": "iPhone7,1",
"description": "iPhone 6 Plus"
},
{
"identifier": "iPhone7,2",
"description": "iPhone 6"
},
{
"identifier": "iPhone8,1",
"description": "iPhone 6s"
},
{
"identifier": "iPhone8,2",
"description": "iPhone 6s Plus"
},
{
"identifier": "iPhone8,4",
"description": "iPhone SE (1st generation)"
},
{
"identifier": "iPhone9,1",
"description": "iPhone 7"
},
{
"identifier": "iPhone9,2",
"description": "iPhone 7 Plus"
},
{
"identifier": "iPhone9,3",
"description": "iPhone 7"
},
{
"identifier": "iPhone9,4",
"description": "iPhone 7 Plus"
},
{
"identifier": "iPhone10,1",
"description": "iPhone 8"
},
{
"identifier": "iPhone10,2",
"description": "iPhone 8 Plus"
},
{
"identifier": "iPhone10,3",
"description": "iPhone X"
},
{
"identifier": "iPhone10,4",
"description": "iPhone 8"
},
{
"identifier": "iPhone10,5",
"description": "iPhone 8 Plus"
},
{
"identifier": "iPhone10,6",
"description": "iPhone X"
},
{
"identifier": "iPhone11,2",
"description": "iPhone XS"
},
{
"identifier": "iPhone11,4",
"description": "iPhone XS Max"
},
{
"identifier": "iPhone11,6",
"description": "iPhone XS Max"
},
{
"identifier": "iPhone11,8",
"description": "iPhone XR"
},
{
"identifier": "iPhone12,1",
"description": "iPhone 11"
},
{
"identifier": "iPhone12,3",
"description": "iPhone 11 Pro"
},
{
"identifier": "iPhone12,5",
"description": "iPhone 11 Pro Max"
},
{
"identifier": "iPhone12,8",
"description": "iPhone SE (2nd generation)"
},
{
"identifier": "iPhone13,1",
"description": "iPhone 12 mini"
},
{
"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"
},
{
"identifier": "iPhone14,8",
"decription": "iPhone 14 Plus"
},
{
"identifier": "iPhone15,2",
"description": "iPhone 14 Pro"
},
{
"identifier": "iPhone15,3",
"description": "iPhone 14 Pro Max"
}
]

View File

@@ -1,923 +0,0 @@
[
{
"build": "1A543a",
"version": "1.0"
},
{
"build": "1C25",
"version": "1.0.1"
},
{
"build": "1C28",
"version": "1.0.2"
},
{
"build": "3A109a",
"version": "1.1.1"
},
{
"build": "3B48b",
"version": "1.1.2"
},
{
"build": "4A93",
"version": "1.1.3"
},
{
"build": "4A102",
"version": "1.1.4"
},
{
"build": "5A347",
"version": "2.0"
},
{
"build": "5B108",
"version": "2.0.1"
},
{
"build": "5C1",
"version": "2.0.2"
},
{
"build": "5F136",
"version": "2.1"
},
{
"build": "5G77",
"version": "2.2"
},
{
"build": "5H11",
"version": "2.2.1"
},
{
"build": "7A341",
"version": "3.0"
},
{
"build": "7A400",
"version": "3.0.1"
},
{
"build": "7C144",
"version": "3.1"
},
{
"build": "7D11",
"version": "3.1.2"
},
{
"build": "7E18",
"version": "3.1.3"
},
{
"build": "8A293",
"version": "4.0"
},
{
"build": "8A306",
"version": "4.0.1"
},
{
"build": "8B117",
"version": "4.1"
},
{
"build": "8C148",
"version": "4.2"
},
{
"build": "8C148a",
"version": "4.2.1"
},
{
"build": "8C148",
"version": "4.2.1"
},
{
"build": "8E401",
"version": "4.2.8"
},
{
"build": "8E501",
"version": "4.2.9"
},
{
"build": "8E600",
"version": "4.2.10"
},
{
"build": "8F190",
"version": "4.3"
},
{
"build": "8J2",
"version": "4.3.3"
},
{
"build": "8K2",
"version": "4.3.4"
},
{
"build": "8L1",
"version": "4.3.5"
},
{
"build": "9A334",
"version": "5.0"
},
{
"build": "9A405",
"version": "5.0.1"
},
{
"build": "9A406",
"version": "5.0.1"
},
{
"build": "9B176",
"version": "5.1"
},
{
"build": "9B179",
"version": "5.1"
},
{
"build": "9B206",
"version": "5.1.1"
},
{
"build": "9B208",
"version": "5.1.1"
},
{
"build": "10A403",
"version": "6.0"
},
{
"build": "10A405",
"version": "6.0"
},
{
"build": "10A523",
"version": "6.0.1"
},
{
"build": "10A525",
"version": "6.0.1"
},
{
"build": "10A551",
"version": "6.0.2"
},
{
"build": "10B141",
"version": "6.1"
},
{
"build": "10B144",
"version": "6.1"
},
{
"build": "10B142",
"version": "6.1"
},
{
"build": "10B143",
"version": "6.1"
},
{
"build": "10B145",
"version": "6.1.1"
},
{
"build": "10B146",
"version": "6.1.2"
},
{
"build": "10B329",
"version": "6.1.3"
},
{
"build": "10B350",
"version": "6.1.4"
},
{
"build": "10B500",
"version": "6.1.6"
},
{
"build": "11B511",
"version": "7.0.3"
},
{
"build": "11B554a",
"version": "7.0.4"
},
{
"build": "11B601",
"version": "7.0.5"
},
{
"build": "11B651",
"version": "7.0.6"
},
{
"build": "11D169",
"version": "7.1"
},
{
"build": "11D167",
"version": "7.1"
},
{
"build": "11D201",
"version": "7.1.1"
},
{
"build": "11D257",
"version": "7.1.2"
},
{
"build": "12A365",
"version": "8.0"
},
{
"build": "12A366",
"version": "8.0"
},
{
"build": "12A402",
"version": "8.0.1"
},
{
"build": "12A405",
"version": "8.0.2"
},
{
"build": "12B411",
"version": "8.1"
},
{
"build": "12B435",
"version": "8.1.1"
},
{
"build": "12B436",
"version": "8.1.1"
},
{
"build": "12B440",
"version": "8.1.2"
},
{
"build": "12B466",
"version": "8.1.3"
},
{
"build": "12D508",
"version": "8.2"
},
{
"build": "12F70",
"version": "8.3"
},
{
"build": "12H143",
"version": "8.4"
},
{
"build": "12H321",
"version": "8.4.1"
},
{
"build": "13A344",
"version": "9.0"
},
{
"build": "13A342",
"version": "9.0"
},
{
"build": "13A343",
"version": "9.0"
},
{
"build": "13A404",
"version": "9.0.1"
},
{
"build": "13A405",
"version": "9.0.1"
},
{
"build": "13A452",
"version": "9.0.2"
},
{
"build": "13B143",
"version": "9.1"
},
{
"build": "13C75",
"version": "9.2"
},
{
"build": "13D15",
"version": "9.2.1"
},
{
"build": "13D20",
"version": "9.2.1"
},
{
"build": "13E237",
"version": "9.3"
},
{
"build": "13E233",
"version": "9.3"
},
{
"build": "13E234",
"version": "9.3"
},
{
"build": "13E238",
"version": "9.3.1"
},
{
"build": "13F69",
"version": "9.3.2"
},
{
"build": "13G34",
"version": "9.3.3"
},
{
"build": "13G35",
"version": "9.3.4"
},
{
"build": "13G36",
"version": "9.3.5"
},
{
"build": "13G37",
"version": "9.3.6"
},
{
"build": "14A403",
"version": "10.0.1"
},
{
"build": "14A456",
"version": "10.0.2"
},
{
"build": "14A551",
"version": "10.0.3"
},
{
"build": "14B72",
"version": "10.1"
},
{
"build": "14B72c",
"version": "10.1"
},
{
"build": "14B150",
"version": "10.1.1"
},
{
"build": "14B100",
"version": "10.1.1"
},
{
"build": "14C92",
"version": "10.2"
},
{
"build": "14D27",
"version": "10.2.1"
},
{
"build": "14E277",
"version": "10.3"
},
{
"build": "14E304",
"version": "10.3.1"
},
{
"build": "14F89",
"version": "10.3.2"
},
{
"build": "14G60",
"version": "10.3.3"
},
{
"build": "14G61",
"version": "10.3.4"
},
{
"build": "15A372",
"version": "11.0"
},
{
"build": "15A402",
"version": "11.0.1"
},
{
"version": "11.0.1",
"build": "15A403"
},
{
"build": "15A421",
"version": "11.0.2"
},
{
"build": "15A432",
"version": "11.0.3"
},
{
"build": "15B93",
"version": "11.1"
},
{
"build": "15B150",
"version": "11.1.1"
},
{
"build": "15B202",
"version": "11.1.2"
},
{
"build": "15C114",
"version": "11.2"
},
{
"build": "15C153",
"version": "11.2.1"
},
{
"build": "15C202",
"version": "11.2.2"
},
{
"build": "15D60",
"version": "11.2.5"
},
{
"build": "15D100",
"version": "11.2.6"
},
{
"build": "15E216",
"version": "11.3"
},
{
"build": "15E302",
"version": "11.3.1"
},
{
"build": "15F79",
"version": "11.4"
},
{
"build": "15G77",
"version": "11.4.1"
},
{
"build": "16A366",
"version": "12.0"
},
{
"build": "16A367",
"version": "12.0"
},
{
"build": "16A404",
"version": "12.0.1"
},
{
"build": "16A405",
"version": "12.0.1"
},
{
"build": "16B92",
"version": "12.1"
},
{
"build": "16B94",
"version": "12.1"
},
{
"build": "16B93",
"version": "12.1"
},
{
"build": "16C50",
"version": "12.1.1"
},
{
"build": "16C104",
"version": "12.1.2"
},
{
"build": "16C101",
"version": "12.1.2"
},
{
"build": "16D39",
"version": "12.1.3"
},
{
"build": "16D40",
"version": "12.1.3"
},
{
"build": "16D57",
"version": "12.1.4"
},
{
"build": "16E227",
"version": "12.2"
},
{
"build": "16F156",
"version": "12.3"
},
{
"build": "16F203",
"version": "12.3.1"
},
{
"build": "16F250",
"version": "12.3.2"
},
{
"build": "16G77",
"version": "12.4"
},
{
"build": "16G102",
"version": "12.4.1"
},
{
"build": "16G114",
"version": "12.4.2"
},
{
"build": "16G130",
"version": "12.4.3"
},
{
"build": "16G140",
"version": "12.4.4"
},
{
"build": "16G161",
"version": "12.4.5"
},
{
"build": "16G183",
"version": "12.4.6"
},
{
"build": "16G192",
"version": "12.4.7"
},
{
"build": "16G201",
"version": "12.4.8"
},
{
"build": "16H5",
"version": "12.4.9"
},
{
"build": "16H20",
"version": "12.5"
},
{
"build": "16H22",
"version": "12.5.1"
},
{
"build": "16H30",
"version": "12.5.2"
},
{
"build": "16H41",
"version": "12.5.3"
},
{
"build": "16H50",
"version": "12.5.4"
},
{
"build": "16H62",
"version": "12.5.5"
},
{
"build": "16H71",
"version": "12.5.6"
},
{
"build": "16H81",
"version": "12.5.7"
},
{
"build": "17A577",
"version": "13.0"
},
{
"build": "17A844",
"version": "13.1"
},
{
"build": "17A854",
"version": "13.1.1"
},
{
"build": "17A860",
"version": "13.1.2"
},
{
"build": "17A861",
"version": "13.1.2"
},
{
"build": "17A878",
"version": "13.1.3"
},
{
"build": "17B84",
"version": "13.2"
},
{
"build": "17B102",
"version": "13.2.2"
},
{
"build": "17B111",
"version": "13.2.3"
},
{
"build": "17C54",
"version": "13.3"
},
{
"build": "17D50",
"version": "13.3.1"
},
{
"build": "17E255",
"version": "13.4"
},
{
"build": "17E8255",
"version": "13.4"
},
{
"build": "17E262",
"version": "13.4.1"
},
{
"build": "17E8258",
"version": "13.4.1"
},
{
"build": "17F75",
"version": "13.5"
},
{
"build": "17F80",
"version": "13.5.1"
},
{
"build": "17G68",
"version": "13.6"
},
{
"build": "17G80",
"version": "13.6.1"
},
{
"build": "17H35",
"version": "13.7"
},
{
"build": "18A373",
"version": "14.0"
},
{
"build": "18A393",
"version": "14.0.1"
},
{
"build": "18A8395",
"version": "14.1"
},
{
"build": "18B92",
"version": "14.2"
},
{
"version": "14.2",
"build": "18B111"
},
{
"version": "14.2.1",
"build": "18B121"
},
{
"build": "18C66",
"version": "14.3"
},
{
"build": "18D52",
"version": "14.4"
},
{
"build": "18D61",
"version": "14.4.1"
},
{
"build": "18D70",
"version": "14.4.2"
},
{
"build": "18E199",
"version": "14.5"
},
{
"build": "18E212",
"version": "14.5.1"
},
{
"build": "18F72",
"version": "14.6"
},
{
"build": "18G69",
"version": "14.7"
},
{
"build": "18G82",
"version": "14.7.1"
},
{
"build": "18H17",
"version": "14.8"
},
{
"build": "18H107",
"version": "14.8.1"
},
{
"build": "19A341",
"version": "15.0"
},
{
"build": "19A346",
"version": "15.0"
},
{
"build": "19A348",
"version": "15.0.1"
},
{
"build": "19A404",
"version": "15.0.2"
},
{
"build": "19B74",
"version": "15.1"
},
{
"build": "19B81",
"version": "15.1.1"
},
{
"build": "19C56",
"version": "15.2"
},
{
"build": "19C63",
"version": "15.2.1"
},
{
"build": "19D50",
"version": "15.3"
},
{
"build": "19D52",
"version": "15.3.1"
},
{
"build": "19E241",
"version": "15.4"
},
{
"build": "19E258",
"version": "15.4.1"
},
{
"build": "19F77",
"version": "15.5"
},
{
"build": "19G71",
"version": "15.6"
},
{
"build": "19G82",
"version": "15.6.1"
},
{
"build": "19H12",
"version": "15.7"
},
{
"build": "19H117",
"version": "15.7.1"
},
{
"build": "19H218",
"version": "15.7.2"
},
{
"version": "15.7.3",
"build": "19H307"
},
{
"version": "15.7.4",
"build": "19H321"
},
{
"version": "15.7.5",
"build": "19H332"
},
{
"version": "15.7.6",
"build": "19H349"
},
{
"build": "20A362",
"version": "16.0"
},
{
"build": "20A371",
"version": "16.0.1"
},
{
"build": "20A380",
"version": "16.0.2"
},
{
"build": "20A392",
"version": "16.0.3"
},
{
"build": "20B82",
"version": "16.1"
},
{
"build": "20B101",
"version": "16.1.1"
},
{
"build": "20B110",
"version": "16.1.2"
},
{
"build": "20C65",
"version": "16.2"
},
{
"build": "20D47",
"version": "16.3"
},
{
"build": "20D67",
"version": "16.3.1"
},
{
"build": "20E247",
"version": "16.4"
},
{
"build": "20E252",
"version": "16.4.1"
},
{
"version": "16.5",
"beta": null,
"build": "20F66"
}
]

View File

@@ -158,7 +158,6 @@ class Manifest(IOSExtraction):
"mode": oct(self._get_key(file_metadata, "Mode")),
"owner": self._get_key(file_metadata, "UserID"),
"size": self._get_key(file_metadata, "Size"),
"type": "file" if file_data["flags"] == 1 else "directory",
})
except Exception:
self.log.exception("Error reading manifest file metadata for file with ID %s "

View File

@@ -1,3 +0,0 @@
from .attachment_deletion import PostAttachmentDeletion
POST_ANALYSIS_MODULES = [PostAttachmentDeletion]

View File

@@ -1,101 +0,0 @@
import logging
import datetime
from typing import Optional
from mvt.common.module import PostAnalysisModule
class PostAttachmentDeletion(PostAnalysisModule):
"""
Heuristic detection for attachment deletion in a cert time period.
This module implements a hueuristic detection for a multiple iOS SMS attachmemt being deleted
in a short period of time. This is a similar concept to the following script used
by Kaspersky Labs to detect infections with the Triangulation iOS malware:
https://github.com/KasperskyLab/triangle_check/blob/main/triangle_check/__init__.py
"""
def __init__(
self,
file_path: Optional[str] = None,
target_path: Optional[str] = None,
results_path: Optional[str] = None,
fast_mode: Optional[bool] = False,
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, fast_mode=fast_mode,
log=log, results=results)
self.required_modules = ["manifest"]
def load_locationd_events(self):
locationd_clients = self.results["locationd_clients"]
locations_stopped_event = [event for event in locationd_clients if "LocationTimeStopped" in event]
return locations_stopped_event
def run(self) -> None:
"""
Run the post-processing module.
The logical is to look for all SMS attachment directories which were recently created
shortly before their last modified time, but which have no contained files.
"""
for module in self.required_modules:
if module not in self.results:
raise Exception(f"Required module {module} was not found in results. Did you run the required modules?")
locationd_events = []
locationd_client_iocs = [
"com.apple.locationd.bundle-/System/Library/LocationBundles/IonosphereHarvest.bundle",
"com.apple.locationd.bundle-/System/Library/LocationBundles/WRMLinkSelection.bundle"
]
for event in self.load_locationd_events():
for ioc in locationd_client_iocs:
if ioc in event["Registered"]:
locationd_events.append(event)
print(event)
# Filter the relevant events from the manifest:
events_by_time = {}
sms_files = [event for event in self.results["manifest"] if event["relative_path"].startswith("Library/SMS/Attachments/")]
attachment_folders = {}
for record in sorted(sms_files, key=lambda x: x["relative_path"]):
num_path_segments = record["relative_path"].count('/')
# Skip entries with a full-path
# if not (num_path_segments == 3 or num_path_segments == 4):
# continue
attachment_root = "/".join(record["relative_path"].split('/', 5)[:5])
attachment_folder = attachment_folders.get(attachment_root, [])
attachment_folder.append(record)
attachment_folders[attachment_root] = attachment_folder
# Look for directories containing no files, which had a short lifespan
for key, items in attachment_folders.items():
has_files = any([item["flags"] == 1 for item in items])
if has_files:
continue
for item in sorted(items, key=lambda x: x["created"]):
# item_created = datetime.datetime.strptime(item["created"], "%Y-%m-%d %H:%M:%S.%f")
item_modified = datetime.datetime.strptime(item["modified"], "%Y-%m-%d %H:%M:%S.%f") # M
status_changed = datetime.datetime.strptime(item["status_changed"], "%Y-%m-%d %H:%M:%S.%f") # C
# self.append_timeline(fs_stat['LastModified'], ('M', relativePath))
# self.append_timeline(fs_stat['LastStatusChange'], ('C', relativePath))
# self.append_timeline(fs_stat['Birth'], ('B', relativePath))
# Skip items which were created and modified at the same time, likely never had files.
# print(item["relative_path"], status_changed, item_modified)
if item_modified == status_changed:
print("changed == modified", item["relative_path"], status_changed, item_modified)
continue
if (item_modified - status_changed): # < datetime.timedelta(minutes=10):
self.log.info(f"Possible attachment deletion. Attachment folder '{key}' with no files, created and modified within 10 minutes. '{item['relative_path']}' created {item_created}, modified {item_modified})")

View File

@@ -2,16 +2,279 @@
# Copyright (c) 2021-2023 Claudio Guarnieri.
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
import json
from logging import Logger
from typing import Dict, Optional
import packaging
import pkgutil
IPHONE_MODELS = [
{"identifier": "iPhone4,1", "description": "iPhone 4S"},
{"identifier": "iPhone5,1", "description": "iPhone 5"},
{"identifier": "iPhone5,2", "description": "iPhone 5"},
{"identifier": "iPhone5,3", "description": "iPhone 5c"},
{"identifier": "iPhone5,4", "description": "iPhone 5c"},
{"identifier": "iPhone6,1", "description": "iPhone 5s"},
{"identifier": "iPhone6,2", "description": "iPhone 5s"},
{"identifier": "iPhone7,1", "description": "iPhone 6 Plus"},
{"identifier": "iPhone7,2", "description": "iPhone 6"},
{"identifier": "iPhone8,1", "description": "iPhone 6s"},
{"identifier": "iPhone8,2", "description": "iPhone 6s Plus"},
{"identifier": "iPhone8,4", "description": "iPhone SE (1st generation)"},
{"identifier": "iPhone9,1", "description": "iPhone 7"},
{"identifier": "iPhone9,2", "description": "iPhone 7 Plus"},
{"identifier": "iPhone9,3", "description": "iPhone 7"},
{"identifier": "iPhone9,4", "description": "iPhone 7 Plus"},
{"identifier": "iPhone10,1", "description": "iPhone 8"},
{"identifier": "iPhone10,2", "description": "iPhone 8 Plus"},
{"identifier": "iPhone10,3", "description": "iPhone X"},
{"identifier": "iPhone10,4", "description": "iPhone 8"},
{"identifier": "iPhone10,5", "description": "iPhone 8 Plus"},
{"identifier": "iPhone10,6", "description": "iPhone X"},
{"identifier": "iPhone11,2", "description": "iPhone XS"},
{"identifier": "iPhone11,4", "description": "iPhone XS Max"},
{"identifier": "iPhone11,6", "description": "iPhone XS Max"},
{"identifier": "iPhone11,8", "description": "iPhone XR"},
{"identifier": "iPhone12,1", "description": "iPhone 11"},
{"identifier": "iPhone12,3", "description": "iPhone 11 Pro"},
{"identifier": "iPhone12,5", "description": "iPhone 11 Pro Max"},
{"identifier": "iPhone12,8", "description": "iPhone SE (2nd generation)"},
{"identifier": "iPhone13,1", "description": "iPhone 12 mini"},
{"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"},
{"identifier": "iPhone14,8", "decription": "iPhone 14 Plus"},
{"identifier": "iPhone15,2", "description": "iPhone 14 Pro"},
{"identifier": "iPhone15,3", "description": "iPhone 14 Pro Max"}
]
IPHONE_MODELS = json.loads(pkgutil.get_data("mvt", "ios/data/ios_models.json"))
IPHONE_IOS_VERSIONS = json.loads(pkgutil.get_data("mvt", "ios/data/ios_versions.json"))
IPHONE_IOS_VERSIONS = [
{"build": "1A543a", "version": "1.0"},
{"build": "1C25", "version": "1.0.1"},
{"build": "1C28", "version": "1.0.2"},
{"build": "3A109a", "version": "1.1.1"},
{"build": "3B48b", "version": "1.1.2"},
{"build": "4A93", "version": "1.1.3"},
{"build": "4A102", "version": "1.1.4"},
{"build": "5A347", "version": "2.0"},
{"build": "5B108", "version": "2.0.1"},
{"build": "5C1", "version": "2.0.2"},
{"build": "5F136", "version": "2.1"},
{"build": "5G77", "version": "2.2"},
{"build": "5H11", "version": "2.2.1"},
{"build": "7A341", "version": "3.0"},
{"build": "7A400", "version": "3.0.1"},
{"build": "7C144", "version": "3.1"},
{"build": "7D11", "version": "3.1.2"},
{"build": "7E18", "version": "3.1.3"},
{"build": "8A293", "version": "4.0"},
{"build": "8A306", "version": "4.0.1"},
{"build": "8B117", "version": "4.1"},
{"build": "8C148", "version": "4.2"},
{"build": "8C148a", "version": "4.2.1"},
{"build": "8C148", "version": "4.2.1"},
{"build": "8E600", "version": "4.2.10"},
{"build": "8E401", "version": "4.2.8"},
{"build": "8E501", "version": "4.2.9"},
{"build": "8F190", "version": "4.3"},
{"build": "8J2", "version": "4.3.3"},
{"build": "8K2", "version": "4.3.4"},
{"build": "8L1", "version": "4.3.5"},
{"build": "9A334", "version": "5.0"},
{"build": "9A405", "version": "5.0.1"},
{"build": "9A406", "version": "5.0.1"},
{"build": "9B176", "version": "5.1"},
{"build": "9B179", "version": "5.1"},
{"build": "9B206", "version": "5.1.1"},
{"build": "9B208", "version": "5.1.1"},
{"build": "10A403", "version": "6.0"},
{"build": "10A405", "version": "6.0"},
{"build": "10A523", "version": "6.0.1"},
{"build": "10A525", "version": "6.0.1"},
{"build": "10A551", "version": "6.0.2"},
{"build": "10B141", "version": "6.1"},
{"build": "10B144", "version": "6.1"},
{"build": "10B142", "version": "6.1"},
{"build": "10B143", "version": "6.1"},
{"build": "10B145", "version": "6.1.1"},
{"build": "10B146", "version": "6.1.2"},
{"build": "10B329", "version": "6.1.3"},
{"build": "10B350", "version": "6.1.4"},
{"build": "10B500", "version": "6.1.6"},
{"build": "11B511", "version": "7.0.3"},
{"build": "11B554a", "version": "7.0.4"},
{"build": "11B601", "version": "7.0.5"},
{"build": "11B651", "version": "7.0.6"},
{"build": "11D169", "version": "7.1"},
{"build": "11D167", "version": "7.1"},
{"build": "11D201", "version": "7.1.1"},
{"build": "11D257", "version": "7.1.2"},
{"build": "12A365", "version": "8.0"},
{"build": "12A366", "version": "8.0"},
{"build": "12A402", "version": "8.0.1"},
{"build": "12A405", "version": "8.0.2"},
{"build": "12B411", "version": "8.1"},
{"build": "12B435", "version": "8.1.1"},
{"build": "12B436", "version": "8.1.1"},
{"build": "12B440", "version": "8.1.2"},
{"build": "12B466", "version": "8.1.3"},
{"build": "12D508", "version": "8.2"},
{"build": "12F70", "version": "8.3"},
{"build": "12H143", "version": "8.4"},
{"build": "12H321", "version": "8.4.1"},
{"build": "13A344", "version": "9.0"},
{"build": "13A342", "version": "9.0"},
{"build": "13A343", "version": "9.0"},
{"build": "13A404", "version": "9.0.1"},
{"build": "13A405", "version": "9.0.1"},
{"build": "13A452", "version": "9.0.2"},
{"build": "13B143", "version": "9.1"},
{"build": "13C75", "version": "9.2"},
{"build": "13D15", "version": "9.2.1"},
{"build": "13D20", "version": "9.2.1"},
{"build": "13E237", "version": "9.3"},
{"build": "13E233", "version": "9.3"},
{"build": "13E234", "version": "9.3"},
{"build": "13E238", "version": "9.3.1"},
{"build": "13F69", "version": "9.3.2"},
{"build": "13G34", "version": "9.3.3"},
{"build": "13G35", "version": "9.3.4"},
{"build": "13G36", "version": "9.3.5"},
{"build": "13G37", "version": "9.3.6"},
{"build": "14A403", "version": "10.0.1"},
{"build": "14A456", "version": "10.0.2"},
{"build": "14A551", "version": "10.0.3"},
{"build": "14B72", "version": "10.1"},
{"build": "14B72c", "version": "10.1"},
{"build": "14B150", "version": "10.1.1"},
{"build": "14B100", "version": "10.1.1"},
{"build": "14C92", "version": "10.2"},
{"build": "14D27", "version": "10.2.1"},
{"build": "14E277", "version": "10.3"},
{"build": "14E304", "version": "10.3.1"},
{"build": "14F89", "version": "10.3.2"},
{"build": "14G60", "version": "10.3.3"},
{"build": "14G61", "version": "10.3.4"},
{"build": "15A372", "version": "11.0"},
{"build": "15A402", "version": "11.0.1"},
{"build": "15A421", "version": "11.0.2"},
{"build": "15A432", "version": "11.0.3"},
{"build": "15B93", "version": "11.1"},
{"build": "15B150", "version": "11.1.1"},
{"build": "15B202", "version": "11.1.2"},
{"build": "15C114", "version": "11.2"},
{"build": "15C153", "version": "11.2.1"},
{"build": "15C202", "version": "11.2.2"},
{"build": "15D60", "version": "11.2.5"},
{"build": "15D100", "version": "11.2.6"},
{"build": "15E216", "version": "11.3"},
{"build": "15E302", "version": "11.3.1"},
{"build": "15F79", "version": "11.4"},
{"build": "15G77", "version": "11.4.1"},
{"build": "16A366", "version": "12.0"},
{"build": "16A367", "version": "12.0"},
{"build": "16A404", "version": "12.0.1"},
{"build": "16A405", "version": "12.0.1"},
{"build": "16B92", "version": "12.1"},
{"build": "16B94", "version": "12.1"},
{"build": "16B93", "version": "12.1"},
{"build": "16C50", "version": "12.1.1"},
{"build": "16C104", "version": "12.1.2"},
{"build": "16C101", "version": "12.1.2"},
{"build": "16D39", "version": "12.1.3"},
{"build": "16D40", "version": "12.1.3"},
{"build": "16D57", "version": "12.1.4"},
{"build": "16E227", "version": "12.2"},
{"build": "16F156", "version": "12.3"},
{"build": "16F203", "version": "12.3.1"},
{"build": "16F250", "version": "12.3.2"},
{"build": "16G77", "version": "12.4"},
{"build": "16G102", "version": "12.4.1"},
{"build": "16G114", "version": "12.4.2"},
{"build": "16G130", "version": "12.4.3"},
{"build": "16G140", "version": "12.4.4"},
{"build": "16G161", "version": "12.4.5"},
{"build": "16G183", "version": "12.4.6"},
{"build": "16G192", "version": "12.4.7"},
{"build": "16G201", "version": "12.4.8"},
{"build": "16H5", "version": "12.4.9"},
{"build": "16H20", "version": "12.5"},
{"build": "16H22", "version": "12.5.1"},
{"build": "16H30", "version": "12.5.2"},
{"build": "16H41", "version": "12.5.3"},
{"build": "16H50", "version": "12.5.4"},
{"build": "16H62", "version": "12.5.5"},
{"build": "16H71", "version": "12.5.6"},
{"build": "16H81", "version": "12.5.7"},
{"build": "17A577", "version": "13.0"},
{"build": "17A844", "version": "13.1"},
{"build": "17A854", "version": "13.1.1"},
{"build": "17A860", "version": "13.1.2"},
{"build": "17A861", "version": "13.1.2"},
{"build": "17A878", "version": "13.1.3"},
{"build": "17B84", "version": "13.2"},
{"build": "17B102", "version": "13.2.2"},
{"build": "17B111", "version": "13.2.3"},
{"build": "17C54", "version": "13.3"},
{"build": "17D50", "version": "13.3.1"},
{"build": "17E255", "version": "13.4"},
{"build": "17E8255", "version": "13.4"},
{"build": "17E262", "version": "13.4.1"},
{"build": "17E8258", "version": "13.4.1"},
{"build": "17F75", "version": "13.5"},
{"build": "17F80", "version": "13.5.1"},
{"build": "17G68", "version": "13.6"},
{"build": "17G80", "version": "13.6.1"},
{"build": "17H35", "version": "13.7"},
{"build": "18A373", "version": "14.0"},
{"build": "18A393", "version": "14.0.1"},
{"build": "18A8395", "version": "14.1"},
{"build": "18B92", "version": "14.2"},
{"build": "18C66", "version": "14.3"},
{"build": "18D52", "version": "14.4"},
{"build": "18D61", "version": "14.4.1"},
{"build": "18D70", "version": "14.4.2"},
{"build": "18E199", "version": "14.5"},
{"build": "18E212", "version": "14.5.1"},
{"build": "18F72", "version": "14.6"},
{"build": "18G69", "version": "14.7"},
{"build": "18G82", "version": "14.7.1"},
{"build": "18H17", "version": "14.8"},
{"build": "18H107", "version": "14.8.1"},
{"build": "19A341", "version": "15.0"},
{"build": "19A346", "version": "15.0"},
{"build": "19A348", "version": "15.0.1"},
{"build": "19A404", "version": "15.0.2"},
{"build": "19B74", "version": "15.1"},
{"build": "19B81", "version": "15.1.1"},
{"build": "19C56", "version": "15.2"},
{"build": "19C63", "version": "15.2.1"},
{"build": "19D50", "version": "15.3"},
{"build": "19D52", "version": "15.3.1"},
{"build": "19E241", "version": "15.4"},
{"build": "19E258", "version": "15.4.1"},
{"build": "19F77", "version": "15.5"},
{"build": "19G71", "version": "15.6"},
{"build": "19G82", "version": "15.6.1"},
{"build": "19H12", "version": "15.7"},
{"build": "19H117", "version": "15.7.1"},
{"build": "19H218", "version": "15.7.2"},
{"build": "20A362", "version": "16.0"},
{"build": "20A371", "version": "16.0.1"},
{"build": "20A380", "version": "16.0.2"},
{"build": "20A392", "version": "16.0.3"},
{"build": "20B82", "version": "16.1"},
{"build": "20B101", "version": "16.1.1"},
{"build": "20B110", "version": "16.1.2"},
{"build": "20C65", "version": "16.2"},
{"build": "20D47", "version": "16.3"},
{"build": "20D67", "version": "16.3.1"},
{"build": "20E247", "version": "16.4"},
{"build": "20E252", "version": "16.4.1"}
]
def get_device_desc_from_id(identifier: str,

View File

@@ -42,9 +42,6 @@ console_scripts =
mvt-ios = mvt.ios:cli
mvt-android = mvt.android:cli
[options.package_data]
mvt = ios/data/*.json
[flake8]
max-complexity = 10
max-line-length = 1000