mirror of
https://github.com/Karmaz95/Snake_Apple.git
synced 2026-03-30 14:00:16 +02:00
Add iokit_dump.py script for dumping IOKit IOConnectCallMethod data in LLDB
This commit is contained in:
140
X. NU/custom/drivers/iokit_dump.py
Normal file
140
X. NU/custom/drivers/iokit_dump.py
Normal file
@@ -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]")
|
||||
Reference in New Issue
Block a user