From 196ed7759c09944ec6b01eb2a11e63cf1439c458 Mon Sep 17 00:00:00 2001 From: Roussille Benoit Date: Sun, 14 Jan 2024 18:49:30 +0100 Subject: [PATCH 1/2] adding parsers for shutdown logs --- parsers/sysdiagnose-shutdownlogs.py | 110 ++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 parsers/sysdiagnose-shutdownlogs.py diff --git a/parsers/sysdiagnose-shutdownlogs.py b/parsers/sysdiagnose-shutdownlogs.py new file mode 100644 index 0000000..3e5bb76 --- /dev/null +++ b/parsers/sysdiagnose-shutdownlogs.py @@ -0,0 +1,110 @@ +#! /usr/bin/env python3 + +# For Python3 +# Demo blank parsers +# Author: david@autopsit.org + +import os +import sys +import json +from optparse import OptionParser +import time +import struct +import datetime +import re + +version_string = "sysdiagnose-shutdownlog.py v2024-01-11 Version 1.0" + +# ----- definition for parsing.py script -----# + +parser_description = "Parsing shutdown.log file" +parser_input = "shutdownlog" +parser_call = "parse_shutdownlog" + +# --------------------------------------------# + +CLIENTS_ARE_STILL_HERE_LINE = "these clients are still here" +REMAINING_CLIENT_PID_LINE = "remaining client pid" +SIGTERM_LINE = "SIGTERM" + +# --------------------------------------------------------------------------- # + + +def parse_shutdownlog(filepath, ios_version=16): + """ + This is the function that will be called + """ + # read log file content + log_lines = "" + with open(filepath, "r") as f: + log_lines = f.readlines() + + json_object = {} + parsed_data = {} + index = 0 + # go through log file + while index < len(log_lines): + # look for begining of shutdown sequence + if CLIENTS_ARE_STILL_HERE_LINE in log_lines[index]: + running_processes = [] + while not(SIGTERM_LINE in log_lines[index]): + if (REMAINING_CLIENT_PID_LINE in log_lines[index]): + result = re.search(r".*: (\b\d+) \((.*)\).*", log_lines[index]) + pid = result.groups()[0] + binary_path = result.groups()[1] + process = pid + ":" + binary_path + if not(process in running_processes): + running_processes.append(process) + index += 1 + # compute timestamp from SIGTERM line + result = re.search(r".*\[(\d+)\].*", log_lines[index]) + timestamp = result.groups()[0] + time = str(datetime.datetime.fromtimestamp(int(timestamp), datetime.UTC)) + # add entries + parsed_data[time] = [] + for p in running_processes: + parsed_data[time].append({"pid": p.split(":")[0], "path": p.split(":")[1]}) + index += 1 + + json_object["data"] = parsed_data + + return json_object + + +# --------------------------------------------------------------------------- # + +def main(): + """ + Main function, to be called when used as CLI tool + """ + + print(f"Running {version_string}\n") + + usage = "\n%prog -i inputfile\n" + + parser = OptionParser(usage=usage) + parser.add_option("-i", dest="inputfile", + action="store", type="string", + help="path to the shutdown.log file") + (options, args) = parser.parse_args() + + # no arguments given by user, print help and exit + if len(sys.argv) == 1: + parser.print_help() + sys.exit(-1) + + # Call the demo function when called directly from CLI + print(parse_shutdownlog(options.inputfile)) + +# --------------------------------------------------------------------------- # + + +""" + Call main function +""" +if __name__ == "__main__": + + # Create an instance of the Analysis class (called "base") and run main + main() + +# That's all folk ;) From 76b58bb57d66d757b0b076d220b0f18a336edee9 Mon Sep 17 00:00:00 2001 From: Roussille Benoit Date: Sun, 14 Jan 2024 18:57:17 +0100 Subject: [PATCH 2/2] adding file generated by initialize to gitignore --- .gitignore | 1 + analyzers/sysdiagnose-timeliner.py | 27 +++++++++++++++++++++++++++ initialyze.py | 5 +++++ 3 files changed, 33 insertions(+) diff --git a/.gitignore b/.gitignore index 43d7d76..df22e57 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ data/* cases.json parsed_data/* *.gpx +db.json # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/analyzers/sysdiagnose-timeliner.py b/analyzers/sysdiagnose-timeliner.py index bdcd3bf..8e569a3 100644 --- a/analyzers/sysdiagnose-timeliner.py +++ b/analyzers/sysdiagnose-timeliner.py @@ -29,6 +29,7 @@ "sysdiagnose-mobileactivation.json": "__extract_ts_mobileactivation", "sysdiagnose-powerlogs.json": "__extract_ts_powerlogs", "sysdiagnose-swcutil.json": "__extract_ts_swcutil", + "sysdiagnose-shutdownlogs.json": "__extract_ts_shutdownlogs", "sysdiagnose-logarchive.json": "__extract_ts_logarchive", "sysdiagnose-wifisecurity.json": "__extract_ts_wifisecurity", "sysdiagnose_wifi_known_networks.json": "__extract_ts_wifi_known_networks", @@ -200,6 +201,32 @@ def __extract_ts_accessibility_tcc(filename): return False return False +def __extract_ts_shutdownlogs(filename): + try: + with open(filename, 'r') as fd: + data = json.load(fd) + for ts in data["data"].keys(): + try: + # create timeline entries + timestamp = datetime.strptime(ts, "%Y-%m-%d %H:%M:%S+00:00") + processes = data["data"][ts] + for p in processes: + ts_event = { + "message": p["path"], + "timestamp": int(timestamp.timestamp() * 1000000), + "datetime": timestamp.strftime("%Y-%m-%dT%H:%M:%S+00:00"), + "timestamp_desc": "Entry in shutdown.log", + "extra_field_1": "pid: %s" % p["pid"] + } + timeline.append(ts_event) + except Exception as e: + print(f"WARNING: entry not parsed: {ts}") + return True + except Exception as e: + print(f"ERROR while extracting timestamp from {filename}. Reason: {str(e)}") + return False + return False + def __extract_ts_logarchive(filename): r""" diff --git a/initialyze.py b/initialyze.py index 3deb36b..269aeec 100644 --- a/initialyze.py +++ b/initialyze.py @@ -160,6 +160,11 @@ def init(sysdiagnose_file, force=False): except: # noqa: E722 pass + try: + new_case_json["shutdownlog"] = new_folder +glob.glob('./*/system_logs.logarchive/Extra/shutdown.log')[0][1:] + except: # noqa: E722 + pass + try: new_case_json["taskinfo"] = new_folder +glob.glob('./*/taskinfo.txt')[0][1:] except: # noqa: E722