Add file timestamp modules to add logs into timeline

This commit is contained in:
Donncha Ó Cearbhaill
2024-10-28 11:49:30 +01:00
parent 84d7716ef1
commit 39f78851ae
5 changed files with 176 additions and 0 deletions
@@ -0,0 +1,43 @@
# 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 typing import Union
from .artifact import AndroidArtifact
class FileTimestampsArtifact(AndroidArtifact):
def serialize(self, record: dict) -> Union[dict, list]:
records = []
for ts in set(
[
record.get("access_time"),
record.get("changed_time"),
record.get("modified_time"),
]
):
if not ts:
continue
macb = ""
macb += "M" if ts == record.get("modified_time") else "-"
macb += "A" if ts == record.get("access_time") else "-"
macb += "C" if ts == record.get("changed_time") else "-"
macb += "-"
msg = record["path"]
if record.get("context"):
msg += f" ({record['context']})"
records.append(
{
"timestamp": ts,
"module": self.__class__.__name__,
"event": macb,
"data": msg,
}
)
return records
@@ -0,0 +1,65 @@
# 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/
import os
import datetime
import logging
from typing import Optional
from mvt.common.utils import convert_datetime_to_iso
from .base import AndroidQFModule
from mvt.android.artifacts.file_timestamps import FileTimestampsArtifact
class LogsFileTimestamps(FileTimestampsArtifact, AndroidQFModule):
"""This module extracts records from battery daily updates."""
slug = "logfile_timestamps"
def __init__(
self,
file_path: Optional[str] = None,
target_path: Optional[str] = None,
results_path: Optional[str] = None,
module_options: Optional[dict] = None,
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,
module_options=module_options,
log=log,
results=results,
)
def _get_file_modification_time(self, file_path: str) -> dict:
if self.archive:
file_timetuple = self.archive.getinfo(file_path).date_time
return datetime.datetime(*file_timetuple)
else:
file_stat = os.stat(os.path.join(self.parent_path, file_path))
return datetime.datetime.fromtimestamp(file_stat.st_mtime)
def run(self) -> None:
filesystem_files = self._get_files_by_pattern("*/logs/*")
self.results = []
for file in filesystem_files:
# Only the modification time is available in the zip file metadata.
# The timezone is the local timezone of the machine the phone.
modification_time = self._get_file_modification_time(file)
self.results.append(
{
"path": file,
"modified_time": convert_datetime_to_iso(modification_time),
}
)
self.log.info(
"Extracted a total of %d filesystem timestamps from AndroidQF logs directory.",
len(self.results),
)
@@ -13,6 +13,7 @@ from .getprop import Getprop
from .packages import Packages
from .receivers import Receivers
from .adb_state import DumpsysADBState
from .fs_timestamps import BugReportTimestamps
BUGREPORT_MODULES = [
Accessibility,
@@ -25,4 +26,5 @@ BUGREPORT_MODULES = [
Packages,
Receivers,
DumpsysADBState,
BugReportTimestamps,
]
@@ -6,6 +6,7 @@
import fnmatch
import logging
import os
from typing import List, Optional
from zipfile import ZipFile
@@ -0,0 +1,65 @@
# 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/
import os
import logging
import datetime
from typing import Optional
from mvt.common.utils import convert_datetime_to_iso
from .base import BugReportModule
from mvt.android.artifacts.file_timestamps import FileTimestampsArtifact
class BugReportTimestamps(FileTimestampsArtifact, BugReportModule):
"""This module extracts records from battery daily updates."""
slug = "bugreport_timestamps"
def __init__(
self,
file_path: Optional[str] = None,
target_path: Optional[str] = None,
results_path: Optional[str] = None,
module_options: Optional[dict] = None,
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,
module_options=module_options,
log=log,
results=results,
)
def _get_file_modification_time(self, file_path: str) -> dict:
if self.zip_archive:
file_timetuple = self.zip_archive.getinfo(file_path).date_time
return datetime.datetime(*file_timetuple)
else:
file_stat = os.stat(os.path.join(self.extract_path, file_path))
return datetime.datetime.fromtimestamp(file_stat.st_mtime)
def run(self) -> None:
filesystem_files = self._get_files_by_pattern("FS/*")
self.results = []
for file in filesystem_files:
# Only the modification time is available in the zip file metadata.
# The timezone is the local timezone of the machine the phone.
modification_time = self._get_file_modification_time(file)
self.results.append(
{
"path": file,
"modified_time": convert_datetime_to_iso(modification_time),
}
)
self.log.info(
"Extracted a total of %d filesystem timestamps from bugreport.",
len(self.results),
)