From 904daad93593d87a4114f2a4774b8109c3e3af92 Mon Sep 17 00:00:00 2001 From: pungentsneak Date: Wed, 22 Sep 2021 13:24:17 +0200 Subject: [PATCH] add ShutdownLog --- docs/ios/records.md | 12 ++++++ mvt/common/indicators.py | 10 ++++- mvt/ios/modules/fs/__init__.py | 3 +- mvt/ios/modules/fs/shutdown.py | 67 ++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 mvt/ios/modules/fs/shutdown.py diff --git a/docs/ios/records.md b/docs/ios/records.md index 3588e45..8d12210 100644 --- a/docs/ios/records.md +++ b/docs/ios/records.md @@ -230,6 +230,18 @@ If indicators are provided through the command-line, they are checked against th --- +### `shutdown_log.json` + +!!! info "Availability" + 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. + +If indicators are provided through the command-line, they are checked against the paths. Any matches are stored in *shutdown_log_detected.json*. + +--- + ### `sms.json` !!! info "Availability" diff --git a/mvt/common/indicators.py b/mvt/common/indicators.py index 1310f11..a7d517f 100644 --- a/mvt/common/indicators.py +++ b/mvt/common/indicators.py @@ -163,10 +163,12 @@ class Indicators: return False - def check_process(self, process) -> bool: + def check_process(self, process, contains = False) -> bool: """Check the provided process name against the list of process indicators. + :param contains: Check if the process is contained inside the string. + :type process: bool :param process: Process name to check against process indicators :type process: str :returns: True if process matched an indicator, otherwise False @@ -175,6 +177,12 @@ class Indicators: if not process: return False + if (contains): + for malicious_process in self.ioc_processes: + if malicious_process in process: + self.log.warning("Found a known suspicious process name (\"%s\") in \"%s\"", malicious_process, process) + return True + proc_name = os.path.basename(process) if proc_name in self.ioc_processes: self.log.warning("Found a known suspicious process name \"%s\"", process) diff --git a/mvt/ios/modules/fs/__init__.py b/mvt/ios/modules/fs/__init__.py index 9a54b51..7762f41 100644 --- a/mvt/ios/modules/fs/__init__.py +++ b/mvt/ios/modules/fs/__init__.py @@ -7,10 +7,11 @@ from .cache_files import CacheFiles from .filesystem import Filesystem from .net_netusage import Netusage from .safari_favicon import SafariFavicon +from .shutdown import ShutdownLog from .version_history import IOSVersionHistory from .webkit_indexeddb import WebkitIndexedDB from .webkit_localstorage import WebkitLocalStorage from .webkit_safariviewservice import WebkitSafariViewService -FS_MODULES = [CacheFiles, Filesystem, Netusage, SafariFavicon, IOSVersionHistory, +FS_MODULES = [CacheFiles, Filesystem, Netusage, SafariFavicon, ShutdownLog, IOSVersionHistory, WebkitIndexedDB, WebkitLocalStorage, WebkitSafariViewService,] diff --git a/mvt/ios/modules/fs/shutdown.py b/mvt/ios/modules/fs/shutdown.py new file mode 100644 index 0000000..4d96692 --- /dev/null +++ b/mvt/ios/modules/fs/shutdown.py @@ -0,0 +1,67 @@ +# 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/ + +from mvt.common.utils import convert_mactime_to_unix, convert_timestamp_to_iso + +from ..base import IOSExtraction + +SHUTDOWN_LOG_PATH = [ + "private/var/db/diagnostics/shutdown.log", +] + +class ShutdownLog(IOSExtraction): + """This module extracts processes information from the shutdown log 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["isodate"], + "module": self.__class__.__name__, + "event": "shutdown", + "data": f"Client {record['client']} with PID {record['pid']} was running when the device was shut down", + } + + + def check_indicators(self): + if not self.indicators: + return + + for result in self.results: + if self.indicators.check_process(result["client"], True): + self.detected.append(result) + + def run(self): + self._find_ios_database(root_paths=SHUTDOWN_LOG_PATH) + self.log.info("Found shutdown log at path: %s", self.file_path) + + with open(self.file_path, "r") as shutdown_log: + shutdown_log_lines = shutdown_log.readlines() + date = "0000-00-00 00:00:00.000000 (unknown)" + + for line in shutdown_log_lines: + if line.startswith("After "): + continue + + elif line.startswith("\t\tremaining client pid: "): + pid = int(line.split("\t\tremaining client pid: ")[1].split(" ")[0]) + client = line.split("(")[1].split(")")[0] + entry = { + "isodate": date, + "pid": pid, + "client": client + } + if entry not in self.results: + self.results.append(entry) + + elif line.startswith("SIGTERM: ["): + isodate = int(line.split("[")[1].split("]")[0]) + date = convert_timestamp_to_iso(convert_mactime_to_unix(isodate, False)) + + self.results = sorted(self.results, key=lambda entry: entry["isodate"])