From 3236c1b3906fc58e4ef7d4eaf3d9980fbc51dc18 Mon Sep 17 00:00:00 2001 From: Nex Date: Thu, 9 Sep 2021 12:00:48 +0200 Subject: [PATCH] Added new TCC module --- docs/ios/records.md | 10 ++++ mvt/ios/modules/mixed/__init__.py | 3 +- mvt/ios/modules/mixed/tcc.py | 90 +++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 mvt/ios/modules/mixed/tcc.py diff --git a/docs/ios/records.md b/docs/ios/records.md index 66a85fa..3588e45 100644 --- a/docs/ios/records.md +++ b/docs/ios/records.md @@ -252,6 +252,16 @@ This JSON file is created by mvt-ios' `SMSAttachments` module. The module extrac --- +### `tcc.json` + +!!! info "Availability" + Backup: :material-check: + Full filesystem dump: :material-check: + +This JSON file is created by mvt-ios' `TCC` module. The module extracts records from a SQLite database located at */private/var/mobile/Library/TCC/TCC.db*, which contains a list of which services such as microphone, camera, or location, apps have been granted or denied access to. + +--- + ### `version_history.json` !!! info "Availability" diff --git a/mvt/ios/modules/mixed/__init__.py b/mvt/ios/modules/mixed/__init__.py index a7d59c8..5eb0070 100644 --- a/mvt/ios/modules/mixed/__init__.py +++ b/mvt/ios/modules/mixed/__init__.py @@ -18,6 +18,7 @@ from .safari_browserstate import SafariBrowserState from .safari_history import SafariHistory from .sms import SMS from .sms_attachments import SMSAttachments +from .tcc import TCC from .webkit_resource_load_statistics import WebkitResourceLoadStatistics from .webkit_session_resource_log import WebkitSessionResourceLog from .whatsapp import Whatsapp @@ -25,5 +26,5 @@ from .whatsapp import Whatsapp MIXED_MODULES = [Calls, ChromeFavicon, ChromeHistory, Contacts, FirefoxFavicon, FirefoxHistory, IDStatusCache, InteractionC, LocationdClients, OSAnalyticsADDaily, Datausage, SafariBrowserState, SafariHistory, - SMS, SMSAttachments, WebkitResourceLoadStatistics, + TCC, SMS, SMSAttachments, WebkitResourceLoadStatistics, WebkitSessionResourceLog, Whatsapp,] diff --git a/mvt/ios/modules/mixed/tcc.py b/mvt/ios/modules/mixed/tcc.py new file mode 100644 index 0000000..f024f5c --- /dev/null +++ b/mvt/ios/modules/mixed/tcc.py @@ -0,0 +1,90 @@ +# 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/ + +import sqlite3 +from datetime import datetime + +from mvt.common.utils import convert_timestamp_to_iso + +from ..base import IOSExtraction + +TCC_BACKUP_IDS = [ + "64d0019cb3d46bfc8cce545a8ba54b93e7ea9347", +] +TCC_ROOT_PATHS = [ + "private/var/mobile/Library/TCC/TCC.db", +] + +AUTH_VALUES = { + 0: "denied", + 1: "unknown", + 2: "allowed", + 3: "limited", +} +AUTH_REASONS = { + 1: "error", + 2: "user_consent", + 3: "user_set", + 4: "system_set", + 5: "service_policy", + 6: "mdm_policy", + 7: "override_policy", + 8: "missing_usage_string", + 9: "prompt_timeout", + 10: "preflight_unknown", + 11: "entitled", + 12: "app_type_policy", +} + +class TCC(IOSExtraction): + """This module extracts records from the TCC.db SQLite database.""" + + 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 process_db(self, file_path): + conn = sqlite3.connect(file_path) + cur = conn.cursor() + cur.execute("""SELECT + service, client, client_type, auth_value, auth_reason, last_modified + FROM access;""") + + for row in cur: + service = row[0] + client = row[1] + client_type = row[2] + client_type_desc = "bundle_id" if client_type == 0 else "absolute_path" + auth_value = row[3] + auth_value_desc = AUTH_VALUES.get(auth_value, "") + auth_reason = row[4] + auth_reason_desc = AUTH_REASONS.get(auth_reason, "unknown") + last_modified = convert_timestamp_to_iso(datetime.utcfromtimestamp((row[5]))) + + if service in ["kTCCServiceMicrophone", "kTCCServiceCamera"]: + device = "microphone" if service == "kTCCServiceMicrophone" else "camera" + self.log.info("Found client \"%s\" with access %s to %s on %s by %s", + client, auth_value_desc, device, last_modified, auth_reason_desc) + + self.results.append({ + "service": service, + "client": client, + "client_type": client_type_desc, + "auth_value": auth_value_desc, + "auth_reason_desc": auth_reason_desc, + "last_modified": last_modified, + }) + + cur.close() + conn.close() + + def run(self): + self._find_ios_database(backup_ids=TCC_BACKUP_IDS, root_paths=TCC_ROOT_PATHS) + self.log.info("Found TCC database at path: %s", self.file_path) + self.process_db(self.file_path) + + self.log.info("Extracted a total of %d TCC items", len(self.results))