diff --git a/mvt/ios/modules/mixed/tcc.py b/mvt/ios/modules/mixed/tcc.py index d5f89cd..4829ba1 100644 --- a/mvt/ios/modules/mixed/tcc.py +++ b/mvt/ios/modules/mixed/tcc.py @@ -17,6 +17,11 @@ TCC_ROOT_PATHS = [ "private/var/mobile/Library/TCC/TCC.db", ] +AUTH_VALUE_OLD = { + 0: "denied", + 1: "allowed" +} + AUTH_VALUES = { 0: "denied", 1: "unknown", @@ -51,34 +56,80 @@ class TCC(IOSExtraction): 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;""") + db_version = "v3" + try: + cur.execute("""SELECT + service, client, client_type, auth_value, auth_reason, last_modified + FROM access;""") + except sqlite3.OperationalError: + # v2 version + try: + cur.execute("""SELECT + service, client, client_type, allowed, prompt_count, last_modified + FROM access;""") + db_version = "v2" + except sqlite3.OperationalError: + cur.execute("""SELECT + service, client, client_type, allowed, prompt_count + FROM access;""") + db_version = "v1" + 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 db_version == "v3": + 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) + 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, - }) + 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, + }) + else: + allowed_value = row[3] + allowed_desc = AUTH_VALUE_OLD.get(allowed_value, "") + prompt_count = row[4] + if db_version == "v2": + 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 at %s", + client, allowed_desc, device, last_modified) + self.results.append({ + "service": service, + "client": client, + "client_type": client_type_desc, + "allowed_value": allowed_desc, + "prompt_count": prompt_count, + "last_modified": last_modified + }) + else: + if service in ["kTCCServiceMicrophone", "kTCCServiceCamera"]: + device = "microphone" if service == "kTCCServiceMicrophone" else "camera" + self.log.info("Found client \"%s\" with access %s to %s", + client, allowed_desc, device) + self.results.append({ + "service": service, + "client": client, + "client_type": client_type_desc, + "allowed_value": allowed_desc, + "prompt_count": prompt_count + }) cur.close() conn.close()