diff --git a/documentation/source/BootROM_8890/boot_chain.rst b/documentation/source/BootROM_8890/boot_chain.rst index ca78edc..6b8220e 100644 --- a/documentation/source/BootROM_8890/boot_chain.rst +++ b/documentation/source/BootROM_8890/boot_chain.rst @@ -11,15 +11,48 @@ TODO document normal samsung boot chain Exploitation ============ -After exploitation the goal is to fully boot the device. +After exploitation the goal is to fully boot the device. The following part describes the current boot chain -Current boot chain: +.. important:: -.. figure:: images/boot_chain.drawio.svg + This is under development and will still change. + +BL1 +--- +The first stage is downloading BL1, authenticating it and patching it after authentication. +This is done by overwriting the USB return address pointer and jumping back to the debugger. +In the debugger we can authenticate BL1, patch it and boot it. An overview of this process is shown below: + +Booting an authenticated and patched BL1: + +.. figure:: images/boot_chain_bl1.drawio.svg :align: center Boot chain +.. note:: + + git commit 8cb5f2e1 fully boots, you can use this commit to patch bl1 only. + +Next up is BL31, which is loaded by BL1. + +BL31 +---- +``BL31`` is the secure monitor. The monitor uses memory that is also being used by the debugger, so we will have to relocate it to keep code exeuction. + +.. figure:: images/bl31_debugger_memory_example.png + :align: center + + Example of BL31 using debugger memory. + +BL31 also configures the VBAR_EL3 and MMU so the memory mapping will probably change after this stage. + +It would be nice to patch BL31 before it is being executed. However the current exploit boot flow does not allow this because the ROM function downloads the next stage. + + +Notes +----- + As done by Frederic, the bootrom can be dumped using his provided scripts, and can the be split into different boots: .. code-block:: bash @@ -256,6 +289,7 @@ bl1 interacts with several pheriperals, from the DTB these are: clock-names = "gate_rtc"; }; +Probably the only thing it does is set some clocks and prepare for BL31 BL31 ---- diff --git a/documentation/source/BootROM_8890/images/bl31_debugger_memory_example.png b/documentation/source/BootROM_8890/images/bl31_debugger_memory_example.png new file mode 100644 index 0000000..edb8628 Binary files /dev/null and b/documentation/source/BootROM_8890/images/bl31_debugger_memory_example.png differ diff --git a/documentation/source/BootROM_8890/images/boot_chain.drawio.svg b/documentation/source/BootROM_8890/images/boot_chain.drawio.svg deleted file mode 100644 index 7ae49dc..0000000 --- a/documentation/source/BootROM_8890/images/boot_chain.drawio.svg +++ /dev/null @@ -1 +0,0 @@ -
Exploit
Stage1
Debugger
BL1
BL31
\ No newline at end of file diff --git a/documentation/source/BootROM_8890/images/boot_chain_bl1.drawio.svg b/documentation/source/BootROM_8890/images/boot_chain_bl1.drawio.svg new file mode 100644 index 0000000..d7cd35d --- /dev/null +++ b/documentation/source/BootROM_8890/images/boot_chain_bl1.drawio.svg @@ -0,0 +1 @@ +
Exploit
Stage1
Debugger
ROM USB Download
Debugger

Stage1

There is not enough space to load the full debugger in one transaction, so the first stage only configures USB receive and downloads the debugger

Debugger

The debugger hijacks the USB return function and lets the ROM download the next stage. Authenticates it and jumps to it. This allows patching BL1 after authentication
Jump BL1

USB Hijack

