diff --git a/scripts/artifacts/DataUsage.py b/scripts/artifacts/DataUsage.py index 4de4cc5a0..41d251205 100644 --- a/scripts/artifacts/DataUsage.py +++ b/scripts/artifacts/DataUsage.py @@ -3,9 +3,8 @@ "name": "Data Usage", "description": "Parses application network data usage", "author": "@KevinPagano3", - "version": "0.0.1", "creation_date": "2023-10-10", - "last_update_date": "2025-02-04", + "last_update_date": "2025-11-21", "requirements": "none", "category": "Network Usage", "notes": "", @@ -14,17 +13,14 @@ } } -import sqlite3 - from scripts.ilapfuncs import artifact_processor -from scripts.ilapfuncs import logfunc, tsv, timeline, is_platform_windows, open_sqlite_db_readonly, does_column_exist_in_db, convert_cocoa_core_data_ts_to_utc +from scripts.ilapfuncs import logfunc, open_sqlite_db_readonly, does_column_exist_in_db, convert_cocoa_core_data_ts_to_utc @artifact_processor -def get_DataUsage(files_found, report_folder, seeker, wrap_text, timezone_offset): - +def get_DataUsage(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('.sqlite'): @@ -62,7 +58,11 @@ def get_DataUsage(files_found, report_folder, seeker, wrap_text, timezone_offset process_split = row[4].split('/') data_list.append((lastconnected,firstused,lastused,row[3],process_split[0],row[5],row[6],row[7],row[8],row[9])) - data_headers = ((('Last Connect Timestamp','datetime'),('First Usage Timestamp','datetime'),('Last Usage Timestamp','datetime'),'Bundle Name','Process Name','Entry Type','Wifi In (Bytes)','Wifi Out (Bytes)','Mobile/WWAN In (Bytes)','Mobile/WWAN Out (Bytes)')) + db.close() + + data_headers = (('Last Connect Timestamp','datetime'), ('First Usage Timestamp','datetime'), ('Last Usage Timestamp','datetime'), + 'Bundle Name', 'Process Name', 'Entry Type', 'Wifi In (Bytes)', 'Wifi Out (Bytes)', 'Mobile/WWAN In (Bytes)', + 'Mobile/WWAN Out (Bytes)') return data_headers, data_list, file_found else: @@ -95,13 +95,12 @@ def get_DataUsage(files_found, report_folder, seeker, wrap_text, timezone_offset process_split = row[4].split('/') data_list.append((lastconnected,firstused,lastused,row[3],process_split[0],row[5],row[6],row[7])) - data_headers = ((('Last Connect Timestamp','datetime'),('First Usage Timestamp','datetime'),('Last Usage Timestamp','datetime'),'Bundle Name','Process Name','Entry Type','Mobile/WWAN In (Bytes)','Mobile/WWAN Out (Bytes)')) - return data_headers, data_list, file_found + db.close() - db.close() - - else: - continue + data_headers = (('Last Connect Timestamp','datetime'), ('First Usage Timestamp','datetime'), ('Last Usage Timestamp','datetime'), + 'Bundle Name', 'Process Name', 'Entry Type', 'Mobile/WWAN In (Bytes)', 'Mobile/WWAN Out (Bytes)') + return data_headers, data_list, file_found if not data_list: - logfunc('No Network Usage (DataUsage) - App Data available') \ No newline at end of file + logfunc('No Network Usage (DataUsage) - App Data available') + return (), [], '' \ No newline at end of file diff --git a/scripts/artifacts/connectedDevices.py b/scripts/artifacts/connectedDevices.py index e958869b6..2d1b4f1d5 100644 --- a/scripts/artifacts/connectedDevices.py +++ b/scripts/artifacts/connectedDevices.py @@ -3,8 +3,8 @@ "name": "Connected Devices", "description": "Extracts information about connected devices from iTunes preferences", "author": "", - "version": "1.0", - "date": "2024-10-23", + "creation_date": "2024-10-23", + "last_update_date": "2025-11-21", "requirements": "none", "category": "Connected Devices", "notes": "", @@ -13,7 +13,7 @@ } } -from scripts.ilapfuncs import logfunc, artifact_processor +from scripts.ilapfuncs import artifact_processor import os MAGIC_BYTES = b"\x01\x01\x80\x00\x00" @@ -21,24 +21,22 @@ NAME_OFFSET = 157 @artifact_processor -def conDev(files_found, report_folder, seeker, wrap_text, timezone_offset): +def conDev(context): data_list = [] data_headers = ('User Name', 'Computer Name', 'File Offset', 'Source File') - source_path = '' - for file_found in files_found: - source_path = file_found + for file_found in context.get_files_found(): with open(file_found, "rb") as f: data = f.read() - logfunc(f"Data being interpreted for FRPD is of type: {type(data)}") + #logfunc(f"Data being interpreted for FRPD is of type: {type(data)}") magic_index = data.find(MAGIC_BYTES) if magic_index == -1: - logfunc("Magic bytes not found in iTunes Prefs FRPD") + #logfunc("Magic bytes not found in iTunes Prefs FRPD") continue - logfunc("Found magic bytes in iTunes Prefs FRPD... Finding Usernames and Desktop names now") + #logfunc("Found magic bytes in iTunes Prefs FRPD... Finding Usernames and Desktop names now") names = [] current_name = bytearray() @@ -72,4 +70,4 @@ def conDev(files_found, report_folder, seeker, wrap_text, timezone_offset): os.path.basename(file_found) )) - return data_headers, data_list, source_path + return data_headers, data_list, 'see Source File for more info' diff --git a/scripts/artifacts/controlCenter.py b/scripts/artifacts/controlCenter.py index 29a2d4c6a..a5e96ed9b 100644 --- a/scripts/artifacts/controlCenter.py +++ b/scripts/artifacts/controlCenter.py @@ -3,8 +3,8 @@ "name": "Control Center Configuration", "description": "Parses controls/apps added to the Control Center", "author": "@KevinPagano3", - "version": "0.0.2", - "date": "2024-10-18", + "creation_date": "2024-10-18", + "last_update_date": "2025-11-21", "requirements": "none", "category": "Control Center", "notes": "", @@ -13,39 +13,27 @@ } } - -import plistlib - -from packaging import version -from scripts.artifact_report import ArtifactHtmlReport -from scripts.ilapfuncs import logfunc, logdevinfo, tsv, is_platform_windows -from scripts.ilapfuncs import artifact_processor +from scripts.ilapfuncs import artifact_processor, get_plist_file_content @artifact_processor -def controlCenter(files_found, report_folder, seeker, wrap_text, timezone_offset): +def controlCenter(context): data_list = [] - - for file_found in files_found: + for file_found in context.get_files_found(): file_found = str(file_found) - - with open(file_found, 'rb') as f: - pl = plistlib.load(f) + pl = get_plist_file_content(file_found) - for control_type, key, prefix in [ - ('Active', 'module-identifiers', 'A'), - ('User Toggled', 'userenabled-fixed-module-identifiers', 'U'), - ('Disabled', 'disabled-module-identifiers', 'D') - ]: - if key in pl and pl[key]: - for position, module in enumerate(pl[key], 1): - formatted_position = f"{prefix}-{position}" - data_list.append((formatted_position, module, control_type)) - - data_headers = ('Position', 'App Bundle', 'Control Type') - - if not data_list: - logfunc('No Control Center Configuration data available') + for control_type, key, prefix in [ + ('Active', 'module-identifiers', 'A'), + ('User Toggled', 'userenabled-fixed-module-identifiers', 'U'), + ('Disabled', 'disabled-module-identifiers', 'D') + ]: + if key in pl and pl[key]: + for position, module in enumerate(pl[key], 1): + formatted_position = f"{prefix}-{position}" + data_list.append((formatted_position, module, control_type, file_found)) + + data_headers = ('Position', 'App Bundle', 'Control Type', 'Source File') - return data_headers, data_list, file_found + return data_headers, data_list, 'see Source File for more info' diff --git a/scripts/artifacts/coreAccessoriesAcc.py b/scripts/artifacts/coreAccessoriesAcc.py index e0b5e752f..1f2ff0820 100644 --- a/scripts/artifacts/coreAccessoriesAcc.py +++ b/scripts/artifacts/coreAccessoriesAcc.py @@ -6,16 +6,28 @@ # Parses records found in the plists located in the accessoryd database related to accessories that are connected. # -import plistlib +__artifacts_v2__ = { + "get_coreAccessories": { + "name": "Core Accessories - AccessoryD", + "description": "Parses records found in the plists located in the accessoryd database related \ + to accessories that are connected.", + "author": "John Hyla", + "creation_date": "2023-08-01", + "last_update_date": "2025-11-21", + "requirements": "none", + "category": "Core Accessories", + "notes": "", + "paths": ('*/mobile/Library/CoreAccessories/Analytics/acc_analytics_accessoryd_v3.db*',), + "output_types": "standard", + } +} -from scripts.artifact_report import ArtifactHtmlReport -from scripts.ilapfuncs import logfunc, logdevinfo, tsv, is_platform_windows, open_sqlite_db_readonly -import datetime +from scripts.ilapfuncs import open_sqlite_db_readonly, artifact_processor, get_plist_content, convert_unix_ts_to_utc +@artifact_processor +def get_coreAccessories(context): -def get_coreAccessories(files_found, report_folder, seeker, wrap_text, timezone_offset): - - for file_found in files_found: + for file_found in context.get_files_found(): file_name = str(file_found) if file_name.endswith('acc_analytics_accessoryd_v3.db'): db_file = str(file_found) @@ -31,7 +43,6 @@ def get_coreAccessories(files_found, report_folder, seeker, wrap_text, timezone_ ''') all_rows = cursor.fetchall() - usageentries = len(all_rows) # Initialize the list to store dictionaries from each iteration temp_data = [] @@ -39,11 +50,10 @@ def get_coreAccessories(files_found, report_folder, seeker, wrap_text, timezone_ # Set to store all possible keys found during iterations all_keys = set() event_time_key = 'eventTime' - if usageentries > 0: - for row in all_rows: - pl = plistlib.loads(row[0]) - temp_data.append(pl) - all_keys.update(pl.keys()) + for row in all_rows: + pl = get_plist_content(row[0]) + temp_data.append(pl) + all_keys.update(pl.keys()) all_keys.remove(event_time_key) all_keys_list = [event_time_key] + list(all_keys) @@ -53,24 +63,12 @@ def get_coreAccessories(files_found, report_folder, seeker, wrap_text, timezone_ for key in all_keys_list: if key == event_time_key: event_time_value = row.get(event_time_key, None) - event_time_value = datetime.datetime.utcfromtimestamp(event_time_value / 1000.0).strftime( - '%Y-%m-%d %H:%M:%S') + event_time_value = convert_unix_ts_to_utc(event_time_value) row_values.append(event_time_value) else: row_values.append(row.get(key, None)) data_list.append(row_values) + all_keys_list[0] = (all_keys_list[0], 'datetime') - report = ArtifactHtmlReport('Core Accessories - AccessoryD') - report.start_artifact_report(report_folder, 'AccessoryD') - report.add_script() - report.write_artifact_data_table(all_keys_list, data_list, file_found) - report.end_artifact_report() - - -__artifacts__ = { - "coreAccessories": ( - "Core Accessories", - ('*/mobile/Library/CoreAccessories/Analytics/acc_analytics_accessoryd_v3.db*'), - get_coreAccessories) -} \ No newline at end of file + return all_keys_list, data_list, db_file diff --git a/scripts/artifacts/coreAccessoriesUserEvent.py b/scripts/artifacts/coreAccessoriesUserEvent.py index e253be87c..1c53d4d37 100644 --- a/scripts/artifacts/coreAccessoriesUserEvent.py +++ b/scripts/artifacts/coreAccessoriesUserEvent.py @@ -6,16 +6,28 @@ # Parses records found in the plists located in the UserEventAgent database found in CoreAccessories # -import plistlib +__artifacts_v2__ = { + "get_coreAccessoriesUserEvent": { + "name": "Core Accessories - UserEventAgent", + "description": "Parses records found in the plists located in the UserEventAgent \ + database found in CoreAccessories", + "author": "John Hyla", + "creation_date": "2023-08-01", + "last_update_date": "2025-10-01", + "requirements": "none", + "category": "Core Accessories", + "notes": "", + "paths": ('*/mobile/Library/CoreAccessories/Analytics/acc_analytics_UserEventAgent_v3.db*',), + "output_types": "standard", + } +} -from scripts.artifact_report import ArtifactHtmlReport -from scripts.ilapfuncs import logfunc, logdevinfo, tsv, is_platform_windows, open_sqlite_db_readonly -import datetime +from scripts.ilapfuncs import open_sqlite_db_readonly, artifact_processor, get_plist_content, convert_unix_ts_to_utc +@artifact_processor +def get_coreAccessoriesUserEvent(context): -def get_coreAccessoriesUserEvent(files_found, report_folder, seeker, wrap_text, timezone_offset): - - for file_found in files_found: + for file_found in context.get_files_found(): file_name = str(file_found) if file_name.endswith('acc_analytics_UserEventAgent_v3.db'): db_file = str(file_found) @@ -31,7 +43,6 @@ def get_coreAccessoriesUserEvent(files_found, report_folder, seeker, wrap_text, ''') all_rows = cursor.fetchall() - usageentries = len(all_rows) # Initialize the list to store dictionaries from each iteration temp_data = [] @@ -39,11 +50,10 @@ def get_coreAccessoriesUserEvent(files_found, report_folder, seeker, wrap_text, # Set to store all possible keys found during iterations all_keys = set() event_time_key = 'eventTime' - if usageentries > 0: - for row in all_rows: - pl = plistlib.loads(row[0]) - temp_data.append(pl) - all_keys.update(pl.keys()) + for row in all_rows: + pl = get_plist_content(row[0]) + temp_data.append(pl) + all_keys.update(pl.keys()) all_keys.remove(event_time_key) all_keys_list = [event_time_key] + list(all_keys) @@ -53,8 +63,7 @@ def get_coreAccessoriesUserEvent(files_found, report_folder, seeker, wrap_text, for key in all_keys_list: if key == event_time_key: event_time_value = row.get(event_time_key, None) - event_time_value = datetime.datetime.utcfromtimestamp(event_time_value / 1000.0).strftime( - '%Y-%m-%d %H:%M:%S') + event_time_value = convert_unix_ts_to_utc(event_time_value) row_values.append(event_time_value) elif key == "lightningDigitalID": value = row.get(key, None) @@ -76,18 +85,8 @@ def get_coreAccessoriesUserEvent(files_found, report_folder, seeker, wrap_text, else: row_values.append(row.get(key, None)) data_list.append(row_values) + + all_keys_list[0] = (all_keys_list[0], 'datetime') - report = ArtifactHtmlReport('Core Accessories - User Event Agent') - report.start_artifact_report(report_folder, 'User Event Agent') - report.add_script() - report.write_artifact_data_table(all_keys_list, data_list, file_found) - report.end_artifact_report() - - -__artifacts__ = { - "coreAccessoriesUserEvent": ( - "Core Accessories", - ('*/mobile/Library/CoreAccessories/Analytics/acc_analytics_UserEventAgent_v3.db*'), - get_coreAccessoriesUserEvent) -} \ No newline at end of file + return all_keys_list, data_list, db_file diff --git a/scripts/artifacts/deviceActivator.py b/scripts/artifacts/deviceActivator.py index 45fb78b10..96c5267a7 100644 --- a/scripts/artifacts/deviceActivator.py +++ b/scripts/artifacts/deviceActivator.py @@ -3,8 +3,8 @@ "name": "iOS Device Activator Data", "description": "Extracts device information from activation data", "author": "", - "version": "1.0", - "date": "2024-10-29", + "creation_date": "2024-10-29", + "last_update_date": "2025-11-21", "requirements": "none", "category": "Device Information", "paths": ('*/mobile/Library/Logs/mobileactivationd/ucrt_oob_request.txt',), @@ -15,16 +15,17 @@ import re import base64 import os -from itertools import compress import xml.etree.ElementTree as ET -from scripts.ilapfuncs import logfunc, device_info, artifact_processor +from scripts.ilapfuncs import device_info, artifact_processor @artifact_processor -def deviceActivator(files_found, report_folder, seeker, wrap_text, timezone_offset): +def deviceActivator(context): data_list = [] + files_found = context.get_files_found() file_found = str(files_found[0]) + report_folder = context.get_report_folder() - with open(file_found, 'r') as f_in: + with open(file_found, 'r', encoding='utf-8') as f_in: for line in f_in: line = line.strip() alllines = alllines + line @@ -60,9 +61,5 @@ def deviceActivator(files_found, report_folder, seeker, wrap_text, timezone_offs if x[0] == 'ModelNumber': device_info("Device Information", "Model Number", x[1], file_found) - if len(results) > 0: - data_headers = ('Property', 'Property Value') - return data_headers, results, file_found - else: - logfunc('No iOS Device Activator Data') - return None \ No newline at end of file + data_headers = ('Property', 'Property Value') + return data_headers, results, file_found \ No newline at end of file