IOS: add Starlet LLE milestone through HBC
Boot original Wii firmware through boot0, boot1, boot2 and IOS on an emulated ARM Starlet. Model the required IPC, memory, SD, USB and Bluetooth hardware behavior, including IOS reload into IOS58, and add focused tests, launch utilities and architecture documentation.
This commit is contained in:
1 parent
38e70fda65
commit
a77c156bc8
46 files changed
+10556
-158
No files matched your search
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import ctypes
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
|
||||
REPOSITORY_ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(REPOSITORY_ROOT / "capstone_local"))
|
||||
|
||||
from capstone import CS_ARCH_ARM, CS_ARCH_PPC, CS_MODE_32, CS_MODE_ARM, CS_MODE_BIG_ENDIAN, Cs
|
||||
|
||||
|
||||
PROCESS_VM_READ = 0x0010
|
||||
PROCESS_QUERY_INFORMATION = 0x0400
|
||||
|
||||
|
||||
def read_process_memory(process_id: int, address: int, length: int) -> bytes:
|
||||
kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
|
||||
kernel32.OpenProcess.argtypes = [ctypes.c_uint32, ctypes.c_bool, ctypes.c_uint32]
|
||||
kernel32.OpenProcess.restype = ctypes.c_void_p
|
||||
kernel32.ReadProcessMemory.argtypes = [
|
||||
ctypes.c_void_p,
|
||||
ctypes.c_void_p,
|
||||
ctypes.c_void_p,
|
||||
ctypes.c_size_t,
|
||||
ctypes.POINTER(ctypes.c_size_t),
|
||||
]
|
||||
kernel32.ReadProcessMemory.restype = ctypes.c_bool
|
||||
kernel32.CloseHandle.argtypes = [ctypes.c_void_p]
|
||||
kernel32.CloseHandle.restype = ctypes.c_bool
|
||||
|
||||
process = kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, False, process_id)
|
||||
if not process:
|
||||
raise ctypes.WinError(ctypes.get_last_error())
|
||||
|
||||
try:
|
||||
buffer = ctypes.create_string_buffer(length)
|
||||
bytes_read = ctypes.c_size_t()
|
||||
if not kernel32.ReadProcessMemory(
|
||||
process, ctypes.c_void_p(address), buffer, length, ctypes.byref(bytes_read)
|
||||
):
|
||||
raise ctypes.WinError(ctypes.get_last_error())
|
||||
if bytes_read.value != length:
|
||||
raise RuntimeError(f"short read: requested {length} bytes, got {bytes_read.value}")
|
||||
return buffer.raw
|
||||
finally:
|
||||
kernel32.CloseHandle(process)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Disassemble big-endian 32-bit PowerPC code from a live Windows process."
|
||||
)
|
||||
parser.add_argument("process_id", type=int)
|
||||
parser.add_argument("host_address", type=lambda value: int(value, 0))
|
||||
parser.add_argument("guest_address", type=lambda value: int(value, 0))
|
||||
parser.add_argument("length", type=lambda value: int(value, 0))
|
||||
parser.add_argument("--arch", choices=("ppc", "arm"), default="ppc")
|
||||
args = parser.parse_args()
|
||||
|
||||
code = read_process_memory(args.process_id, args.host_address, args.length)
|
||||
if args.arch == "arm":
|
||||
disassembler = Cs(CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_BIG_ENDIAN)
|
||||
else:
|
||||
disassembler = Cs(CS_ARCH_PPC, CS_MODE_32 | CS_MODE_BIG_ENDIAN)
|
||||
for instruction in disassembler.disasm(code, args.guest_address):
|
||||
operands = f" {instruction.op_str}" if instruction.op_str else ""
|
||||
print(f"{instruction.address:08x}: {instruction.bytes.hex(' '):11} "
|
||||
f"{instruction.mnemonic}{operands}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user