diff --git a/scripts/artifacts/callHistory.py b/scripts/artifacts/callHistory.py index 21e6645c1..6c1f5a53f 100644 --- a/scripts/artifacts/callHistory.py +++ b/scripts/artifacts/callHistory.py @@ -7,7 +7,7 @@ "last_update_date": "2026-07-31", "requirements": "none", "category": "Call History", - "notes": "Call type and disconnected-cause value mappings are community-established decodes reported as observed; unrecognized values are reported as stored.", + "notes": 'Call type and disconnected-cause value mappings are community-established decodes reported as observed; unrecognized values are reported as stored. When both CallHistory.storedata and CallHistoryTemp.storedata hold records, rows from both are reported with a Source File path column and the report names both stores. On none of the nine registered corpora run did both stores hold records, so that path was exercised on a constructed tree with the same records under both names.', "paths": ( '*/mobile/Library/CallHistoryDB/CallHistory*', '*/mobile/Library/CallHistoryDB/call_history.db*'), @@ -129,7 +129,7 @@ def callHistory(context): temp_db_records = list( get_sqlite_db_records(temp_db_path, query) ) if db_path or temp_db_path: if db_records and temp_db_records: - source_path = "Source file path in the report below" + source_path = '\n'.join([db_path, temp_db_path]) records_in_both_db = True records = [tuple(list(record) + [db_path]) for record in db_records] + [tuple(list(record) + [temp_db_path]) for record in temp_db_records] else: diff --git a/scripts/artifacts/united_airlines.py b/scripts/artifacts/united_airlines.py index a920991b1..e13634eb3 100644 --- a/scripts/artifacts/united_airlines.py +++ b/scripts/artifacts/united_airlines.py @@ -176,12 +176,12 @@ "last_update_date": "2026-07-31", "requirements": "none", "category": "United Airlines", + "sample_data": {'abe_ios16': 'iOS 16.5 | 0 rows'}, "notes": ( - "Core Data table: ZUACDINFLIGHTMEDIA; also app prefs " - "com.united.UnitedCustomerFacingIPhone.plist (.mpd / MOV_* resume keys)." + 'Core Data table: ZUACDINFLIGHTMEDIA; also app prefs com.united.UnitedCustomerFacingIPhone.plist (.mpd / MOV_* resume keys). On abe_ios16 the Core Data store is read and its ZUACDINFLIGHTMEDIA table is present with no rows. The preferences plist was not found on any of the 21 registered corpora whose listings were checked, so the preferences branch is unexercised.' ), "paths": ( - "*/UnitediPhoneCoreData.sqlite*" + "*/UnitediPhoneCoreData.sqlite*", "*/com.united.UnitedCustomerFacingIPhone/Library/Preferences/" "com.united.UnitedCustomerFacingIPhone.plist", ), diff --git a/scripts/artifacts/voicemail.py b/scripts/artifacts/voicemail.py index 6d929240e..2179a762d 100644 --- a/scripts/artifacts/voicemail.py +++ b/scripts/artifacts/voicemail.py @@ -7,8 +7,7 @@ 'last_update_date': '2026-07-31', 'requirements': "none", 'category': 'Call History', - 'notes': "Reference: A. Hoog & K. Strzempka, 'iPhone and iOS Forensics' (Syngress, " - "2011), voicemail.db flags: 67 = old, 75 = deleted, 3 = recent.", + 'notes': "Reference: A. Hoog & K. Strzempka, 'iPhone and iOS Forensics' (Syngress, 2011), voicemail.db flags: 67 = old, 75 = deleted, 3 = recent. When no voicemail.db is present, one row is reported per audio file with its transcript matched by file stem, and the report names the audio and transcript files read. The 19 registered corpora found to carry voicemail files all carry the database as well, so that path was exercised on a constructed tree of audio and transcript files without it.", 'paths': ( '*/mobile/Library/Voicemail/voicemail.db*', '*/mobile/Library/Voicemail/*.amr', @@ -150,13 +149,14 @@ def voicemail(context): transcription_confidence)) else: - source_file = 'See Filename Column' + source_paths = [] transcriptions_map = {} for transcript_path in extracted_transcript_files: t_id = Path(transcript_path).stem try: pl = get_plist_file_content(transcript_path) transcriptions_map[t_id] = pl + source_paths.append(transcript_path) except (OSError, TypeError, ValueError): continue @@ -185,10 +185,12 @@ def voicemail(context): transcription_string, confidence )) + source_paths.append(audio_file_path) data_headers = ( ('File Created', 'datetime'), ('File Modified', 'datetime'), 'Audio Filename', ('Audio File', 'media'), 'Transcript', 'Transcript confidence') + source_file = '\n'.join(source_paths) return data_headers, data_list, source_file