Skip to content
Open
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
16 changes: 5 additions & 11 deletions scripts/artifacts/FacebookMessenger.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,7 @@ def get_FacebookMessenger(files_found, report_folder, seeker, wrap_text):
when 0 then ""
when 1 then "Yes"
end as "Messenger User",
case friendship_status
when 0 then "N/A (Self)"
when 1 then "Friends"
when 2 then "Friend Request Received"
when 3 then "Friend Request Sent"
when 4 then "Not Friends"
end as "Friendship Status",
'' as "Friendship Status",
substr(datetime(birthday_timestamp,'unixepoch'),6,5) as "Birthdate (MM-DD)"
from contacts
''')
Expand Down Expand Up @@ -224,7 +218,7 @@ def get_FacebookMessenger(files_found, report_folder, seeker, wrap_text):
(select json_extract (messages.shares, '$[0].description')) as ShareDesc,
(select json_extract (messages.shares, '$[0].href')) as ShareLink,
message_reactions.reaction as "Message Reaction",
datetime(message_reactions.reaction_timestamp/1000,'unixepoch') as "Message Reaction Timestamp",
'' as "Message Reaction Timestamp",
messages.msg_id
from messages, threads
left join message_reactions on message_reactions.msg_id = messages.msg_id
Expand All @@ -248,7 +242,7 @@ def get_FacebookMessenger(files_found, report_folder, seeker, wrap_text):
(select json_extract (messages.shares, '$[0].description')) as ShareDesc,
(select json_extract (messages.shares, '$[0].href')) as ShareLink,
message_reactions.reaction as "Message Reaction",
datetime(message_reactions.reaction_timestamp/1000,'unixepoch') as "Message Reaction Timestamp",
'' as "Message Reaction Timestamp",
messages.msg_id
from messages, threads
left join message_reactions on message_reactions.msg_id = messages.msg_id
Expand Down Expand Up @@ -338,8 +332,8 @@ def get_FacebookMessenger(files_found, report_folder, seeker, wrap_text):
when 0 then 'No'
when 1 then 'Yes'
end is_friend,
friendship_status,
contact_relationship_status
'' as friendship_status,
'' contact_relationship_status
from thread_users
''')

Expand Down
19 changes: 13 additions & 6 deletions scripts/artifacts/appops.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,19 @@ def get_appops(files_found, report_folder, seeker, wrap_text):

data_list = []
#check if file is abx
if (checkabx(file_found)):
multi_root = False
tree = abxread(file_found, multi_root)
else:
tree = ET.parse(file_found)
root = tree.getroot()
try:
if (checkabx(file_found)):
multi_root = False
tree = abxread(file_found, multi_root)
else:
tree = ET.parse(file_found)
root = tree.getroot()
except ET.ParseError:
logfunc(f"Skipping invalid XML/AppOps file: {file_found}")
continue
except Exception as e:
logfunc(f"Error parsing AppOps file {file_found}: {str(e)}")
continue

for elem in root.iter('pkg'):
pkg = elem.attrib['n']
Expand Down
36 changes: 30 additions & 6 deletions scripts/artifacts/googleMessages.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,51 @@
from scripts.artifact_report import ArtifactHtmlReport
from scripts.ilapfuncs import logfunc, tsv, timeline, is_platform_windows, open_sqlite_db_readonly


def get_googleMessages(files_found, report_folder, seeker, wrap_text):

for file_found in files_found:
file_found = str(file_found)
if not file_found.endswith('bugle_db'):
continue # Skip all other files

# Helper function
def table_col_info(cursor, table):
cursor.execute(f"PRAGMA table_info({table});")
return {row[1] for row in cursor.fetchall()}

