Skip to content

Commit

Permalink
Add rebase opcode parsing and some quickstart fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
0cyn committed Jan 10, 2024
1 parent 507e5df commit e3c8436
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 5 deletions.
6 changes: 3 additions & 3 deletions docs/source/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 35 additions & 2 deletions src/ktool/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()}')
Expand Down Expand Up @@ -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]:
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -537,14 +540,41 @@ 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")
fixups_done = True
if next_entry_stride_count == 0:
fixups_done = True

return cls(syms)
return cls(syms, rebases)

@classmethod
def from_values(cls, *args, **kwargs):
Expand All @@ -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'])
Expand Down

0 comments on commit e3c8436

Please sign in to comment.