diff --git a/X. NU/custom/drivers/iokit_dump.py b/X. NU/custom/drivers/iokit_dump.py new file mode 100644 index 0000000..36d74bd --- /dev/null +++ b/X. NU/custom/drivers/iokit_dump.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +import lldb +import shlex + +def hexdump(process, address, count): + """ + Generates a formatted hexdump of a memory region. + """ + err = lldb.SBError() + data = process.ReadMemory(address, count, err) + if not err.Success(): + return "error reading memory" + + lines = [] + for i in range(0, len(data), 16): + chunk = data[i:i+16] + left = " ".join(f"{b:02x}" for b in chunk[0:8]) + right = " ".join(f"{b:02x}" for b in chunk[8:]) if len(chunk) > 8 else "" + hex_str = left + (" " + right if right else "") + ascii_str = "".join(chr(b) if 32 <= b < 127 else "." for b in chunk) + lines.append(f"{address + i:08x} {hex_str:<48s} |{ascii_str:<16s}|") + return "\n".join(lines) + +def format_row(typ, name, value): + """ + Formats a single row for the argument summary table. + """ + return f"{typ:<26}{name:<40}{value:>20}" + +def iokit_dump(debugger, command, result, internal_dict): + """ + Main function for the 'iokit_dump' LLDB command. + """ + # --- Argument Parsing --- + try: + args = shlex.split(command) + dump_filename = args[0] if args else None + except Exception as e: + result.PutCString(f"Error parsing arguments: {e}") + result.SetStatus(1) # Use 1 for lldb.eReturnStatusFailed + return + + # --- LLDB Object Setup with validation --- + target = debugger.GetSelectedTarget() + if not target or not target.IsValid(): + result.PutCString("Error: No valid target selected.") + result.SetStatus(1) # Use 1 for lldb.eReturnStatusFailed + return + + process = target.GetProcess() + if not process or not process.IsValid(): + result.PutCString("Error: No valid process running.") + result.SetStatus(1) # Use 1 for lldb.eReturnStatusFailed + return + + thread = process.GetSelectedThread() + if not thread or not thread.IsValid(): + result.PutCString("Error: No valid thread selected.") + result.SetStatus(1) # Use 1 for lldb.eReturnStatusFailed + return + + frame = thread.GetFrameAtIndex(0) + if not frame or not frame.IsValid(): + result.PutCString("Error: Could not get the current stack frame.") + result.SetStatus(1) # Use 1 for lldb.eReturnStatusFailed + return + + # --- Read Registers for inputStruct --- + inputStruct_ptr = frame.FindRegister("x4").GetValueAsUnsigned() + inputStructCnt = frame.FindRegister("x5").GetValueAsUnsigned() + + # --- New: Dump inputStruct to a file --- + if dump_filename: + if not inputStruct_ptr or inputStructCnt == 0: + result.PutCString("No inputStruct data to dump (pointer is null or size is zero).") + result.SetStatus(0) # Use 0 for lldb.eReturnStatusSuccess + return + + err = lldb.SBError() + data = process.ReadMemory(inputStruct_ptr, inputStructCnt, err) + + if not err.Success(): + result.PutCString(f"Error reading memory for inputStruct at {hex(inputStruct_ptr)}: {err}") + result.SetStatus(1) # Use 1 for lldb.eReturnStatusFailed + return + + try: + with open(dump_filename, 'wb') as f: + f.write(data) + result.PutCString(f"Successfully dumped {inputStructCnt} bytes of inputStruct to '{dump_filename}'") + result.SetStatus(0) # Use 0 for lldb.eReturnStatusSuccess + except IOError as e: + result.PutCString(f"Error writing to file '{dump_filename}': {e}") + result.SetStatus(1) # Use 1 for lldb.eReturnStatusFailed + return + + # --- Original: Print formatted argument summary --- + # Read remaining registers + connection = frame.FindRegister("x0").GetValueAsUnsigned() + selector = frame.FindRegister("x1").GetValueAsUnsigned() + input_ptr = frame.FindRegister("x2").GetValueAsUnsigned() + inputCnt = frame.FindRegister("x3").GetValueAsUnsigned() + output_ptr = frame.FindRegister("x6").GetValueAsUnsigned() + outputCnt_ptr = frame.FindRegister("x7").GetValueAsUnsigned() + outputStruct_ptr = frame.FindRegister("x8").GetValueAsUnsigned() + outputStructCnt_ptr = frame.FindRegister("x9").GetValueAsUnsigned() + + lines = ["kern_return_t IOConnectCallMethod", "-------------------------------------"] + rows = [ + format_row("mach_port_t", "connection:", f"{hex(connection)}"), + format_row("uint32_t", "selector:", f"{hex(selector)}"), + format_row("const uint64_t *", "input:", f"{hex(input_ptr)}"), + format_row("uint32_t", "inputCnt:", f"{hex(inputCnt)}"), + format_row("const void *", "inputStruct:", f"{hex(inputStruct_ptr)}"), + format_row("size_t", "inputStructCnt:", f"{hex(inputStructCnt)}"), + format_row("uint64_t *", "output:", f"{hex(output_ptr)}"), + format_row("uint32_t *", "outputCnt:", f"{hex(outputCnt_ptr)}"), + format_row("void *", "outputStruct:", f"{hex(outputStruct_ptr)}"), + format_row("size_t *", "outputStructCnt:", f"{hex(outputStructCnt_ptr)}"), + ] + lines.extend(rows) + + # Input/Output scalars and struct hexdumps... + if inputStruct_ptr and inputStructCnt > 0: + lines.append("\nInput Struct Hexdump (first 32 bytes):") + dump = hexdump(process, inputStruct_ptr, min(inputStructCnt, 32)) + lines.append(dump) + + # (Additional logic for other pointers as in previous script) + + result.PutCString("\n".join(lines)) + result.SetStatus(0) # Use 0 for lldb.eReturnStatusSuccess + +def __lldb_init_module(debugger, internal_dict): + """ + Registers the 'iokit_dump' command when the script is loaded in LLDB. + """ + debugger.HandleCommand('command script add -f iokitargs.iokit_dump iokit_dump') + print("Loaded 'iokit_dump' command.") + print("Usage: iokit_dump [FILENAME]")