From 11bd8dd512d4bcbcedd0c7c46c6eff0ece23ece9 Mon Sep 17 00:00:00 2001 From: Jonathan Herrewijnen Date: Thu, 8 Aug 2024 19:46:04 +0200 Subject: [PATCH 1/3] 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) From 34c23e0d2a4f9243d8b29688ae76d58eb1d78ae6 Mon Sep 17 00:00:00 2001 From: Jonathan Herrewijnen Date: Fri, 9 Aug 2024 13:15:31 +0200 Subject: [PATCH 2/3] add venv to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index de94b74..d86fd80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ dump/ *.bin *.a +venv/ \ No newline at end of file From 5d6204efa307db6c5e405f34df06203742def1ac Mon Sep 17 00:00:00 2001 From: Jonathan Herrewijnen Date: Fri, 9 Aug 2024 22:16:13 +0200 Subject: [PATCH 3/3] Minor docs update. Trying to dump memory --- .../source/BootROM_8890/boot_chain.rst | 2 + documentation/source/BootROM_8890/index.rst | 28 ++++ source/exploit/.vscode/launch.json | 11 +- source/exploit/exploit.py | 146 ++++++++++-------- 4 files changed, 115 insertions(+), 72 deletions(-) diff --git a/documentation/source/BootROM_8890/boot_chain.rst b/documentation/source/BootROM_8890/boot_chain.rst index 3a1c3d2..4dbced1 100644 --- a/documentation/source/BootROM_8890/boot_chain.rst +++ b/documentation/source/BootROM_8890/boot_chain.rst @@ -1,6 +1,8 @@ +.. _boot-chain-label: ======= Booting ======= + After exploitation the goal is to fully boot the device. Current boot chain: diff --git a/documentation/source/BootROM_8890/index.rst b/documentation/source/BootROM_8890/index.rst index 143a0fa..9fe7aa4 100644 --- a/documentation/source/BootROM_8890/index.rst +++ b/documentation/source/BootROM_8890/index.rst @@ -15,12 +15,40 @@ Samsung Firmware ---------------- Samsung releases firmware files for their devices. These files contain the bootloader, modem, and other firmware files. To see how the ROM works we are interested in the sboot firmware, which contains multiple stages of the bootloader. + To extract the sboot.bin file from a samsung firmware file: .. code-block:: bash $ unzip -p firmware.zip 'BL_*.tar.md5' | tar -Oxf - 'sboot.bin.lz4' | lz4 -d - sboot.bin +Frederic has also written a payload to extract the sboot.bin file from a connected samsung device (See: :ref:`boot-chain-label`). The extracted boots can be split up in different stages. We're provied with sboot 1-4.bin. Running strings then provides us with some information about each stage. + +.. code-block:: bash + + $ 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/.vscode/launch.json b/source/exploit/.vscode/launch.json index 3bbe32b..024e36c 100644 --- a/source/exploit/.vscode/launch.json +++ b/source/exploit/.vscode/launch.json @@ -10,7 +10,7 @@ "request": "launch", "program": "exploit.py", "console": "integratedTerminal", - "args": ["--usb-debug"] + "args": ["--debug"] }, { "name": "Run boot chain", @@ -19,15 +19,6 @@ "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": [] }, { diff --git a/source/exploit/exploit.py b/source/exploit/exploit.py index c01aed2..dc7f979 100644 --- a/source/exploit/exploit.py +++ b/source/exploit/exploit.py @@ -5,7 +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 +import os, tqdm, datetime def p32(x): return struct.pack("