mirror of
https://github.com/mvt-project/mvt.git
synced 2026-07-18 02:17:22 +02:00
Support rotated iOS shutdown logs (#834)
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from mvt.common.module import DatabaseNotFoundError
|
||||
from mvt.common.module_types import (
|
||||
ModuleAtomicResult,
|
||||
ModuleResults,
|
||||
@@ -17,6 +18,7 @@ from ..base import IOSExtraction
|
||||
|
||||
SHUTDOWN_LOG_PATH = [
|
||||
"private/var/db/diagnostics/shutdown.log",
|
||||
"private/var/db/diagnostics/shutdown.*.log",
|
||||
]
|
||||
|
||||
|
||||
@@ -132,10 +134,17 @@ class ShutdownLog(IOSExtraction):
|
||||
self.results = sorted(self.results, key=lambda entry: entry["isodate"])
|
||||
|
||||
def run(self) -> None:
|
||||
self._find_ios_database(root_paths=SHUTDOWN_LOG_PATH)
|
||||
self.log.info("Found shutdown log at path: %s", self.file_path)
|
||||
if self.file_path:
|
||||
shutdown_log_paths = [self.file_path]
|
||||
else:
|
||||
shutdown_log_paths = sorted(
|
||||
self._get_fs_files_from_patterns(SHUTDOWN_LOG_PATH)
|
||||
)
|
||||
|
||||
if not self.file_path:
|
||||
return
|
||||
with open(self.file_path, "r", encoding="utf-8") as handle:
|
||||
self.process_shutdownlog(handle.read())
|
||||
if not shutdown_log_paths:
|
||||
raise DatabaseNotFoundError("unable to find any shutdown log files")
|
||||
|
||||
for shutdown_log_path in shutdown_log_paths:
|
||||
self.log.info("Found shutdown log at path: %s", shutdown_log_path)
|
||||
with open(shutdown_log_path, "r", encoding="utf-8") as handle:
|
||||
self.process_shutdownlog(handle.read())
|
||||
|
||||
@@ -35,6 +35,7 @@ def indicators_factory(indicator_file):
|
||||
domains=[],
|
||||
emails=[],
|
||||
file_names=[],
|
||||
file_paths=[],
|
||||
processes=[],
|
||||
app_ids=[],
|
||||
app_cert_hashes=[],
|
||||
@@ -47,6 +48,7 @@ def indicators_factory(indicator_file):
|
||||
ind.ioc_collections[0]["domains"].extend(domains)
|
||||
ind.ioc_collections[0]["emails"].extend(emails)
|
||||
ind.ioc_collections[0]["file_names"].extend(file_names)
|
||||
ind.ioc_collections[0]["file_paths"].extend(file_paths)
|
||||
ind.ioc_collections[0]["processes"].extend(processes)
|
||||
ind.ioc_collections[0]["app_ids"].extend(app_ids)
|
||||
ind.ioc_collections[0]["android_property_names"].extend(android_property_names)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# Mobile Verification Toolkit (MVT)
|
||||
# Copyright (c) 2021-2023 The MVT Authors.
|
||||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
from mvt.common.module import run_module
|
||||
from mvt.ios.modules.fs.shutdownlog import ShutdownLog
|
||||
|
||||
|
||||
def _shutdown_log_entry(pid: int, client: str, timestamp: int) -> str:
|
||||
return (
|
||||
f"remaining client pid: {pid} ({client})\n"
|
||||
f"SIGTERM: [{timestamp}]\n"
|
||||
)
|
||||
|
||||
|
||||
class TestShutdownLog:
|
||||
def test_discovers_rotated_shutdown_logs(self, tmp_path):
|
||||
diagnostics_path = tmp_path / "private/var/db/diagnostics"
|
||||
diagnostics_path.mkdir(parents=True)
|
||||
(diagnostics_path / "shutdown.log").write_text(
|
||||
_shutdown_log_entry(100, "/usr/libexec/first", 1_700_000_000),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(diagnostics_path / "shutdown.0.log").write_text(
|
||||
_shutdown_log_entry(200, "/usr/libexec/second", 1_700_000_001),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
module = ShutdownLog(target_path=str(tmp_path))
|
||||
run_module(module)
|
||||
|
||||
assert {result["client"] for result in module.results} == {
|
||||
"/usr/libexec/first",
|
||||
"/usr/libexec/second",
|
||||
}
|
||||
|
||||
def test_file_path_indicator_matches_client_with_trailing_uuid(
|
||||
self, indicators_factory
|
||||
):
|
||||
executable_path = "/usr/sbin/filecoordinationd"
|
||||
client = f"{executable_path}/123e4567-e89b-12d3-a456-426614174000"
|
||||
module = ShutdownLog(
|
||||
results=[
|
||||
{
|
||||
"isodate": "2023-11-14 22:13:20.000000",
|
||||
"pid": "100",
|
||||
"client": client,
|
||||
"delay": 0.0,
|
||||
"times_delayed": 0,
|
||||
}
|
||||
]
|
||||
)
|
||||
module.indicators = indicators_factory(file_paths=[executable_path])
|
||||
|
||||
module.check_indicators()
|
||||
|
||||
assert len(module.alertstore.alerts) == 1
|
||||
assert module.alertstore.alerts[0].matched_indicator.value == executable_path
|
||||
Reference in New Issue
Block a user