db = open_sqlite_db_readonly(file_found)
cursor = db.cursor()
cursor.execute('''
cols = table_col_info(cursor, "parts")

if "file_size_bytes" in cols:
size_expr = """
CASE
WHEN parts.file_size_bytes = -1 THEN 'N/A'
ELSE parts.file_size_bytes
END
"""
elif "size" in cols:
size_expr = "parts.size"
else:
size_expr = "''"

if "local_cache_path" in cols:
location_expr = "parts.local_cache_path"
elif "content_uri" in cols:
location_expr = "parts.content_uri"
else:
location_expr = "''"

cursor.execute(f'''
SELECT
datetime(parts.timestamp/1000,'unixepoch') AS "Timestamp (UTC)",
parts.content_type AS "Message Type",
conversations.name AS "Other Participant/Conversation Name",
participants.display_destination AS "Message Sender",
parts.text AS "Message",
CASE
WHEN parts.file_size_bytes=-1 THEN "N/A"
ELSE parts.file_size_bytes
END AS "Attachment Byte Size",
parts.local_cache_path AS "Attachment Location"
{size_expr} AS "Attachment Byte Size",
{location_expr} AS "Attachment Location"
FROM
parts
JOIN messages ON messages._id=parts.message_id
Expand Down
95 changes: 58 additions & 37 deletions scripts/artifacts/siminfo.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,49 @@ def process_siminfo(folder, uid, report_folder):

#Query to create report
try:
cursor.execute('''
SELECT
number,
imsi,
display_name,
carrier_name,
iso_country_code,
carrier_id,
icc_id
FROM
siminfo
''')
# Find columns that available
columns_info = cursor.fetchall()
available_columns = [col[1] for col in columns_info]
except:
cursor.execute('''
# If siminfo table don't exist
logfunc(f'Error getting table schema for SIM_info_{uid}')
db.close()
return

#Helper function
def get_col(col_name):
return col_name if col_name in available_columns else "''"

id_col = "''"
if 'imsi' in available_columns: id_col = 'imsi'
elif 'card_id' in available_columns: id_col = 'card_id'
elif 'sim_id' in available_columns: id_col = 'sim_id'

iso_col = "''"
if 'iso_country_code' in available_columns: iso_column = 'iso_country_code'
elif 'country_iso' in available_columns: iso_column = 'country_iso'

icc_col = get_col('icc_id')

query = f'''
SELECT
number,
card_id,
display_name,
carrier_name,
carrier_name,
carrier_name,
icc_id
FROM
siminfo
''')

all_rows = cursor.fetchall()
usageentries = len(all_rows)
{get_col('number')},
{id_col} as sim_identifier,
{get_col('display_name')},
{get_col('carrier_name')},
{iso_col} as country_iso,
{get_col('carrier_id')},
{icc_col}
FROM siminfo
'''

try:
cursor.execute(query)
all_rows = cursor.fetchall()
usageentries = len(all_rows)
except Exception as e:
logfunc(f'Error executing query for SIM_info_{uid}: {str(e)}')
usageentries = 0
if usageentries > 0:
report = ArtifactHtmlReport('Device Info')
report.start_artifact_report(report_folder, f'SIM_info_{uid}')
Expand All @@ -68,17 +83,21 @@ def process_siminfo(folder, uid, report_folder):

data_list = []
for row in all_rows:
if row[3] == row[4]:
row1 = ''
row4 = ''
row5 = ''
else:
row1 = row[1]
row4 = row[4]
row5 = row[5]
data_list.append((row[0], row1, row[2], row[3], row4, row5, row[6]))
logdevinfo(f"<b>SIM Number & IMSI: </b>{row[0]} - {row1}")
logdevinfo(f"<b>SIM Display Name: </b>{row[2]}")
# Collect data directly
number = str(row[0]) if row[0] is not None else ''
identifier = str(row[1]) if row[1] is not None else ''
display_name = str(row[2]) if row[2] is not None else ''
carrier = str(row[3]) if row[3] is not None else ''
iso = str(row[4]) if row[4] is not None else ''
carrier_id = str(row[5]) if row[5] is not None else ''
icc_id = str(row[6]) if row[6] is not None else ''

data_list.append((number, identifier, display_name, carrier, iso, carrier_id, icc_id))

logdevinfo(f"<b>SIM Number: </b>{number}")
logdevinfo(f"<b>SIM ID (IMSI/CardID): </b>{identifier}")
logdevinfo(f"<b>SIM Carrier: </b>{carrier}")

report.write_artifact_data_table(data_headers, data_list, folder)
report.end_artifact_report()

Expand All @@ -87,6 +106,8 @@ def process_siminfo(folder, uid, report_folder):
else:
logfunc(f'No SIM_Info{uid} data available')
db.close()



__artifacts__ = {
"siminfo": (
Expand Down