Before jumping in BL1 the ROM function for downloading the next stage is also hijacked, giving us code execution after BL1 is loaded
Debugger
\ No newline at end of file diff --git a/documentation/source/BootROM_8890/notes.rst b/documentation/source/BootROM_8890/notes.rst new file mode 100644 index 0000000..59c9c0b --- /dev/null +++ b/documentation/source/BootROM_8890/notes.rst @@ -0,0 +1,16 @@ +======== +Emulator +======== +What is interesting about the ROM is that it starts by checking MPIDR_EL1 register and doing a conditional branch to 0x20e0000. + +.. code-block:: ghidra + + + undefined w0:1 + Reset XREF[1]: Entry Point(*) + 00000000 bb 00 38 d5 mrs x27,mpidr_el1 + 00000004 7b 0f 78 92 and x27,x27,#0xf00 + 00000008 7f 03 00 f1 cmp x27,#0x0 + 0000000c 41 00 00 54 b.ne LAB_00000014 + 00000010 fc 7f 83 14 b LAB_020e0000 + diff --git a/reven/SamsungS7.lock b/reven/SamsungS7.lock deleted file mode 100644 index f90341a..0000000 --- a/reven/SamsungS7.lock +++ /dev/null @@ -1,9 +0,0 @@ -#Ghidra Lock File -#Thu Aug 15 13:43:49 CEST 2024 -OS\ Name=Linux -OS\ Version=6.5.0-44-generic -Username=eljakim -Hostname=levith -\ Supports\ File\ Channel\ Locking=Channel Lock -OS\ Architecture=amd64 -Timestamp=8/15/24, 1\:43 PM diff --git a/reven/SamsungS7.lock~ b/reven/SamsungS7.lock~ deleted file mode 100644 index e69de29..0000000 diff --git a/reven/SamsungS7.rep/idata/00/00000002.prp b/reven/SamsungS7.rep/idata/00/00000002.prp index e9cbf94..aee01aa 100644 --- a/reven/SamsungS7.rep/idata/00/00000002.prp +++ b/reven/SamsungS7.rep/idata/00/00000002.prp @@ -4,7 +4,7 @@ - + diff --git a/reven/SamsungS7.rep/idata/~index.bak b/reven/SamsungS7.rep/idata/~index.bak index 30584e4..3ab1737 100644 --- a/reven/SamsungS7.rep/idata/~index.bak +++ b/reven/SamsungS7.rep/idata/~index.bak @@ -1,9 +1,7 @@ VERSION=1 / 00000006:8890_bootrom.bin:7f0119bc3142241939494339 - 0000000a:8890_bootrom.bin.1:7f011a6853998629050259 - 00000002:8890_bootrom.bin.keep:7f011889d240069673442230 - 00000008:8890_bootrom_old_bl1:7f011822f30596451841878 + 0000000a:8890_bootrom_bl31_loaded:7f011a6853998629050259 /dump 00000009:reloc_debugger.elf:7f0119bd531451643843511 /mib3 @@ -13,5 +11,8 @@ VERSION=1 00000003:bl31.bin:7f011ab837995028720085 00000004:sboot.bin.3.bin:7f011872b8163836628792 00000005:sboot.bin.4.bin:7f011842b8231996037592 +/s7/dump + 00000002:8890_bootrom.bin.keep:7f011889d240069673442230 + 00000008:8890_bootrom_old_bl1:7f011822f30596451841878 NEXT-ID:b MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/reven/SamsungS7.rep/idata/~index.dat b/reven/SamsungS7.rep/idata/~index.dat index e251186..3ab1737 100644 --- a/reven/SamsungS7.rep/idata/~index.dat +++ b/reven/SamsungS7.rep/idata/~index.dat @@ -1,9 +1,7 @@ VERSION=1 / 00000006:8890_bootrom.bin:7f0119bc3142241939494339 - 00000002:8890_bootrom.bin.keep:7f011889d240069673442230 0000000a:8890_bootrom_bl31_loaded:7f011a6853998629050259 - 00000008:8890_bootrom_old_bl1:7f011822f30596451841878 /dump 00000009:reloc_debugger.elf:7f0119bd531451643843511 /mib3 @@ -13,5 +11,8 @@ VERSION=1 00000003:bl31.bin:7f011ab837995028720085 00000004:sboot.bin.3.bin:7f011872b8163836628792 00000005:sboot.bin.4.bin:7f011842b8231996037592 +/s7/dump + 00000002:8890_bootrom.bin.keep:7f011889d240069673442230 + 00000008:8890_bootrom_old_bl1:7f011822f30596451841878 NEXT-ID:b MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/reven/SamsungS7.rep/user/~index.bak b/reven/SamsungS7.rep/user/~index.bak index 257c699..274b54a 100644 --- a/reven/SamsungS7.rep/user/~index.bak +++ b/reven/SamsungS7.rep/user/~index.bak @@ -4,7 +4,8 @@ VERSION=1 00000004:udf_7f011842b8231996037592:7f01190f112184430945139 00000003:udf_7f011872b8163836628792:7f011a9478217161533597 00000001:udf_7f0119bc3142241939494339:7f011abb7142807435236045 + 00000006:udf_7f0119bd531451643843511:7f011a1c131523520933550 00000005:udf_7f011a0d5252765509589854:7f0118e15255467845445248 00000002:udf_7f011ab837995028720085:7f0118cdd8148515697603 -NEXT-ID:6 +NEXT-ID:7 MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/reven/SamsungS7.rep/user/~index.dat b/reven/SamsungS7.rep/user/~index.dat index 274b54a..ff71ce5 100644 --- a/reven/SamsungS7.rep/user/~index.dat +++ b/reven/SamsungS7.rep/user/~index.dat @@ -6,6 +6,7 @@ VERSION=1 00000001:udf_7f0119bc3142241939494339:7f011abb7142807435236045 00000006:udf_7f0119bd531451643843511:7f011a1c131523520933550 00000005:udf_7f011a0d5252765509589854:7f0118e15255467845445248 + 00000007:udf_7f011a6853998629050259:7f011a98934430536471611 00000002:udf_7f011ab837995028720085:7f0118cdd8148515697603 -NEXT-ID:7 +NEXT-ID:8 MD5:d41d8cd98f00b204e9800998ecf8427e diff --git a/reven/SamsungS7.rep/user/~journal.bak b/reven/SamsungS7.rep/user/~journal.bak index 588753e..bd4a967 100644 --- a/reven/SamsungS7.rep/user/~journal.bak +++ b/reven/SamsungS7.rep/user/~journal.bak @@ -1,2 +1,2 @@ -IADD:00000006:/udf_7f0119bd531451643843511 -IDSET:/udf_7f0119bd531451643843511:7f011a1c131523520933550 +IADD:00000007:/udf_7f011a6853998629050259 +IDSET:/udf_7f011a6853998629050259:7f011a98934430536471611 diff --git a/source/emulator/.vscode/launch.json b/source/emulator/.vscode/launch.json new file mode 100644 index 0000000..1ddabb5 --- /dev/null +++ b/source/emulator/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Exynos Emultor", + "type": "debugpy", + "request": "launch", + "program": "emulator.py", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/source/emulator/emulator.py b/source/emulator/emulator.py new file mode 100644 index 0000000..e81467c --- /dev/null +++ b/source/emulator/emulator.py @@ -0,0 +1,36 @@ +from ghidra_assistant.utils.utils import * +from ghidra_assistant.utils.archs.arm64.arm64_emulator import ARM64UC_Emulator +from unicorn.arm64_const import * +from unicorn.unicorn_const import * + +class ExynosEmulator(ARM64UC_Emulator): + def __init__(self, rom_path): + super().__init__() + self.rom_path = rom_path + self.setup() + + def setup(self): + self.setup_memory() + self.setup_registers() + + def setup_memory(self): + #ROM + self.uc.mem_map(0x0, 128 * KB, UC_PROT_READ | UC_PROT_EXEC) + self.uc.mem_write(0x0, open(self.rom_path, "rb").read()) + pass + + def setup_registers(self): + self.pc = 0x0 + self.uc.reg_write(UC_ARM64_REG_PC, self.pc) + + def run(self): + try: + self.uc.emu_start(self.pc, self.pc + 1) + pass + except Exception as e: + self.print_ctx(print) + pass + +if __name__ == '__main__': + emulator = ExynosEmulator("../S7/rom.bin") + emulator.run() \ No newline at end of file diff --git a/source/exploit/exploit.py b/source/exploit/exploit.py index 8ad0527..327374f 100644 --- a/source/exploit/exploit.py +++ b/source/exploit/exploit.py @@ -385,6 +385,23 @@ class ExynosDevice(): assert self.usb_read(0x200) == b"GiAs", "Failed to relocate debugger" self.cd.relocate_debugger(0x020c7000, 0x020c0000, 0x020c4000) + def relocate_debugger_2(self): + # Seems to be cleared upon cache clearing?? + if os.getenv("USER") == "eljakim": + debugger_reloc = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/reloc_debugger.bin", "rb").read() + else: + try: + 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) + def dumb_interact(self, dump_imems=False): ''' @@ -612,15 +629,43 @@ class ExynosDevice(): # ==== BL31 ==== assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger" - self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) # To continue booting next stages - self.cd.restore_stack_and_jump(hijacked_fun) + + self.cd.memwrite_region(self.cd.arch_dbg.state.X0, open("../S7/g930f_latest/g930f_sboot.bin.2.bin", "rb").read()) + + + 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 time.sleep(2) self.connect_device() + + - self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.2.bin", "rb").read()) + self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.2.bin", "rb").read()[:0x10]) + time.sleep(2) + + self.usb_read(0x200) # GiAs + # lr = self.cd.arch_dbg.state.LR + self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) + GADGET_RET0 = 0x00000d58 + self.cd.memwrite_region(0x020200e4, p32(GADGET_RET0)) + + # ====== PATCHES TO BL31 here! ====== + # TODO fix not checking signatures + # self.cd.memwrite_region(0x02031008, b"ELH") + # self.cd.memwrite_region(0x02024774, self.cd.arch_dbg.sc.mov_0_w0_ins + self.cd.arch_dbg.sc.ret_ins) + # self.cd.arch_dbg.state.LR = DEBUGGER_ADDR + # self.cd.arch_dbg.state.X0 = 0x020347f0 + # self.cd.arch_dbg.state.X1 = 0 + # self.cd.restore_stack_and_jump(0x02030464) + self.cd.restore_stack_and_jump(lr) + time.sleep(2) self.connect_device() - time.sleep(1) + + + # self.usb_read(0x200) # GiAs + # self.cd.restore_stack_and_jump(hijacked_fun) # ==== Stage 3 BL2 ==== self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.3.bin", "rb").read()) @@ -629,9 +674,17 @@ class ExynosDevice(): # ==== Stage 4 ==== - self.send_normal_stage(open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read()) + 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) - self.connect_device() + pass diff --git a/source/gupje_device/device.h b/source/gupje_device/device.h index e3e78ff..d255992 100644 --- a/source/gupje_device/device.h +++ b/source/gupje_device/device.h @@ -25,8 +25,8 @@ int mystrlen(char *data) { #define recv_buffer 0x020c6200 #define data_received 0x020c6000 #else -#define recv_buffer 0x206fe00 //0x02021800 + 0x3000 -#define data_received 0x206fd00 +#define recv_buffer 0x206f000 //0x02021800 + 0x3000 +#define data_received 0x206f100 #endif void recv_data_cb(uint32_t endpoint, uint32_t len){ diff --git a/source/gupje_device/reloc2_linkscript.ld b/source/gupje_device/reloc2_linkscript.ld new file mode 100644 index 0000000..3d1a536 --- /dev/null +++ b/source/gupje_device/reloc2_linkscript.ld @@ -0,0 +1,14 @@ +MEMORY { + ROM (rwx): ORIGIN = 0x020c0000, LENGTH = 0x1000 +} + +SECTIONS +{ + . = 0x020c0000; + .text . : { + *(.text*) + *(.data*) + *(.rodata*) + } >ROM + +} \ No newline at end of file diff --git a/source/gupje_device/reloc2_symbols.txt b/source/gupje_device/reloc2_symbols.txt new file mode 100644 index 0000000..bab33dc --- /dev/null +++ b/source/gupje_device/reloc2_symbols.txt @@ -0,0 +1,12 @@ +debugger_storage = 0x020c4000; +debugger_stack = 0x020c2000; +debugger_entry = 0x020c0000; + +maybe_usb_setup_read = 0x00006f88; +dwc3_ep0_start_trans = 0x0000791c; +usb_event_handler = 0x00007bac; +get_endpoint_recv_buffer = 0x00007a7c; +exynos_sleep = 0x000027c8; + +g_recv_buffer = 0x020c6200; +g_data_received = 0x020c6000; \ No newline at end of file