From 11bd8dd512d4bcbcedd0c7c46c6eff0ece23ece9 Mon Sep 17 00:00:00 2001 From: Jonathan Herrewijnen Date: Thu, 8 Aug 2024 19:46:04 +0200 Subject: [PATCH] changed exploit flow --- .../source/BootROM_8890/boot_chain.rst | 10 +- source/exploit/.vscode/launch.json | 23 ++- source/exploit/exploit.py | 183 +++++++++++------- 3 files changed, 140 insertions(+), 76 deletions(-) diff --git a/documentation/source/BootROM_8890/boot_chain.rst b/documentation/source/BootROM_8890/boot_chain.rst index d49e4c0..3a1c3d2 100644 --- a/documentation/source/BootROM_8890/boot_chain.rst +++ b/documentation/source/BootROM_8890/boot_chain.rst @@ -10,14 +10,20 @@ Current boot chain: Boot chain +As done by Frederic, the bootrom can be dumped using his provided scripts, and can the be split into different boots: + +.. code-block:: bash + + ./exynos-usbdl e payloads/Exynos8890_dump_bootrom.bin dumped_sboot.bin + scripts/split-sboot-8890.sh dumped_sboot.bin + debugger ======== Some other information about the debugger and it's current state. bl1 === - -Loads at address ``0x02024000`` and contains some form of header. +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``. diff --git a/source/exploit/.vscode/launch.json b/source/exploit/.vscode/launch.json index 78a455b..3bbe32b 100644 --- a/source/exploit/.vscode/launch.json +++ b/source/exploit/.vscode/launch.json @@ -5,21 +5,38 @@ "version": "0.2.0", "configurations": [ { - "name": "Debug exploit", + "name": "Debug usb stack", "type": "debugpy", "request": "launch", "program": "exploit.py", "console": "integratedTerminal", - "args": ["--debug"] + "args": ["--usb-debug"] }, { - "name": "Run chain", + "name": "Run boot chain", + "type": "debugpy", + "request": "launch", + "program": "exploit.py", + "console": "integratedTerminal", + "justMyCode": false, + "args": ["--run-boot-chain"] + }, + { + "name": "Debug on device", "type": "debugpy", "request": "launch", "program": "exploit.py", "console": "integratedTerminal", "justMyCode": false, "args": [] + }, + { + "name": "Debug current file", + "type": "debugpy", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": false, } ] } \ No newline at end of file diff --git a/source/exploit/exploit.py b/source/exploit/exploit.py index 0a0b754..4ecddab 100644 --- a/source/exploit/exploit.py +++ b/source/exploit/exploit.py @@ -1,4 +1,3 @@ -import usb.util, usb.core import struct, sys, usb1, libusb1, ctypes, usb, argparse from keystone import * from capstone import * @@ -6,6 +5,7 @@ from ghidra_assistant.utils.utils import * from ghidra_assistant.concrete_device import * from ghidra_assistant.utils.debugger.debugger_archs.ga_arm64 import GA_arm64_debugger from qiling.const import QL_ARCH +import os def p32(x): return struct.pack("= 0x02020F08: + print(f'stack_pointer at {stack_pointer}') + return dumped def auth_bl1(): # Load the firmware @@ -251,6 +298,8 @@ class ExynosDevice(): # self.cd.arch_dbg.state.LR = 0x2069000 #jump back to debugger when finished # self.cd.restore_stack_and_jump(0x00012814) # self.cd.restore_stack_and_jump(0x000125b4) + + dumped = memdump_try() bl1 = open("../S7/bl1.bin", "rb").read() self.cd.memwrite_region(0x02024000, bl1) @@ -265,6 +314,7 @@ class ExynosDevice(): self.cd.arch_dbg.state.LR = 0x2069000 self.cd.restore_stack_and_jump(0x02021810) bl31 = open("../S7/bl31.bin", "rb").read() + self.cd.memwrite_region(0x02021800, bl31) jump_bl31() assert self.usb_read(0x200) == b"GiAs", "not jumped back to debugger?" @@ -276,14 +326,34 @@ class ExynosDevice(): #authenticate it pass + - def run_boot_chain(self): - stage1 = open("stage1/stage1.bin", "rb").read() - self.exploit(stage1) - - def run_debugger(): - # TODO, hardcoded path - debugger = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin", "rb").read() + def setup_guppy_debugger(self): + """ + Run the boot chain for the Exynos device. + + Load and send stage1 payload - exploit (stage1) + """ + + def _setup_debugger(): + ''' + Setup the debugger as a concrete device + ''' + self.cd = ConcreteDevice(None, False) + self.cd.dev = self.setup_concrete_device(self.cd) + self.cd.test_connection() + + + def _initial_run_debugger(): + """Write debugger to device and test basic functionality""" + if os.getenv("USER") == "eljakim": + debugger = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/debugger.bin", "rb").read() + else: + try: + debugger = open("../../dump/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) debugger += ((0x2000 - len(debugger)) * b"\x00") assert len(debugger) == 0x2000, "Invalid debugger size, stage1 requires 0x2000 size" for block in range(0, len(debugger), 0x200): @@ -296,57 +366,28 @@ class ExynosDevice(): r = self.usb_read(0x200) assert r == b"PONG", f"Invalid response from device: {r}" - run_debugger() - self.setup_debugger() - - self.dumb_interact() - - - -def usb_debug(): - ''' - Function to debug USB behavior - ''' - - shellcode = open("../dwc3_test/dwc3.bin", "rb").read() - assert len(shellcode) <= MAX_PAYLOAD_SIZE, "Shellcode too big" - - exynos = ExynosDevice() - exynos.exploit(shellcode) - - transferred = ctypes.c_int() - # Send some data - count = 0 - def send_data(): - transferred.value = 0 - p = p32(count) + b"\xaa" * (0x200 - 4) - res = libusb1.libusb_bulk_transfer(exynos.handle._USBDeviceHandle__handle, ENDPOINT_BULK_OUT, p, len(p), ctypes.byref(transferred), 100) - assert res == 0, "Error sending data" - - def recv_data(): - transferred.value = 0 - buf = ctypes.c_buffer(b"", 0x200) - res = libusb1.libusb_bulk_transfer(exynos.handle._USBDeviceHandle__handle, 0x81, buf, len(buf), ctypes.byref(transferred), 100) - assert res == 0, "Error receiving data" - hexdump(buf.raw) - pass - - # Should have received some bytes - while True: - send_data() - recv_data() - count += 1 + _initial_run_debugger() + _setup_debugger() if __name__ == "__main__": arg = argparse.ArgumentParser("Exynos exploit") - arg.add_argument("--debug", action="store_true", help="Debug USB stack", default=False) - - # Debug mode + arg.add_argument("--usb-debug", action="store_true", help="Debug USB stack", default=False) + arg.add_argument("--run-boot-chain", action="store_true", help="Run boot chain to boot different boot stages", default=False) + arg.add_argument("--dumb-debug", action="store_true", help="Live debugging on device", default=True) args = arg.parse_args() - if args.debug: - usb_debug() - sys.exit(0) exynos = ExynosDevice() - exynos.run_boot_chain() + + if args.usb_debug: + shellcode = open("../dwc3_test/dwc3.bin", "rb").read() + exynos.exploit(shellcode) + exynos.usb_debug() + + elif args.run_boot_chain: + stage1 = open("stage1/stage1.bin", "rb").read() + exynos.exploit(stage1) + exynos.setup_guppy_debugger() + exynos.dumb_interact() + + sys.exit(0)