From 179b6976fa2d99a2256a43a188352a3dfb83ffb9 Mon Sep 17 00:00:00 2001 From: tek Date: Fri, 7 Apr 2023 12:25:30 +0200 Subject: [PATCH] Improves interactionc module --- mvt/ios/modules/mixed/interactionc.py | 322 ++++++++++++++++++-------- 1 file changed, 219 insertions(+), 103 deletions(-) diff --git a/mvt/ios/modules/mixed/interactionc.py b/mvt/ios/modules/mixed/interactionc.py index ddba2bc..ebb8c99 100644 --- a/mvt/ios/modules/mixed/interactionc.py +++ b/mvt/ios/modules/mixed/interactionc.py @@ -17,6 +17,200 @@ INTERACTIONC_BACKUP_IDS = [ INTERACTIONC_ROOT_PATHS = [ "private/var/mobile/Library/CoreDuet/People/interactionC.db", ] +# Taken from APOLLO +# https://github.com/mac4n6/APOLLO/blob/master/modules/interaction_contact_interactions.txt +QUERIES = [ + """SELECT + ZINTERACTIONS.ZSTARTDATE AS "start_date", + ZINTERACTIONS.ZENDDATE AS "end_date", + ZINTERACTIONS.ZBUNDLEID AS "bundle_id", + ZINTERACTIONS.ZACCOUNT AS "account", + ZINTERACTIONS.ZTARGETBUNDLEID AS "target_bundle_id", + CASE ZINTERACTIONS.ZDIRECTION + WHEN '0' THEN 'INCOMING' + WHEN '1' THEN 'OUTGOING' + END 'DIRECTION' AS "direction", + ZCONTACTS.ZDISPLAYNAME AS "sender_display_name", + ZCONTACTS.ZIDENTIFIER AS "sender_identifier", + ZCONTACTS.ZPERSONID AS "sender_personid", + RECEIPIENTCONACT.ZDISPLAYNAME AS "recipient_display_name", + RECEIPIENTCONACT.ZIDENTIFIER AS "recipient_identifier", + RECEIPIENTCONACT.ZPERSONID AS "recipient_personid", + ZINTERACTIONS.ZRECIPIENTCOUNT AS "recipient_count", + ZINTERACTIONS.ZDOMAINIDENTIFIER AS "domain_identifier", + ZINTERACTIONS.ZISRESPONSE AS "is_response", + ZATTACHMENT.ZCONTENTTEXT AS "content", + ZATTACHMENT.ZUTI AS "uti", + ZATTACHMENT.ZCONTENTURL AS "attachment_content_url", + ZATTACHMENT.ZSIZEINBYTES AS "size", + ZATTACHMENT.ZPHOTOLOCALIDENTIFIER AS "photo_local_id", + HEX(ZATTACHMENT.ZIDENTIFIER) AS "attachment_id", + ZATTACHMENT.ZCLOUDIDENTIFIER AS "cloud_id", + ZCONTACTS.ZINCOMINGRECIPIENTCOUNT AS "incoming_recipient_count", + ZCONTACTS.ZINCOMINGSENDERCOUNT AS "incoming_sender_count", + ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT AS "outgoing_recipient_count", + ZINTERACTIONS.ZCREATIONDATE AS "interactions_creation_date", + ZCONTACTS.ZCREATIONDATE AS "contacts_creation_date", + ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE AS "first_incoming_recipient_date", + ZCONTACTS.ZFIRSTINCOMINGSENDERDATE AS "first_incoming_sender_date", + ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE AS "first_outgoing_recipient_date", + ZCONTACTS.ZLASTINCOMINGSENDERDATE AS "last_incoming_sender_date", + ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE AS "last_incoming_recipient_date", + ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE AS "last_outgoing_recipient_date", + ZCONTACTS.ZCUSTOMIDENTIFIER AS "custom_id", + ZINTERACTIONS.ZCONTENTURL AS "interaction_content_url", + ZINTERACTIONS.ZLOCATIONUUID AS "location_uuid", + ZINTERACTIONS.ZGROUPNAME AS "group_name", + ZINTERACTIONS.ZDERIVEDINTENTIDENTIFIER AS "derivied_intent_id", + ZINTERACTIONS.Z_PK AS "table_id" + FROM ZINTERACTIONS + LEFT JOIN ZCONTACTS + ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK + LEFT JOIN Z_1INTERACTIONS + ON ZINTERACTIONS.Z_PK == Z_1INTERACTIONS.Z_3INTERACTIONS + LEFT JOIN ZATTACHMENT + ON Z_1INTERACTIONS.Z_1ATTACHMENTS == ZATTACHMENT.Z_PK + LEFT JOIN Z_2INTERACTIONRECIPIENT + ON ZINTERACTIONS.Z_PK == Z_2INTERACTIONRECIPIENT.Z_3INTERACTIONRECIPIENT + LEFT JOIN ZCONTACTS RECEIPIENTCONACT + ON Z_2INTERACTIONRECIPIENT.Z_2RECIPIENTS == RECEIPIENTCONACT.Z_PK; + """, + """ SELECT + ZINTERACTIONS.ZSTARTDATE AS "start_date", + ZINTERACTIONS.ZENDDATE AS "end_date", + ZINTERACTIONS.ZBUNDLEID AS "bundle_id", + ZINTERACTIONS.ZACCOUNT AS "account", + ZINTERACTIONS.ZTARGETBUNDLEID AS "target_bundle_id", + CASE ZINTERACTIONS.ZDIRECTION + WHEN '0' THEN 'INCOMING' + WHEN '1' THEN 'OUTGOING' + END 'DIRECTION' AS "direction", + ZCONTACTS.ZDISPLAYNAME AS "sender_display_name", + ZCONTACTS.ZIDENTIFIER AS "sender_identifier", + ZCONTACTS.ZPERSONID AS "sender_personid", + RECEIPIENTCONACT.ZDISPLAYNAME AS "recipient_display_name", + RECEIPIENTCONACT.ZIDENTIFIER AS "recipient_identifier", + RECEIPIENTCONACT.ZPERSONID AS "recipient_personid", + ZINTERACTIONS.ZRECIPIENTCOUNT AS "recipient_count", + ZINTERACTIONS.ZDOMAINIDENTIFIER AS "domain_identifier", + ZINTERACTIONS.ZISRESPONSE AS "is_response", + ZATTACHMENT.ZCONTENTTEXT AS "content", + ZATTACHMENT.ZUTI AS "uti", + ZATTACHMENT.ZCONTENTURL AS "attachment_content_url", + ZATTACHMENT.ZSIZEINBYTES AS "size", + HEX(ZATTACHMENT.ZIDENTIFIER) AS "attachment_id", + ZATTACHMENT.ZCLOUDIDENTIFIER AS "cloud_id", + ZCONTACTS.ZINCOMINGRECIPIENTCOUNT AS "incoming_recipient_count", + ZCONTACTS.ZINCOMINGSENDERCOUNT AS "incoming_sender_count", + ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT AS "outgoing_recipient_count", + ZINTERACTIONS.ZCREATIONDATE AS "interactions_creation_date", + ZCONTACTS.ZCREATIONDATE AS "contacts_creation_date", + ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE AS "first_incoming_recipient_date", + ZCONTACTS.ZFIRSTINCOMINGSENDERDATE AS "first_incoming_sender_date", + ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE AS "first_outgoing_recipient_date", + ZCONTACTS.ZLASTINCOMINGSENDERDATE AS "last_incoming_sender_date", + CASE ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE + WHEN '0' THEN '0' + ELSE ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE + END 'LAST INCOMING RECIPIENT DATE' AS "last_incoming_recipient_date", + ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE AS "last_outgoing_recipient_date", + ZCONTACTS.ZCUSTOMIDENTIFIER AS "custom_id", + ZINTERACTIONS.ZCONTENTURL AS "interaction_content_url", + ZINTERACTIONS.ZLOCATIONUUID AS "location_uuid", + ZINTERACTIONS.Z_PK AS "table_id" + FROM + ZINTERACTIONS + LEFT JOIN + ZCONTACTS + ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK + LEFT JOIN Z_1INTERACTIONS ON ZINTERACTIONS.Z_PK == Z_1INTERACTIONS.Z_3INTERACTIONS + LEFT JOIN ZATTACHMENT ON Z_1INTERACTIONS.Z_1ATTACHMENTS == ZATTACHMENT.Z_PK + LEFT JOIN Z_2INTERACTIONRECIPIENT ON ZINTERACTIONS.Z_PK== Z_2INTERACTIONRECIPIENT.Z_3INTERACTIONRECIPIENT + LEFT JOIN ZCONTACTS RECEIPIENTCONACT ON Z_2INTERACTIONRECIPIENT.Z_2RECIPIENTS== RECEIPIENTCONACT.Z_PK + """, + """ SELECT + ZINTERACTIONS.ZSTARTDATE AS "start_date", + ZINTERACTIONS.ZENDDATE AS "end_date", + ZINTERACTIONS.ZBUNDLEID AS "bundle_id", + ZCONTACTS.ZDISPLAYNAME AS "sender_display_name", + ZCONTACTS.ZIDENTIFIER AS "sender_identifier", + ZCONTACTS.ZPERSONID AS "sender_personid", + ZINTERACTIONS.ZDIRECTION AS "direction", + ZINTERACTIONS.ZISRESPONSE AS "is_response", + ZINTERACTIONS.ZMECHANISM AS "mechanism", + ZINTERACTIONS.ZRECIPIENTCOUNT AS "recipient_count", + ZINTERACTIONS.ZCREATIONDATE AS "interactions_creation_date", + ZCONTACTS.ZCREATIONDATE AS "contacts_creation_date", + ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE AS "first_incoming_recipient_date", + ZCONTACTS.ZFIRSTINCOMINGSENDERDATE AS "first_incoming_sender_date", + ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE AS "first_outgoing_recipient_date", + ZCONTACTS.ZLASTINCOMINGSENDERDATE AS "last_incoming_sender_date", + CASE + ZLASTINCOMINGRECIPIENTDATE + WHEN + '0' + THEN + '0' + ELSE + ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE + END AS "last_incoming_recipient_date", + ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE AS "last_outgoing_recipient_date", + ZINTERACTIONS.ZACCOUNT AS 'account', + ZINTERACTIONS.ZDOMAINIDENTIFIER AS "domain_identifier", + ZCONTACTS.ZINCOMINGRECIPIENTCOUNT AS "incoming_recipient_count", + ZCONTACTS.ZINCOMINGSENDERCOUNT AS "incoming_sender_count", + ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT AS "outgoing_recipient_count", + ZCONTACTS.ZCUSTOMIDENTIFIER AS "custom_id", + ZINTERACTIONS.ZCONTENTURL AS "interaction_content_url", + ZINTERACTIONS.ZLOCATIONUUID AS "location_uuid", + ZINTERACTIONS.Z_PK AS "table_id" + FROM + ZINTERACTIONS + LEFT JOIN + ZCONTACTS + ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK + """, + """ SELECT + ZINTERACTIONS.ZSTARTDATE AS "start_date", + ZINTERACTIONS.ZENDDATE AS "end_date", + ZINTERACTIONS.ZCREATIONDATE AS "interactions_creation_date", + ZINTERACTIONS.ZBUNDLEID AS "bundle_id", + ZCONTACTS.ZDISPLAYNAME AS "sender_display_name", + ZCONTACTS.ZIDENTIFIER AS "sender_identifier", + ZCONTACTS.ZPERSONID AS "sender_personid", + ZINTERACTIONS.ZDIRECTION AS "direction", + ZINTERACTIONS.ZISRESPONSE AS "is_response", + ZINTERACTIONS.ZMECHANISM AS "mechanism", + ZCONTACTS.ZCREATIONDATE AS "contacts_creation_date", + ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE AS "first_incoming_recipient_date", + ZCONTACTS.ZFIRSTINCOMINGSENDERDATE AS "first_incoming_sender_date", + ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE AS "first_outgoing_recipient_date", + ZCONTACTS.ZLASTINCOMINGSENDERDATE AS "last_incoming_sender_date", + CASE + ZLASTINCOMINGRECIPIENTDATE + WHEN + '0' + THEN + '0' + ELSE + ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE + END AS "last_incoming_recipient_date", + ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE AS "last_outgoing_recipient_date", + ZINTERACTIONS.ZACCOUNT AS "account", + ZINTERACTIONS.ZDOMAINIDENTIFIER AS "domain_identifier", + ZCONTACTS.ZINCOMINGRECIPIENTCOUNT AS "incoming_recipient_count", + ZCONTACTS.ZINCOMINGSENDERCOUNT AS "incoming_sender_count", + ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT AS "outgoing_recipient_count", + ZINTERACTIONS.ZCONTENTURL AS "interaction_content_url", + ZINTERACTIONS.ZLOCATIONUUID AS "location_uuid", + ZINTERACTIONS.Z_PK AS "table_id" + FROM + ZINTERACTIONS + LEFT JOIN + ZCONTACTS + ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK + """ +] class InteractionC(IOSExtraction): @@ -66,8 +260,8 @@ class InteractionC(IOSExtraction): "event": timestamp, "data": f"[{record['bundle_id']}] {record['account']} - " f"from {record['sender_display_name']} ({record['sender_identifier']}) " - f"to {record['recipient_display_name']} ({record['recipient_identifier']}):" - f" {record['content']}" + f"to {record.get('recipient_display_name', '')} ({record.get('recipient_identifier', '')}):" + f" {record.get('content', '')}" }) processed.append(record[timestamp]) @@ -81,108 +275,30 @@ class InteractionC(IOSExtraction): conn = sqlite3.connect(self.file_path) cur = conn.cursor() - # TODO: Support all versions. - # Taken from: - # https://github.com/mac4n6/APOLLO/blob/master/modules/interaction_contact_interactions.txt - cur.execute(""" - SELECT - ZINTERACTIONS.ZSTARTDATE, - ZINTERACTIONS.ZENDDATE, - ZINTERACTIONS.ZBUNDLEID, - ZINTERACTIONS.ZACCOUNT, - ZINTERACTIONS.ZTARGETBUNDLEID, - CASE ZINTERACTIONS.ZDIRECTION - WHEN '0' THEN 'INCOMING' - WHEN '1' THEN 'OUTGOING' - END 'DIRECTION', - ZCONTACTS.ZDISPLAYNAME, - ZCONTACTS.ZIDENTIFIER, - ZCONTACTS.ZPERSONID, - RECEIPIENTCONACT.ZDISPLAYNAME, - RECEIPIENTCONACT.ZIDENTIFIER, - RECEIPIENTCONACT.ZPERSONID, - ZINTERACTIONS.ZRECIPIENTCOUNT, - ZINTERACTIONS.ZDOMAINIDENTIFIER, - ZINTERACTIONS.ZISRESPONSE, - ZATTACHMENT.ZCONTENTTEXT, - ZATTACHMENT.ZUTI, - ZATTACHMENT.ZCONTENTURL, - ZATTACHMENT.ZSIZEINBYTES, - ZATTACHMENT.ZPHOTOLOCALIDENTIFIER, - HEX(ZATTACHMENT.ZIDENTIFIER), - ZATTACHMENT.ZCLOUDIDENTIFIER, - ZCONTACTS.ZINCOMINGRECIPIENTCOUNT, - ZCONTACTS.ZINCOMINGSENDERCOUNT, - ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT, - ZINTERACTIONS.ZCREATIONDATE, - ZCONTACTS.ZCREATIONDATE, - ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE, - ZCONTACTS.ZFIRSTINCOMINGSENDERDATE, - ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE, - ZCONTACTS.ZLASTINCOMINGSENDERDATE, - ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE, - ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE, - ZCONTACTS.ZCUSTOMIDENTIFIER, - ZINTERACTIONS.ZCONTENTURL, - ZINTERACTIONS.ZLOCATIONUUID, - ZINTERACTIONS.ZGROUPNAME, - ZINTERACTIONS.ZDERIVEDINTENTIDENTIFIER, - ZINTERACTIONS.Z_PK - FROM ZINTERACTIONS - LEFT JOIN ZCONTACTS - ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK - LEFT JOIN Z_1INTERACTIONS - ON ZINTERACTIONS.Z_PK == Z_1INTERACTIONS.Z_3INTERACTIONS - LEFT JOIN ZATTACHMENT - ON Z_1INTERACTIONS.Z_1ATTACHMENTS == ZATTACHMENT.Z_PK - LEFT JOIN Z_2INTERACTIONRECIPIENT - ON ZINTERACTIONS.Z_PK == Z_2INTERACTIONRECIPIENT.Z_3INTERACTIONRECIPIENT - LEFT JOIN ZCONTACTS RECEIPIENTCONACT - ON Z_2INTERACTIONRECIPIENT.Z_2RECIPIENTS == RECEIPIENTCONACT.Z_PK; - """) - # names = [description[0] for description in cur.description] + try: + cur.execute(QUERIES[0]) + except sqlite3.OperationalError: + try: + cur.execute(QUERIES[1]) + except sqlite3.OperationalError: + try: + cur.execute(QUERIES[2]) + except sqlite3.OperationalError: + cur.execute(QUERIES[3]) - for row in cur: - self.results.append({ - "start_date": convert_mactime_to_iso(row[0]), - "end_date": convert_mactime_to_iso(row[1]), - "bundle_id": row[2], - "account": row[3], - "target_bundle_id": row[4], - "direction": row[5], - "sender_display_name": row[6], - "sender_identifier": row[7], - "sender_personid": row[8], - "recipient_display_name": row[9], - "recipient_identifier": row[10], - "recipient_personid": row[11], - "recipient_count": row[12], - "domain_identifier": row[13], - "is_response": row[14], - "content": row[15], - "uti": row[16], - "content_url": row[17], - "size": row[18], - "photo_local_id": row[19], - "attachment_id": row[20], - "cloud_id": row[21], - "incoming_recipient_count": row[22], - "incoming_sender_count": row[23], - "outgoing_recipient_count": row[24], - "interactions_creation_date": convert_mactime_to_iso(row[25]) if row[25] else None, - "contacts_creation_date": convert_mactime_to_iso(row[26]) if row[26] else None, - "first_incoming_recipient_date": convert_mactime_to_iso(row[27]) if row[27] else None, - "first_incoming_sender_date": convert_mactime_to_iso(row[28]) if row[28] else None, - "first_outgoing_recipient_date": convert_mactime_to_iso(row[29]) if row[29] else None, - "last_incoming_sender_date": convert_mactime_to_iso(row[30]) if row[30] else None, - "last_incoming_recipient_date": convert_mactime_to_iso(row[31]) if row[31] else None, - "last_outgoing_recipient_date": convert_mactime_to_iso(row[32]) if row[32] else None, - "custom_id": row[33], - "location_uuid": row[35], - "group_name": row[36], - "derivied_intent_id": row[37], - "table_id": row[38] - }) + names = [description[0] for description in cur.description] + for item in cur: + entry = {} + for index, value in enumerate(item): + if names[index] in self.timestamps: + if value is None or isinstance(value, str): + entry[names[index]] = value + else: + entry[names[index]] = convert_mactime_to_iso(value) + else: + entry[names[index]] = value + + self.results.append(entry) cur.close() conn.close()