Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 15 additions & 16 deletions scripts/artifacts/DataUsage.py
Original file line number Diff line number Diff line change
Expand Up @@ -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": "",
Expand All @@ -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'):
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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')
logfunc('No Network Usage (DataUsage) - App Data available')
return (), [], ''
20 changes: 9 additions & 11 deletions scripts/artifacts/connectedDevices.py
Original file line number Diff line number Diff line change
Expand Up @@ -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": "",
Expand All @@ -13,32 +13,30 @@
}
}

from scripts.ilapfuncs import logfunc, artifact_processor
from scripts.ilapfuncs import artifact_processor
import os

MAGIC_BYTES = b"\x01\x01\x80\x00\x00"
MAGIC_OFFSET = 92
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()
Expand Down Expand Up @@ -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'
48 changes: 18 additions & 30 deletions scripts/artifacts/controlCenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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": "",
Expand All @@ -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'


54 changes: 26 additions & 28 deletions scripts/artifacts/coreAccessoriesAcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -31,19 +43,17 @@ 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 = []

# 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)
Expand All @@ -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)
}
return all_keys_list, data_list, db_file
55 changes: 27 additions & 28 deletions scripts/artifacts/coreAccessoriesUserEvent.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -31,19 +43,17 @@ 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 = []

# 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)
Expand All @@ -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)
Expand All @@ -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)
}
return all_keys_list, data_list, db_file
Loading