From e3c8436760ccf6d56c0bd0fcdd380555c768112d Mon Sep 17 00:00:00 2001 From: kat Date: Wed, 10 Jan 2024 17:27:46 -0500 Subject: [PATCH] Add rebase opcode parsing and some quickstart fixes --- docs/source/quickstart.rst | 6 +++--- src/ktool/loader.py | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index fb0fa03..773ad2d 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -9,17 +9,17 @@ Basic Concepts to understand: * There are a lot of subfiles and a few modules, but :python:`import ktool` will import all of the stuff you most likely need. * My struct system emulates C's. Or if you don't know C, it's like someone smashed together python structs and namedtuples. -On the github, :sh:`src/ktool/ktool_script.py` is a fairly standard client for this library, and you can reference it to +On the github, `src/ktool/ktool_script.py` is a fairly standard client for this library, and you can reference it to figure out how to do a lot of the basic stuff this library is capable of. Install The Library ======================= -:sh:`python3 -m pip install k2l` +`python3 -m pip install k2l` To install new updates: -:sh:`python3 -m pip install --upgrade k2l` +`python3 -m pip install --upgrade k2l` Code Examples diff --git a/src/ktool/loader.py b/src/ktool/loader.py index d457019..d75b65d 100644 --- a/src/ktool/loader.py +++ b/src/ktool/loader.py @@ -373,6 +373,7 @@ class ChainedFixups(Constructable): def from_image(cls, image: Image, chained_fixup_cmd: linkedit_data_command): syms = [] + rebases = {} fixup_header = image.read_struct(chained_fixup_cmd.dataoff, dyld_chained_fixups_header) log.debug_tm(f'{fixup_header.render_indented()}') @@ -421,6 +422,7 @@ def from_image(cls, image: Image, chained_fixup_cmd: linkedit_data_command): stride_size: int = 0 ptr_format: ChainedFixupPointerGeneric = ChainedFixupPointerGeneric.Error + log.debug_tm(f"Pointer Format: {ptr_format.name}") if starts.pointer_format in [dyld_chained_ptr_format.DYLD_CHAINED_PTR_ARM64E.value, dyld_chained_ptr_format.DYLD_CHAINED_PTR_ARM64E_USERLAND.value, dyld_chained_ptr_format.DYLD_CHAINED_PTR_ARM64E_USERLAND24.value]: @@ -449,6 +451,7 @@ def from_image(cls, image: Image, chained_fixup_cmd: linkedit_data_command): log.error(f'{hex(fixup_header.off)} @ {fixup_header.render_indented()}') log.error(f"{starts.render_indented()}") return cls([]) + log.debug_tm(f"Stride Size: {stride_size}") page_start_offsets: List[List[int]] = [] for i in range(0, starts.page_count): @@ -537,6 +540,33 @@ def from_image(cls, image: Image, chained_fixup_cmd: linkedit_data_command): sym = Symbol.from_values(entry.name, target_addr, external=True, ordinal=entry.ord) syms.append(sym) + else: #rebase + entry_offset = 0 + if starts.pointer_format in [dyld_chained_ptr_format.DYLD_CHAINED_PTR_ARM64E, + dyld_chained_ptr_format.DYLD_CHAINED_PTR_ARM64E_KERNEL, + dyld_chained_ptr_format.DYLD_CHAINED_PTR_ARM64E_USERLAND, + dyld_chained_ptr_format.DYLD_CHAINED_PTR_ARM64E_USERLAND24]: + if pointer64.generic64.ChainedPointerArm64E.dyld_chained_ptr_arm64e_auth_rebase.auth == 1: + entry_offset = pointer64.generic64.ChainedPointerArm64E.dyld_chained_ptr_arm64e_auth_rebase.target + else: + entry_offset = pointer64.generic64.ChainedPointerArm64E.dyld_chained_ptr_arm64e_rebase.target + + if starts.pointer_format != dyld_chained_ptr_format.DYLD_CHAINED_PTR_ARM64E or pointer64.generic64.ChainedPointerArm64E.dyld_chained_ptr_arm64e_auth_rebase.auth: + entry_offset += image.vm.vm_base_addr + elif starts.pointer_format == dyld_chained_ptr_format.DYLD_CHAINED_PTR_64: + entry_offset = pointer64.generic64.ChainedPointerGeneric64.dyld_chained_ptr_64_rebase.target + elif starts.pointer_format == dyld_chained_ptr_format.DYLD_CHAINED_PTR_64_OFFSET: + entry_offset = pointer64.generic64.ChainedPointerGeneric64.dyld_chained_ptr_64_rebase.target + image.vm.vm_base_addr + #elif starts.pointer_format == dyld_chained_ptr_format.DYLD_CHAINED_PTR_64_KERNEL_CACHE or \ + # starts.pointer_format == dyld_chained_ptr_format.DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE: + # entry_offset = pointer64. + elif starts.pointer_format == dyld_chained_ptr_format.DYLD_CHAINED_PTR_32 or starts.pointer_format == dyld_chained_ptr_format.DYLD_CHAINED_PTR_32_CACHE: + entry_offset = pointer32.generic32.dyld_chained_ptr_32_rebase.target + elif starts.pointer_format == dyld_chained_ptr_format.DYLD_CHAINED_PTR_32_CACHE: + entry_offset = pointer32.generic32.dyld_chained_ptr_32_firmware_rebase.target + + rebases[pointer64.off] = entry_offset + chain_entry_address += next_entry_stride_count * stride_size if (chain_entry_address > page_addr + starts.page_size): log.error("Pointer left page, bailing fixup processing, binary is malformed") @@ -544,7 +574,7 @@ def from_image(cls, image: Image, chained_fixup_cmd: linkedit_data_command): if next_entry_stride_count == 0: fixups_done = True - return cls(syms) + return cls(syms, rebases) @classmethod def from_values(cls, *args, **kwargs): @@ -553,8 +583,11 @@ def from_values(cls, *args, **kwargs): def raw_bytes(self): pass - def __init__(self, symbols): + def __init__(self, symbols, rebases=None): + if rebases is None: + rebases = {} self.symbols = symbols + self.rebases = rebases export_node = namedtuple("export_node", ['text', 'offset', 'flags'])