## https://sploitus.com/exploit?id=71243956-DFA6-5F79-BFB3-9215DC1C4D44
# SM-G985F / Exynos9830 Bootrom exploit
> [!CAUTION]
> The current key bundle and generated files are fusing-capable. Once a device has been fused,
> the eFuse change is irreversible and the device must continue to use boot images and key material that
> match the fused key. Using these files or flows is at your own risk because of the fusing behavior;
> all consequences remain the responsibility of the user running them. Verify the eFuse file, private
> keys, signed FWBL1, LK / `sboot.bin` images, and target device before running any fusing flow.
## Contents
- [Repository Layout](#repository-layout)
- [Requirements](#requirements)
- [Image Preparation](#image-preparation)
- [Payload Build](#payload-build)
- [Signed SBoot Image Generation](#signed-sboot-image-generation)
- [Exploit Modes](#exploit-modes)
- [Exynos 9830 Boot Chain](#exynos-9830-boot-chain)
- [Exynos 9830 Image Layout](#exynos-9830-image-layout)
- [Load Addresses](#load-addresses)
- [Boot Source IDs](#boot-source-ids)
- [Dump /mem Payload](#dump-mem-payload)
- [Upstream Attribution](#upstream-attribution)
- [Credits](#credits)
## Repository Layout
| Path | Purpose |
|-------------------------------------|-----------------------------------------------------------------------------------------------------|
| `bootLoaderFiles/` | Bootloader binaries, split bootloader parts, original images, decrypted images, and dump artifacts. |
| `bootromNotes/` | Boot ROM notes, flowcharts, and USB context offsets. |
| `exploit/` | Python tooling, exploit runner, split/merge scripts, payload build helper, and SoC data. |
| `exploit/extra/images/` | Working bootloader images consumed by the exploit flows. |
| `exploit/extra/payloads/` | Built payload binaries copied from `external/payloads/`. |
| `external/` | Payload sources, build Makefile, decompiled notes, shared key material, and helper tools. |
| `external/keys/exynos9830_crecker/` | Shared Exynos9830 / Exynos990 custom-key bundle used by the signed-loader flow. |
| `exynos990reverseEng/` | Exynos 990 reverse engineering project files. |
## Requirements
### Linux Toolchain
```bash
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
```
### macOS Toolchain
```bash
brew tap messense/macos-cross-toolchains
brew install aarch64-unknown-linux-gnu
```
### Python Dependencies
```bash
python3 -m pip install -r requirements.txt
```
`requirements.txt` includes `coloredlogs`, `cryptography`, `hexdump`, `libusb`, `pyusb`, and `pycryptodome`.
### Windows USB Driver
On Windows, the BootROM USB device `04e8:1234` must use a WinUSB/libusb-compatible
driver before PyUSB can open it. See `exploit/windows/README.md`.
The repository includes a WinUSB driver package at
`exploit/windows/Exynos_USB_Device.inf`, with its matching catalog and certificate
import file in the same directory.
## Image Preparation
### Split `sboot.bin`
```bash
python3 exploit/split.py bootLoaderFiles/originalSboot_K/sboot.bin -o exploit/extra/images
```
The split script writes image parts and a `split_manifest.json` file into the output directory.
### Patch LK Custom Key
The LK image must use the ROM secure boot key 2 command IDs for the custom-key flow:
| Key 1 command | Value | Key 2 command | Value |
|-------------------------------|---------|-------------------------------|---------|
| `CMD_W_ROM_SEC_BOOT_KEY1` | `0x001` | `CMD_W_ROM_SEC_BOOT_KEY2` | `0x016` |
| `CMD_W_USE_ROM_SEC_BOOT_KEY1` | `0x002` | `CMD_W_USE_ROM_SEC_BOOT_KEY2` | `0x017` |
| `CMD_C_ROM_SEC_BOOT_KEY1` | `0x100` | `CMD_C_ROM_SEC_BOOT_KEY2` | `0x114` |
| `CMD_R_USE_ROM_SEC_BOOT_KEY1` | `0x101` | `CMD_R_USE_ROM_SEC_BOOT_KEY2` | `0x115` |
When applying the LK patch TSV inside the Ghidra project, the helper was called through
Ghidra headless like this:
```bash
GHIDRA=/path/to/ghidra_12.0.4_PUBLIC
REPO=$(pwd)
"$GHIDRA/support/analyzeHeadless" "$REPO/exynos990reverseEng" exynos990 \
-process lk.bin \
-noanalysis \
-scriptPath "$REPO/external/ghidra" \
-postScript ApplyLkPatches.java "$REPO/external/ghidra/lk_985_selected_patches.tsv"
```
Embed the 32-byte eFuse key into `lk.bin` at offset `0x205008`, replacing the stock key:
```bash
dd if=external/keys/exynos9830_crecker/crecker.efuse of=exploit/extra/images/lk.bin bs=1 seek=$((0x205008)) count=32 conv=notrunc
xxd -g1 -s $((0x205008)) -l 32 exploit/extra/images/lk.bin
```
### Merge Split Parts
```bash
python3 exploit/merge.py exploit/extra/images Exynos9830
```
The merge script writes `sboot.bin` in the current working directory.
## Payload Build
Build the payload projects under `external/payloads/` and copy the resulting binaries into `exploit/extra/payloads/`:
```bash
./exploit/build_payloads.sh
```
| Payload | Output path | Purpose |
|---------------------------------|--------------------------------------------------------|------------------------------------------------------|
| `mem.bin` | `exploit/extra/payloads/mem.bin` | Boot ROM memory dump payload. |
| `loader.bin` | `exploit/extra/payloads/loader.bin` | UFS path payload used by `--ufs`. |
| `Exynos990_boot_custom_key.bin` | `exploit/extra/payloads/Exynos990_boot_custom_key.bin` | Custom-key signed-loader payload used by `--signed`. |
The UFS loader and custom-key payload embed a 32-byte efuse file at build time.
By default the Makefile reads `external/keys/exynos9830_crecker/crecker.efuse`;
override this with `CUSTOM_KEY_EFUSE=/path/to/crecker.efuse` when needed.
## Signed SBoot Image Generation
The preflight step run by `exploit/exploit.py` re-signs the SBoot image set in
`exploit/extra/images/` in place before each signed run. No separate signed
output is kept. The signing step uses the intentionally tracked shared key
bundle under `external/keys/exynos9830_crecker/`.
Equivalent repo-root command for the complete image set:
```bash
python3 external/tools/sign_sboot_images.py \
--images-dir exploit/extra/images \
--keys-dir external/keys/exynos9830_crecker
```
This signs:
| Image | Key material used | Rollback revision |
|---------------|------------------------------------------|-------------------|
| `fwbl1.img` | BL1 private key + Stage2 TEE/REE pubkeys | `23` |
| `epbl.img` | Stage2 TEE private key | `23` |
| `bl2.img` | Stage2 REE private key | `23` |
| `lk.bin` | Stage2 REE private key | `23` |
| `el3_mon.img` | Stage2 TEE private key | `23` |
| `ldfw.img` | Stage2 TEE private key, inner + outer | `23` |
| `tzsw.img` | Stage2 TEE private key, inner + outer | `23` |
The batch signer passes decimal `23` for every image and does not reuse an
older rollback value already present in an existing footer.
`epbl.img` is re-encrypted first when needed, then signed over the final bytes.
`ldfw.img` and `tzsw.img` still need the external AVB flow if their AVB content
is meant to be refreshed.
The FWBL1-only command is:
```bash
python3 external/tools/sign_tool.py \
-i exploit/extra/images/fwbl1.img \
-o exploit/extra/images/fwbl1.img \
-k external/keys/exynos9830_crecker/crecker_private.pem \
-H external/keys/exynos9830_crecker/crecker.hmac \
-s 0x3000 \
-r 23 \
-ma 0x9830 \
-m 0x142 \
-e 11 \
-t external/keys/exynos9830_crecker/crecker_stage2_tee_pubkey.bin \
-re external/keys/exynos9830_crecker/crecker_stage2_ree_pubkey.bin
```
Short form when `sign_tool.py`, `fwbl1.img`, and the `crecker_*` files are in the current directory:
```bash
python3 sign_tool.py -i fwbl1.img -o fwbl1.img -k crecker_private.pem -H crecker.hmac -s 0x3000 -r 23 -ma 0x9830 -m 0x142 -e 11 -t crecker_stage2_tee_pubkey.bin -re crecker_stage2_ree_pubkey.bin
```
## Exploit Modes
Run commands from the repository root unless noted otherwise.
| Command | Mode | Default payload | Notes |
|---------------------------------------|-------------------|---------------------------------|--------------------------------------------------------|
| `python3 exploit/exploit.py --ufs` | UFS path | `loader.bin` | Starts the UFS payload flow. |
| `python3 exploit/exploit.py --signed` | Signed Boot Chain | `Exynos990_boot_custom_key.bin` | Re-signs the SBoot image set, sends images. |
| `python3 exploit/exploit.py --dump` | Boot ROM dump | `mem.bin` | Receives `0x20000` bytes into `exynos990.bootrom.bin`. |
### Device Flow Notes
| Step | Note |
|-----:|--------------------------------------------------------------------------------------------------------------|
| 1 | Enter download mode. |
| 2 | Create or update `sboot.bin` with `exploit/merge.py` when needed. |
| 3 | Use the signed custom-key flow to reach Crecker mode, an ODIN-style mode that accepts the target image flow. |
| 4 | Send the new `sboot.bin` through ODIN, Heimdall, or another compatible sender. |
| 5 | Run the UFS payload. |
| 6 | Optional: install CreckerRom for One UI 7 and Strong Integrity workflows. |
| 7 | Optional: lock the bootloader after the target setup is complete. |
## Exynos 9830 Boot Chain
The observed Exynos 9830 boot procedure is:
| Step | Stage | Notes |
|-----:|----------------------|--------------------------------------------------------------------|
| 1 | BootROM | Initial ROM execution. |
| 2 | BL1 | Full handoff from BootROM. |
| 3 | EPBL | Full handoff from BL1. |
| 4 | EPBL | Sets up a minimal SMC handler. |
| 5 | BL2 | EPBL loads BL2. |
| 6 | BL2 | Partial handoff to BL2. |
| 7 | LK | BL2 uses EPBL to load LK, but LK does not immediately execute. |
| 8 | EL3 Monitor | BL2 uses EPBL to load EL3 Monitor. |
| 9 | EL3 Monitor | EPBL decrypts EL3 Monitor. |
| 10 | EL3 Monitor | Full handoff to EL3 Monitor. |
| 11 | EL3 Monitor | Initializes and sets up the extended SMC handler. |
| 12 | LK | Execution jumps to LK. |
| 13 | LK / EL3 Monitor | LK calls into the EL3 Monitor SMC handler to load TrustZone parts. |
| 14 | ODIN / custom target | Boot continues to ODIN or the configured target. |
## Exynos 9830 Image Layout
| Part | Start | End |
|---------------|-----------:|-----------:|
| `fwbl1.img` | `0x0` | `0x3000` |
| `epbl.img` | `0x3000` | `0x16000` |
| `bl2.img` | `0x16000` | `0x82000` |
| `lk.bin` | `0xDB000` | `0x35B000` |
| `el3_mon.img` | `0x35B000` | `0x39B000` |
## Load Addresses
| Stage | Load address |
|---------------|-------------:|
| `BL1` | `0x02022000` |
| `EPBL` | `0x02026000` |
| `BL2` | `0x15600000` |
| `LK` | `0xE8000000` |
| `EL3_MONITOR` | `0xBFE80000` |
## Boot Source IDs
### Raw Boot Source IDs
| `_boot_device` source ID | Boot source path |
|-------------------------:|---------------------------------------------------------------------------|
| `1` | UFS path, shared UFS load flow. |
| `2` | eMMC/SDMMC init path, `mmc_card_detect_and_init` flow. |
| `3` | SDMMC/MMC device 0, `mmc_read_blocks(0, ...)`. |
| `4` | USB load path. |
| `5` | SDMMC/MMC device 1, `mmc_read_blocks(1, ...)`. |
| `6` | UFS alternate mode, same core UFS flow as `1` with a different mode flag. |
| `7` | Non-MMC/UFS/USB raw controller read path. |
| `0xB` / `11` | USB fallback path, then same USB handler as `4`. |
### Boot Source Values
| Source ID | Value | Meaning |
|-------------|-------:|-----------|
| `1` | `0x20` | UFS |
| `2` | `0x14` | eMMC |
| `3` | `0x00` | SDMMC_CH2 |
| `4` / `0xB` | `0x40` | USB |
## Dump /mem Payload
Note: The `mem.bin` dump payload can only be used when no working `sboot` is installed.
1. Send `uh.bin` over Heimdall to the bootloader:
```bash
heimdall flash --BOOTLOADER uh.bin
```
2. Run the dump flow:
```bash
python3 exploit/exploit.py --dump
```
3. Review the generated `exynos990.bootrom.bin` dump.
## Upstream Attribution
Portions of the Python recovery tooling in this repository were adapted
from [halal-beef/hubble](https://github.com/halal-beef/hubble).
That upstream project is published under the GNU GPL v2.0, and this repository keeps a GPL-2.0 license for
compatibility. See [LICENSE](LICENSE) and [NOTICE.md](NOTICE.md).
The Exynos990 custom-key payload under `external/payloads/exynos990_boot_custom_key/` is based on the
boot-custom-key payload skeleton and control-flow idea from
[VDavid003/exynos-usbdl](https://github.com/VDavid003/exynos-usbdl), a fork of
[frederic/exynos-usbdl](https://github.com/frederic/exynos-usbdl). It has been substantially rewritten and
adapted for the Exynos9830 / Exynos990 GET_CONFIGURATION chain, and is not a verbatim copy of the upstream
payload. Because the referenced upstream project is licensed under the GNU GPL v3.0, this payload is kept
under GPL-3.0-only; see `external/payloads/exynos990_boot_custom_key/LICENSE`.
## Credits
| Credit | Contribution |
|----------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Chimera Tool](https://chimeratool.com) | First discovery of the exploit circa 2021-2022. Chimera provides advanced Exynos servicing capabilities across many devices, including capabilities based on this exploit. |
| [CVE-2024-56426](https://semiconductor.samsung.com/support/quality-support/product-security-updates/cve-2024-56426/) | The CVE that this project is based on. |
| Christopher Wade | Reported CVE-2024-56426 to Samsung. |
| [kethily-daniel](https://github.com/kethily-daniel) | Provided access to the tool used for USB packet tracing and sample extraction. |
| [BotchedRPR](https://github.com/BotchedRPR) | Helped with the initial research and creation of carte2. |
| [VDavid003](https://github.com/VDavid003) | Helped reverse engineer the PoC through packet dumps and personally tested on devices. |
| [halal-beef](https://github.com/halal-beef) / [hubble](https://github.com/halal-beef/hubble) | Provided initial USB packet dumps and analysis of the PoC during the research lifecycle, backend code used by the exploit script, and SoC layouts used by the split and merge scripts. |
| [VDavid003](https://github.com/VDavid003) / [exynos-usbdl](https://github.com/VDavid003/exynos-usbdl) | Provided the GPLv3 custom-key payload skeleton and Exynos USB download reference flow used as the basis for the Exynos990 custom-key payload. |
| [R0rt1z2](https://github.com/R0rt1z2) | Helped with payload creation; some work was based on his project, kaeru. |
| [AntiEngineer](https://github.com/AntiEngineer) | Shared ARM knowledge, hints, and research support. |
| AA | Vulnerability inspiration and first use outside of Chimera. |