mirror of
https://github.com/mvt-project/mvt.git
synced 2026-07-28 15:18:51 +02:00
* fix(ios): scan Safari profile databases for history and browser state Safari profiles (iOS 17 and later) keep their own databases under Library/Safari/Profiles/<UUID>/, but SafariHistory and SafariBrowserState only ever looked at the default profile's Library/Safari/History.db and Library/Safari/BrowserState.db. On a device where browsing happens inside a profile, MVT silently skipped that history and still reported no detections, so an indicator only ever visited within a profile went unnoticed. Both modules now also match Library/Safari/Profiles/*/ in backups and in filesystem dumps. No helper changes were needed: the Manifest.db lookup already translates "*" into a SQL LIKE wildcard, and the filesystem lookup already globs. Found while examining an encrypted iOS 26.5.2 backup that contained 14 per-profile History.db files under AppDomain-com.apple.mobilesafari::Library/Safari/Profiles/<UUID>/. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(ios): scope Safari redirects to history database --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Janik Besendorf <janik@besendorf.org>
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
# 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 sqlite3
|
|
from pathlib import Path
|
|
|
|
|
|
def get_artifact(fname):
|
|
"""
|
|
Return the artifact path in the artifact folder
|
|
"""
|
|
fpath = os.path.join(get_artifact_folder(), fname)
|
|
if os.path.isfile(fpath):
|
|
return fpath
|
|
return
|
|
|
|
|
|
def get_artifact_folder():
|
|
return os.path.join(os.path.dirname(__file__), "artifacts")
|
|
|
|
|
|
def get_ios_backup_folder():
|
|
return os.path.join(os.path.dirname(__file__), "artifacts", "ios_backup")
|
|
|
|
|
|
def get_android_backup_folder():
|
|
return os.path.join(os.path.dirname(__file__), "artifacts", "android_backup")
|
|
|
|
|
|
def get_android_androidqf():
|
|
return os.path.join(os.path.dirname(__file__), "artifacts", "androidqf")
|
|
|
|
|
|
def get_indicator_file():
|
|
print("PYTEST env", os.getenv("PYTEST_CURRENT_TEST"))
|
|
|
|
|
|
def add_backup_manifest_entry(backup_path, file_id, domain, relative_path):
|
|
"""
|
|
Register an extra file in a test backup's Manifest.db
|
|
"""
|
|
conn = sqlite3.connect(os.path.join(backup_path, "Manifest.db"))
|
|
conn.execute(
|
|
"INSERT INTO Files (fileID, domain, relativePath, flags, file) "
|
|
"VALUES (?, ?, ?, 1, ?);",
|
|
(file_id, domain, relative_path, b""),
|
|
)
|
|
conn.commit()
|
|
# MVT opens backup databases with immutable=1, which ignores any -wal file,
|
|
# so the new row has to be checkpointed into Manifest.db itself.
|
|
conn.execute("PRAGMA journal_mode=DELETE;")
|
|
conn.close()
|
|
|
|
|
|
def delete_tmp_db_files(file_path):
|
|
"""
|
|
Remove Sqlite temporary files that appear on some platforms
|
|
|
|
These can cause filesystem tests to fail depending on the OS.
|
|
"""
|
|
for file_name in ["Manifest.db-wal", "Manifest.db-shm"]:
|
|
path = os.path.join(file_path, file_name)
|
|
if os.path.isfile(path):
|
|
os.remove(path)
|
|
|
|
|
|
def list_files(path: str):
|
|
files = []
|
|
parent_path = Path(path).absolute().parent.as_posix()
|
|
target_abs_path = os.path.abspath(path)
|
|
for root, subdirs, subfiles in os.walk(target_abs_path):
|
|
for fname in subfiles:
|
|
file_path = os.path.relpath(os.path.join(root, fname), parent_path)
|
|
files.append(file_path)
|
|
|
|
return files
|