245 lines
8.2 KiB
ReStructuredText
245 lines
8.2 KiB
ReStructuredText
.. _boot-chain-label:
|
|
=======
|
|
Booting
|
|
=======
|
|
|
|
After exploitation the goal is to fully boot the device.
|
|
|
|
Current boot chain:
|
|
|
|
.. figure:: images/boot_chain.drawio.svg
|
|
:align: center
|
|
|
|
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
|
|
|
|
This results in the following files:
|
|
|
|
.. 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?
|
|
|
|
debugger
|
|
========
|
|
After the initial loading of the debugger, the state reported is:
|
|
|
|
.. code:: bash
|
|
|
|
root | DEBUG |
|
|
X0 : 0x0 | X1 : 0xffffffff | 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 : 0x206d000 | 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 : 0x20219b8 | SP/X31 : 0x2020ef0
|
|
|
|
With the original 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
|
|
|
|
|
|
|
|
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.
|
|
|
|
.. code-block:: python
|
|
|
|
self.cd.arch_dbg.state.auto_sync = False
|
|
self.cd.arch_dbg.state.auto_sync_special = False
|
|
self.cd.arch_dbg.state.print_ctx()
|
|
|
|
def relocate_debugger():
|
|
# Seems to be cleared upon cache clearing??
|
|
debugger_reloc = open("/home/eljakim/Source/gupje/source/bin/samsung_s7/reloc_debugger.bin", "rb").read()
|
|
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()
|
|
|
|
|
|
|
|
|
|
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``.
|
|
|
|
.. code-block:: python
|
|
|
|
# Try loading bl1
|
|
bl1 = open("../S7/bl1.bin", "rb").read()
|
|
self.cd.memwrite_region(0x02021800, bl1)
|
|
# self.usb_write(b"FLSH")
|
|
AUTH_BL1 = 0x00012848
|
|
def auth_bl1(lr=0x2069000):
|
|
# Load the firmware
|
|
self.cd.arch_dbg.state.W0 = 1
|
|
self.cd.arch_dbg.state.X1 = 1
|
|
self.cd.arch_dbg.state.LR = lr #jump back to debugger when finished
|
|
self.cd.restore_stack_and_jump(AUTH_BL1)
|
|
assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger"
|
|
assert self.cd.arch_dbg.state.X0 == 0, "auth_bl1 returned with error!"
|
|
|
|
auth_bl1(0x020c0000)
|
|
|
|
After authentication the bootROM jumps to it, we can execute this function with the debugger.
|
|
|
|
.. code-block:: python
|
|
|
|
self.cd.memwrite_region(0x02020f60, p32(0x020c0000))
|
|
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)
|
|
|
|
jump_fwbl1()
|
|
|
|
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
|
|
|
|
TODO TODO TODO
|
|
The reason for this is the following code in bl1:
|
|
|
|
.. code-block:: c
|
|
|
|
iVar3 = FUN_02024320();
|
|
if (iVar3 == 1) {
|
|
(*(code *)(ulong)uRam0000000002020108)(0,1);
|
|
}
|
|
|
|
This code uses a predefined ROM function(I was looking for it) and jumps back to that function when it's done.
|
|
This function is at address ``0x020200e8``, looking in our IMEM dump we can see where in the ROM this points to:
|
|
|
|
.. code-block:: c
|
|
|
|
DAT_02020108 XREF[2]: FUN_00001708:000018b4(W),
|
|
FUN_02021970:02021a40(R)
|
|
02020108 90 57 00 00 undefined4 00005790h
|
|
|
|
Replacing this function with our debugger makes us jump back:
|
|
|
|
.. code-block:: python
|
|
|
|
# Overwrite jump back
|
|
self.cd.memwrite_region(0x02020108, p32(0x2069000))
|
|
self.cd.memwrite_region(0x020200e8, p32(0x2069000))
|
|
|
|
def jump_bl1():
|
|
self.cd.arch_dbg.state.LR = 0x2069000
|
|
self.cd.restore_stack_and_jump(0x02024010)
|
|
# self.cd.restore_stack_and_jump(0x02021810)
|
|
|
|
bl1 = open("../S7/bl1.bin", "rb").read()
|
|
self.cd.memwrite_region(0x02024000, bl1)
|
|
self.usb_write(b"FLSH")
|
|
|
|
# auth_bl1()
|
|
jump_bl1()
|
|
assert self.usb_read(0x200) == b"GiAs", "not jumped back to debugger?"
|
|
self.cd.arch_dbg.state.print_ctx()
|
|
|
|
root | DEBUG |
|
|
X0 : 0xc00000 | X1 : 0x2069000 | X2 : 0x0 | X3 : 0x2023114 | X4 : 0x4 | X5 : 0x0 | X6 : 0x0 |
|
|
X7 : 0x136c0008 | X8 : 0x2069000 | X9 : 0x0 | X10 : 0x2070000 | X11 : 0x0 | X12 : 0x0 | X13 : 0x0 |
|
|
X14 : 0xf | X15 : 0x206d000 | X16 : 0x9 | X17 : 0x0 | X18 : 0x1 | X19 : 0x20200e8 | X20 : 0x0 |
|
|
X21 : 0x80000000 | X22 : 0x0 | X23 : 0x0 | X24 : 0x0 | X25 : 0x0 | X26 : 0x0 | X27 : 0x1 |
|
|
X28 : 0x0 | X29 : 0x2020ed8 | LR/X30 : 0x202419c | SP/X31 : 0x2020ec0
|
|
|
|
However this does not fully run bl1, so we will have to dig a bit deeper to see the puropose and when to jump back to the debugger.
|
|
|
|
Authentication of BL1 seems to be done at ``0x0012848``. With return value '0' expected when this function is executed, to execute other functions.
|
|
|
|
.. figure:: images/bl1_auth_references.png
|
|
:align: center
|
|
|
|
BL1 authentication.
|
|
|
|
purpose
|
|
-------
|
|
bl1 interacts with several pheriperals, from the DTB these are:
|
|
|
|
.. code-block:: dtsi
|
|
|
|
/* FSYS0 */
|
|
pinctrl_5: pinctrl@10E60000 {
|
|
compatible = "samsung,exynos8890-pinctrl";
|
|
reg = <0x0 0x10E60000 0x1000>;
|
|
interrupts = <0 212 0>;
|
|
};
|
|
|
|
/* FSYS1 */
|
|
pinctrl_6: pinctrl@15690000 {
|
|
compatible = "samsung,exynos8890-pinctrl";
|
|
reg = <0x0 0x15690000 0x1000>;
|
|
interrupts = <0 202 0>;
|
|
};
|
|
|
|
/* PERIC1 */
|
|
pinctrl_9: pinctrl@14CC0000 {
|
|
compatible = "samsung,exynos8890-pinctrl";
|
|
reg = <0x0 0x14CC0000 0x1000>;
|
|
interrupts = <0 460 0>;
|
|
};
|
|
|
|
pmu_system_controller: system-controller@105C0000 {
|
|
compatible = "samsung,exynos8890-pmu", "syscon";
|
|
reg = <0x0 0x105C0000 0x10000>;
|
|
};
|
|
|
|
rtc@10070000 {
|
|
compatible = "samsung,s3c6410-rtc";
|
|
reg = <0x0 0x10070000 0x100>;
|
|
interrupts = <0 73 0>, <0 74 0>;
|
|
clocks = <&clock 157>;
|
|
clock-names = "gate_rtc";
|
|
};
|
|
|
|
|
|
BL31
|
|
----
|
|
|
|
Setups EL3 stuff, probably in preperation of loading trustzone |