diff --git a/scripts/artifacts/appItunesmeta.py b/scripts/artifacts/appItunesmeta.py index aaa1787e1..ff935f023 100644 --- a/scripts/artifacts/appItunesmeta.py +++ b/scripts/artifacts/appItunesmeta.py @@ -3,121 +3,92 @@ "name": "Apps - Itunes Metadata", "description": "iTunes & Bundle ID Metadata contents for apps", "author": "@AlexisBrignoni", - "version": "0.2", - "date": "2020-10-04", + "creation_date": "2020-10-04", + "last_update_date": "2025-12-16", "requirements": "none", "category": "Installed Apps", "notes": "", - "paths": ('*/iTunesMetadata.plist', '**/BundleMetadata.plist',), - "function": "get_appItunesmeta", + "paths": ('*/iTunesMetadata.plist', '*/BundleMetadata.plist',), "output_types": "standard" } } -import biplist import pathlib import os -import nska_deserialize as nd -import plistlib -import sys -from datetime import * -import pytz - -#from scripts.artifact_report import ArtifactHtmlReport -#from scripts.ilapfuncs import logfunc, tsv, timeline, is_platform_windows -from scripts.ilapfuncs import artifact_processor, convert_ts_human_to_timezone_offset, convert_time_obj_to_utc - -def convert_plist_date_to_timezone_offset_b(plist_date, timezone_offset): - if plist_date: - plist_date = datetime.strptime(plist_date, '%Y-%m-%dT%H:%M:%SZ') - iso_date = plist_date.strftime("%Y-%m-%d %H:%M:%S") - - return convert_ts_human_to_timezone_offset(iso_date, timezone_offset) - else: - return plist_date - +from scripts.ilapfuncs import artifact_processor, convert_time_obj_to_utc, convert_plist_date_to_utc, get_plist_file_content @artifact_processor -def get_appItunesmeta(files_found, report_folder, seeker, wrap_text, timezone_offset): +def get_appItunesmeta(context): data_list = [] - for file_found in files_found: + for file_found in context.get_files_found(): file_found = str(file_found) if file_found.endswith('iTunesMetadata.plist'): - with open(file_found, "rb") as fp: - if sys.version_info >= (3, 9): - plist = plistlib.load(fp) - else: - plist = biplist.readPlist(fp) - - purchasedate = plist.get('com.apple.iTunesStore.downloadInfo', {}).get('purchaseDate', '') - #print(purchasedate, timezone_offset) - purchasedate = convert_plist_date_to_timezone_offset_b(purchasedate, timezone_offset) + # with open(file_found, "rb") as fp: + # if sys.version_info >= (3, 9): + # plist = plistlib.load(fp) + # else: + # plist = biplist.readPlist(fp) + + plist = get_plist_file_content(file_found) + + # Check if plist is a valid parseable object + if not plist or not isinstance(plist, dict): + continue - bundleid = plist.get('softwareVersionBundleId', '') - itemname = plist.get('itemName', '') - artistname = plist.get('artistName', '') - versionnum = plist.get('bundleShortVersionString', '') - downloadedby = plist.get('com.apple.iTunesStore.downloadInfo', {}) .get('accountInfo', {}).get('AppleID', '') - genre = plist.get('genre', '') - factoryinstall = plist.get('isFactoryInstall', '') - appreleasedate = plist.get('releaseDate', '') - appreleasedate = convert_plist_date_to_timezone_offset_b(appreleasedate, timezone_offset) - sourceapp = plist.get('sourceApp', '') - sideloaded = plist.get('sideLoadedDeviceBasedVPP', '') - variantid = plist.get('variantID', '') - - p = pathlib.Path(file_found) - parent = p.parent - parent = str(parent) + purchasedate = plist.get('com.apple.iTunesStore.downloadInfo', {}).get('purchaseDate', '') + #print(purchasedate, timezone_offset) + purchasedate = convert_plist_date_to_utc(purchasedate) + + bundleid = plist.get('softwareVersionBundleId', '') + itemname = plist.get('itemName', '') + artistname = plist.get('artistName', '') + versionnum = plist.get('bundleShortVersionString', '') + downloadedby = plist.get('com.apple.iTunesStore.downloadInfo', {}) .get('accountInfo', {}).get('AppleID', '') + genre = plist.get('genre', '') + factoryinstall = plist.get('isFactoryInstall', '') + appreleasedate = plist.get('releaseDate', '') + appreleasedate = convert_plist_date_to_utc(appreleasedate) + sourceapp = plist.get('sourceApp', '') + sideloaded = plist.get('sideLoadedDeviceBasedVPP', '') + variantid = plist.get('variantID', '') + + p = pathlib.Path(file_found) + parent = p.parent + parent = str(parent) - itunes_metadata_path = (os.path.join(parent, "BundleMetadata.plist")) - if os.path.exists(itunes_metadata_path): - with open(itunes_metadata_path, 'rb') as f: - deserialized_plist = nd.deserialize_plist(f) - install_date = deserialized_plist.get('installDate', '') - #print(install_date, type(install_date)) - install_date = convert_time_obj_to_utc(install_date) - else: + itunes_metadata_path = (os.path.join(parent, "BundleMetadata.plist")) + if os.path.exists(itunes_metadata_path): + #with open(itunes_metadata_path, 'rb') as f: + deserialized_plist = get_plist_file_content(itunes_metadata_path) + # Check if deserialized_plist is a valid parseable object + if not deserialized_plist or not isinstance(deserialized_plist, dict): install_date = '' - - data_list.append((install_date, purchasedate, bundleid, itemname, artistname, versionnum, downloadedby, genre, factoryinstall, appreleasedate, sourceapp, sideloaded, variantid, parent)) + else: + install_date = deserialized_plist.get('installDate', '') + #print(install_date, type(install_date)) + install_date = convert_time_obj_to_utc(install_date) + else: + install_date = '' + + data_list.append((install_date, purchasedate, bundleid, itemname, artistname, versionnum, downloadedby, genre, factoryinstall, appreleasedate, sourceapp, sideloaded, variantid, parent)) - if len(data_list) > 0: - fileloc = 'See source file location column' - """ - description = 'iTunes & Bundle ID Metadata contents for apps' - report = ArtifactHtmlReport('Apps - Itunes & Bundle Metadata') - report.start_artifact_report(report_folder, 'Apps - Itunes Metadata', description) - report.add_script() - data_headers = ('Installed Date', 'App Purchase Date','Bundle ID', 'Item Name', 'Artist Name', 'Version Number', 'Downloaded by', 'Genre', 'Factory Install', 'App Release Date', 'Source App', 'Sideloaded?', 'Variant ID', 'Source File Location') - report.write_artifact_data_table(data_headers, data_list, fileloc) - report.end_artifact_report() - - tsvname = 'Apps - Itunes Bundle Metadata' - tsv(report_folder, data_headers, data_list, tsvname) - - tlactivity = 'Apps - Itunes Bundle Metadata' - timeline(report_folder, tlactivity, data_list, data_headers) - else: - logfunc('No data on Apps - Itunes Bundle Metadata') - """ - data_headers = ( - ('Installed Date','datetime'), - ('App Purchase Date','datetime'), - 'Bundle ID', - 'Item Name', - 'Artist Name', - 'Version Number', - 'Downloaded by', - 'Genre', - 'Factory Install', - 'App Release Date', - 'Source App', - 'Sideloaded?', - 'Variant ID', - 'Source File Location') - return data_headers, data_list, fileloc + data_headers = ( + ('Installed Date','datetime'), + ('App Purchase Date','datetime'), + 'Bundle ID', + 'Item Name', + 'Artist Name', + 'Version Number', + 'Downloaded by', + 'Genre', + 'Factory Install', + 'App Release Date', + 'Source App', + 'Sideloaded?', + 'Variant ID', + 'Source File Location') + return data_headers, data_list, 'see Source File Location' diff --git a/scripts/artifacts/appleAlarms.py b/scripts/artifacts/appleAlarms.py index e2e461e3e..663bdfe53 100644 --- a/scripts/artifacts/appleAlarms.py +++ b/scripts/artifacts/appleAlarms.py @@ -4,7 +4,7 @@ "description": "Extraction of alarms set", "author": "Anna-Mariya Mateyna", "creation_date": "2021-01-17", - "last_update_date": "2024-12-22", + "last_update_date": "2025-12-16", "requirements": "none", "category": "Clock", "notes": "", @@ -14,7 +14,7 @@ } } -from scripts.ilapfuncs import artifact_processor, get_file_path, get_plist_file_content, convert_plist_date_to_utc +from scripts.ilapfuncs import artifact_processor, get_file_path, get_plist_file_content, convert_plist_date_to_utc, logfunc def decode_repeat_schedule(repeat_schedule_value): days_list = { @@ -43,15 +43,21 @@ def decode_repeat_schedule(repeat_schedule_value): @artifact_processor -def alarms(files_found, report_folder, seeker, wrap_text, timezone_offset): +def alarms(context): + files_found = context.get_files_found() source_path = get_file_path(files_found, "com.apple.mobiletimerd.plist") data_list = [] pl = get_plist_file_content(source_path) + + # Check if plist is valid before processing + if not pl or not isinstance(pl, dict): + return (), [], '' + if 'MTAlarms' in pl: if 'MTAlarms' in pl['MTAlarms']: - for alarms in pl['MTAlarms']['MTAlarms']: - alarms_dict = alarms['$MTAlarm'] + for alarm in pl['MTAlarms']['MTAlarms']: + alarms_dict = alarm['$MTAlarm'] alarm_title = alarms_dict.get('MTAlarmTitle', 'Alarm') alarm_hour = alarms_dict.get('MTAlarmHour', '') @@ -82,6 +88,7 @@ def alarms(files_found, report_folder, seeker, wrap_text, timezone_offset): if 'MTSleepAlarm' in pl['MTAlarms']: for sleep_alarms in pl['MTAlarms']['MTSleepAlarm']: + logfunc(sleep_alarms) sleep_alarm_dict = pl['MTAlarms']['MTSleepAlarm'][sleep_alarms] alarm_title = sleep_alarm_dict.get('MTAlarmTitle', 'Bedtime') @@ -95,6 +102,7 @@ def alarms(files_found, report_folder, seeker, wrap_text, timezone_offset): data_list.append( (fire_date, + None, # alarm time alarm_title, sleep_alarm_dict['MTAlarmEnabled'], dismiss_date, diff --git a/scripts/artifacts/appleLocationd.py b/scripts/artifacts/appleLocationd.py index 1b8293b18..8d772fe8b 100644 --- a/scripts/artifacts/appleLocationd.py +++ b/scripts/artifacts/appleLocationd.py @@ -4,7 +4,7 @@ "description": "Extracts location services settings", "author": "@AlexisBrignoni", "creation_date": "2023-10-03", - "last_update_date": "2024-12-20", + "last_update_date": "2025-10-08", "requirements": "none", "category": "Identifiers", "notes": "", @@ -17,11 +17,17 @@ from scripts.ilapfuncs import artifact_processor, get_file_path, get_plist_file_content, device_info, convert_cocoa_core_data_ts_to_utc @artifact_processor -def appleLocationd(files_found, report_folder, seeker, wrap_text, timezone_offset): +def appleLocationd(context): + files_found = context.get_files_found() source_path = get_file_path(files_found, "com.apple.locationd.plist") data_list = [] pl = get_plist_file_content(source_path) + + # Check if plist is valid before processing + if not pl or not isinstance(pl, dict): + return (), [], '' + for key, val in pl.items(): if key == 'LocationServicesEnabledIn8.0': data_list.append(('Location Services Enabled', val)) diff --git a/scripts/artifacts/appleMapsApplication.py b/scripts/artifacts/appleMapsApplication.py index 9b09047e0..edf7331e2 100644 --- a/scripts/artifacts/appleMapsApplication.py +++ b/scripts/artifacts/appleMapsApplication.py @@ -4,7 +4,7 @@ "description": "", "author": "@AlexisBrignoni", "creation_date": "2020-08-03", - "last_update_date": "2024-12-20", + "last_update_date": "2025-10-08", "requirements": "none", "category": "Locations", "notes": "", @@ -19,12 +19,17 @@ from scripts.ilapfuncs import artifact_processor, get_file_path, get_plist_file_content @artifact_processor -def appleMapsApplication(files_found, report_folder, seeker, wrap_text, timezone_offset): +def appleMapsApplication(context): + files_found = context.get_files_found() source_path = get_file_path(files_found, "com.apple.Maps.plist") data_list = [] plist = get_plist_file_content(source_path) + # Check if plist is valid before processing + if not plist or not isinstance(plist, dict): + return (), [], '' + types = {'1': {'type': 'double', 'name': 'Latitude'}, '2': {'type': 'double', 'name': 'Longitude'}, '3': {'type': 'double', 'name': ''}, diff --git a/scripts/artifacts/appleMapsGroup.py b/scripts/artifacts/appleMapsGroup.py index 26f60c3f7..bf7733c56 100644 --- a/scripts/artifacts/appleMapsGroup.py +++ b/scripts/artifacts/appleMapsGroup.py @@ -4,7 +4,7 @@ "description": "", "author": "@AlexisBrignoni", "creation_date": "2020-08-03", - "last_update_date": "2025-01-21", + "last_update_date": "2025-12-16", "requirements": "none", "category": "Locations", "notes": "", @@ -18,11 +18,15 @@ from scripts.ilapfuncs import artifact_processor, get_file_path, get_plist_file_content @artifact_processor -def appleMapsGroup(files_found, report_folder, seeker, wrap_text, timezone_offset): +def appleMapsGroup(context): + files_found = context.get_files_found() source_path = get_file_path(files_found, "group.com.apple.Maps.plist") data_list = [] pl = get_plist_file_content(source_path) + # Check if plist is valid before processing + if not pl or not isinstance(pl, dict): + return (), [], '' maps_activity = pl.get('MapsActivity', None) if maps_activity: types = {'1': {'type': 'message', 'message_typedef': @@ -38,7 +42,7 @@ def appleMapsGroup(files_found, report_folder, seeker, wrap_text, timezone_offse '7': {'type': 'int', 'name': ''}}, 'name': ''} } - internal_deserialized_plist, di = blackboxprotobuf.decode_message(maps_activity, types) + internal_deserialized_plist, _ = blackboxprotobuf.decode_message(maps_activity, types) latitude = (internal_deserialized_plist['1']['5']['Latitude']) longitude = (internal_deserialized_plist['1']['5']['Longitude']) data_list.append((latitude, longitude))