Revert changes in exploit.py

This commit is contained in:
Jonathan Herrewijnen 2024-08-21 19:00:18 +02:00
parent 34ca995109
commit 416521c8c7
7 changed files with 1489 additions and 79 deletions

View File

@ -12,7 +12,9 @@ pages:
- python -m venv venv - python -m venv venv
- source venv/bin/activate - source venv/bin/activate
- pip install -r <(head -n -1 requirements.txt) - pip install -r <(head -n -1 requirements.txt)
- documentation/make html - cd documentation
- make html
- cd ..
- cp -r documentation/build/* .public - cp -r documentation/build/* .public
- mv .public public - mv .public public
artifacts: artifacts:

View File

@ -17,8 +17,6 @@ After exploitation the goal is to fully boot the device. The following part desc
This is under development and will still change. This is under development and will still change.
BL1
---
The first stage is downloading BL1, authenticating it and patching it after authentication. 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. 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: In the debugger we can authenticate BL1, patch it and boot it. An overview of this process is shown below:
@ -36,8 +34,6 @@ Booting an authenticated and patched BL1:
Next up is BL31, which is loaded by BL1. 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. ``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 .. figure:: images/bl31_debugger_memory_example.png
@ -127,8 +123,9 @@ The processor state reported then is:
X21 : 0x0 | X22 : 0x0 | X23 : 0x0 | X24 : 0x0 | X25 : 0x0 | X26 : 0x0 | X27 : 0x1 | X21 : 0x0 | X22 : 0x0 | X23 : 0x0 | X24 : 0x0 | X25 : 0x0 | X26 : 0x0 | X27 : 0x1 |
X28 : 0x0 | X29 : 0x2020f00 | LR/X30 : 0x20c0000 | SP/X31 : 0x2020ef0 X28 : 0x0 | X29 : 0x2020f00 | LR/X30 : 0x20c0000 | SP/X31 : 0x2020ef0
Initial boot function Initial boot function (BL1)
--- ---------------------
.. figure:: images/initial_boot_function.png .. figure:: images/initial_boot_function.png
:align: center :align: center
@ -186,9 +183,79 @@ BL1 is laoded at the download buffer and self copies to ``0x02024000`` and resum
However, this does not result in a jump back to the debugger. But the ROM still allows receival of one data package from the USB host (this is likely the system 'waiting' to receive the bootloader). However, this does not result in a jump back to the debugger. But the ROM still allows receival of one data package from the USB host (this is likely the system 'waiting' to receive the bootloader).
By adding the IMEM to ghidra, we can have a look at what is going here. (How is this done in Ghidra?). We seem to lose control of our debugger once we step into the `some_weird_brom_function`. By adding the IMEM to ghidra, we can have a look at what is going here. After having modified the LR to jump back to the debugger and jumping into auth_bl1 at ``0x00012848`` we jump back to the debugger. Jumping into BL1 at ``2c0`` does not return us to the debugger. Here we need to hijack ``020200dc`` and ``02021880`` we're able to boot into BL1. We store the address of the hijacked function, to restore it later for a proper boot flow.
.. code:: python
auth_bl1(DEBUGGER_ADDR)
self.usb_write(b"FLSH") # Flush cache
hijacked_fun = u32(self.cd.memdump_region(0x020200dc, 4))
# BL1 patches
self.cd.memwrite_region(0x020200dc, p32(DEBUGGER_ADDR)) # hijack ROM_DOWNLOAD_USB for BL31
self.cd.memwrite_region(0x02021880, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR, branch_ins="br"))
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";
};
Probably the only thing it does is set some clocks and prepare for BL31.
BL31
----
BL31 is written at 0x02024000 with the entry point at 0x02024010.
BL2
---
0x02e8dc mentions 'Onyx-OPR6-8511R1', which is likely sboot.
OLD
---
TODO TODO TODO
The reason for this is the following code in bl1: The reason for this is the following code in bl1:
.. code-block:: c .. code-block:: c
@ -238,52 +305,3 @@ Replacing this function with our debugger makes us jump back:
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. 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";
};
Probably the only thing it does is set some clocks and prepare for BL31

View File

@ -39,7 +39,13 @@ TODO make memory layout of ROM, IMEM and some devices @JONHE
.. figure:: images/memory_layout.drawio.svg .. figure:: images/memory_layout.drawio.svg
The memory layout of the Exynos 8890 The memory layout of the Exynos 8890
- 0x00000000 to 0x00020000: BootROM
- 0x000002c0: BL1 boot entry point
- 0x00012848: bootrom authentication function
- 0x00019310: BL1 boot function
- 0x02069000: First debugger location
Download protocol Download protocol
----------------- -----------------

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,8 @@ extensions = [ 'myst_parser',
templates_path = ['_templates'] templates_path = ['_templates']
exclude_patterns = [] exclude_patterns = []
# Ignore
exclude_patterns = ['_ignore']
# select the theme # select the theme
html_theme = 'sphinx_wagtail_theme' html_theme = 'sphinx_wagtail_theme'

View File

@ -12,4 +12,7 @@ pyhidra
sphinxcontrib.confluencebuilder sphinxcontrib.confluencebuilder
sphinxcontrib.drawio sphinxcontrib.drawio
sphinx_wagtail_theme sphinx_wagtail_theme
plotly
numpy
nbformat>4.2.0
source/ghidra_assistant/ghidra_assistant-0.0.1-py3-none-any.whl source/ghidra_assistant/ghidra_assistant-0.0.1-py3-none-any.whl

View File

@ -625,18 +625,6 @@ class ExynosDevice():
self.cd.memwrite_region(0x02021880, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR, branch_ins="br")) self.cd.memwrite_region(0x02021880, self.cd.arch_dbg.sc.branch_absolute(DEBUGGER_ADDR, branch_ins="br"))
# self.cd.memwrite_region(0x020200a0, p32(DEBUGGER_ADDR))
# self.cd.memwrite_region(0x020200d0, p32(DEBUGGER_ADDR))
# self.cd.memwrite_region(0x020200b4, p32(DEBUGGER_ADDR))
# self.cd.memwrite_region(0x020200a4, p32(DEBUGGER_ADDR))
# self.cd.memwrite_region(0x0202297c, self.cd.arch_dbg.sc.mov_0_w0_ins + self.cd.arch_dbg.sc.ret_ins)
GADGET_RET0 = 0x00000d58
# self.cd.memwrite_region(0x20296da , p32(GADGET_RET0))
# self.cd.memwrite_region(0x20296da + 4, p32(GADGET_RET0))
# END # END
jump_bl1(DEBUGGER_ADDR) jump_bl1(DEBUGGER_ADDR)
@ -655,7 +643,9 @@ class ExynosDevice():
self.usb_read(0x200) # GiAs self.usb_read(0x200) # GiAs
# lr = self.cd.arch_dbg.state.LR # lr = self.cd.arch_dbg.state.LR
self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) # Resore oginal boot flow
# self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) # Resore oginal boot flow
# TODO patch verification # TODO patch verification
@ -677,13 +667,22 @@ class ExynosDevice():
# ====== PATCHES TO BL31 here! ====== # ====== PATCHES TO BL31 here! ======
# Jump BL31 # Jump entry BL31
self.cd.restore_stack_and_jump(0x02024010) self.cd.restore_stack_and_jump(0x02024010)
time.sleep(2) time.sleep(2)
self.connect_device() self.connect_device()
# WORKING
assert self.usb_read(0x200) == b"GiAs", "Failed to jump back to debugger"
self.cd.memwrite_region(0x020200dc, p32(hijacked_fun)) #Sets jump/X1 address at X0 0x2048000 -> Entry point of BL2
self.cd.memwrite_region(0x02020, p32(DEBUGGER_ADDR)) # Restore original boot flow
# Jump into BL2
self.cd.restore_stack_and_jump(hijacked_fun)
# END
# self.usb_read(0x200) # GiAs # self.usb_read(0x200) # GiAs
# self.cd.restore_stack_and_jump(hijacked_fun) # self.cd.restore_stack_and_jump(hijacked_fun)
@ -697,12 +696,12 @@ class ExynosDevice():
# ==== Stage 4 ==== # ==== Stage 4 ====
stage4 = open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read() stage4 = open("../S7/g930f_latest/g930f_sboot.bin.4.bin", "rb").read()
# Patching # Patching
stage4_len = len(stage4) # stage4_len = len(stage4)
patch_len = len(b"USB RECOVERY MODE") # patch_len = len(b"USB RECOVERY MODE")
patch = b"ELHER HERE" + (b"\x00" * (patch_len - len(b"ELHER HERE"))) # patch = b"ELHER HERE" + (b"\x00" * (patch_len - len(b"ELHER HERE")))
patch_offset = stage4.find(b"USB RECOVERY MODE") # patch_offset = stage4.find(b"USB RECOVERY MODE")
stage4 = stage4[:patch_offset] + patch + stage4[patch_len + patch_offset:] # stage4 = stage4[:patch_offset] + patch + stage4[patch_len + patch_offset:]
assert len(stage4) == stage4_len, "Invalid stage4 length" # assert len(stage4) == stage4_len, "Invalid stage4 length"
self.send_normal_stage(stage4) self.send_normal_stage(stage4)
time.sleep(2) time.sleep(2)