
CVE-2024-56426 Exploit do Bootrom Exynos9830 - SM-G985F
[!CAUTION] O pacote de chaves atual e os arquivos gerados são capazes de fusing. Depois que um dispositivo é submetido ao fusing, a alteração do eFuse é irreversível e o dispositivo deve continuar a usar imagens de boot e material de chaves que correspondam à chave gravada. O uso desses arquivos ou fluxos é por sua conta e risco por causa do comportamento de fusing; todas as consequências permanecem sob responsabilidade do usuário que os executa. Verifique o arquivo eFuse, as chaves privadas, o FWBL1 assinado, as imagens LK /
sboot.bine o dispositivo de destino antes de executar qualquer fluxo de fusing.
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
brew tap messense/macos-cross-toolchains
brew install aarch64-unknown-linux-gnu
python3 -m pip install -r requirements.txt
requirements.txt inclui coloredlogs, cryptography, hexdump, libusb, pyusb e pycryptodome.
No Windows, o dispositivo 04e8:1234 da BootROM deve usar um driver compatível com WinUSB/libusb
antes que o PyUSB possa abri-lo. Consulte exploit/windows/README.md.
O repositório inclui um pacote de driver WinUSB em
exploit/windows/Exynos_USB_Device.inf, com seu catálogo correspondente e o arquivo
de importação de certificado no mesmo diretório.
sboot.binpython3 exploit/split.py bootLoaderFiles/originalSboot_K/sboot.bin -o exploit/extra/images
O script de divisão grava as partes da imagem e um arquivo split_manifest.json no diretório de saída.
A imagem do LK deve usar os IDs de comando da chave 2 de boot seguro da ROM para o fluxo de chave personalizada:
Ao aplicar o TSV de patch do LK dentro do projeto Ghidra, o auxiliar foi chamado por meio do Ghidra headless da seguinte forma:
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"
Insira a chave eFuse de 32 bytes em lk.bin no offset 0x205008, substituindo a chave original:
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
python3 exploit/merge.py exploit/extra/images Exynos9830
O script de mesclagem grava sboot.bin no diretório de trabalho atual.
Compile os projetos de payload em external/payloads/ e copie os binários resultantes em exploit/extra/payloads/:
./exploit/build_payloads.sh
O carregador UFS e o payload de chave personalizada incorporam um arquivo efuse de 32 bytes no momento
da compilação. Por padrão, o Makefile lê external/keys/exynos9830_crecker/crecker.efuse;
substitua isso por CUSTOM_KEY_EFUSE=/path/to/crecker.efuse quando necessário.
A etapa de pré-verificação executada por exploit/exploit.py reassina o conjunto de imagens SBoot em
exploit/extra/images/ no próprio local antes de cada execução assinada. Nenhuma saída assinada
separada é mantida. A etapa de assinatura usa o pacote de chaves compartilhado intencionalmente rastreado
em external/keys/exynos9830_crecker/.
Comando equivalente na raiz do repositório para o conjunto completo de imagens:
python3 external/tools/sign_sboot_images.py \
--images-dir exploit/extra/images \
--keys-dir external/keys/exynos9830_crecker
Isto assina:
O assinador em lote passa o decimal 23 para cada imagem e não reutiliza um
valor de rollback mais antigo já presente em um rodapé existente.
epbl.img é primeiro criptografado novamente quando necessário e depois assinado sobre os bytes finais.
ldfw.img e tzsw.img ainda precisam do fluxo AVB externo se o conteúdo AVB
deles precisar ser atualizado.
O comando apenas para FWBL1 é:
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
Forma abreviada quando sign_tool.py, fwbl1.img e os arquivos crecker_* estão no diretório atual:
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
Execute os comandos a partir da raiz do repositório, salvo indicação em contrário.
O procedimento de boot observado do Exynos 9830 é:
Observação: o payload de dump mem.bin só pode ser usado quando nenhum sboot funcional está instalado.
Envie uh.bin via Heimdall para o bootloader:
heimdall flash --BOOTLOADER uh.bin
Execute o fluxo de dump:
python3 exploit/exploit.py --dump
Revise o dump exynos990.bootrom.bin gerado.
Partes das ferramentas de recuperação em Python deste repositório foram adaptadas de halal-beef/hubble.
Esse projeto upstream é publicado sob a GNU GPL v2.0, e este repositório mantém uma licença GPL-2.0 por compatibilidade. Consulte LICENSE e NOTICE.md.
O payload de chave personalizada do Exynos990 em external/payloads/exynos990_boot_custom_key/ é baseado no
esqueleto de payload de chave de boot personalizada e na ideia de fluxo de controle de
VDavid003/exynos-usbdl, um fork de
frederic/exynos-usbdl. Ele foi substancialmente reescrito e
adaptado para a cadeia GET_CONFIGURATION do Exynos9830 / Exynos990 e não é uma cópia literal do payload
upstream. Como o projeto upstream referenciado é licenciado sob a GNU GPL v3.0, este payload é mantido
sob GPL-3.0-only; consulte external/payloads/exynos990_boot_custom_key/LICENSE.
| Caminho | Finalidade |
|---|
bootLoaderFiles/ | Binários do bootloader, partes do bootloader divididas, imagens originais, imagens descriptografadas e artefatos de dump. |
bootromNotes/ | Notas da ROM de boot, fluxogramas e offsets de contexto USB. |
exploit/ | Ferramentas Python, executor de exploit, scripts de divisão/mesclagem, auxiliar de compilação de payload e dados do SoC. |
exploit/extra/images/ | Imagens de bootloader funcionais consumidas pelos fluxos de exploit. |
exploit/extra/payloads/ | Binários de payload compilados copiados de external/payloads/. |
external/ | Fontes do payload, Makefile de compilação, notas decompiladas, material de chaves compartilhado e ferramentas auxiliares. |
external/keys/exynos9830_crecker/ | Pacote de chave personalizada compartilhado do Exynos9830 / Exynos990 usado pelo fluxo de carregador assinado. |
exynos990reverseEng/ | Arquivos do projeto de engenharia reversa do Exynos 990. |
| Comando da chave 1 | Valor | Comando da chave 2 | Valor |
|---|
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 |
| Payload | Caminho de saída | Finalidade |
|---|
mem.bin | exploit/extra/payloads/mem.bin | Payload de dump de memória da ROM de boot. |
loader.bin | exploit/extra/payloads/loader.bin | Payload do caminho UFS usado por --ufs. |
Exynos990_boot_custom_key.bin | exploit/extra/payloads/Exynos990_boot_custom_key.bin | Payload de carregador assinado com chave personalizada usado por --signed. |
| Imagem | Material de chave usado | Revisão de rollback |
|---|
fwbl1.img | Chave privada do BL1 + chaves públicas TEE/REE do Stage2 | 23 |
epbl.img | Chave privada TEE do Stage2 | 23 |
bl2.img | Chave privada REE do Stage2 | 23 |
lk.bin | Chave privada REE do Stage2 | 23 |
el3_mon.img | Chave privada TEE do Stage2 | 23 |
ldfw.img | Chave privada TEE do Stage2, interna + externa | 23 |
tzsw.img | Chave privada TEE do Stage2, interna + externa | 23 |
| Comando | Modo | Payload padrão | Observações |
|---|
python3 exploit/exploit.py --ufs | Caminho UFS | loader.bin | Inicia o fluxo do payload UFS. |
python3 exploit/exploit.py --signed | Cadeia de Boot Assinada | Exynos990_boot_custom_key.bin | Reassina o conjunto de imagens SBoot e envia as imagens. |
python3 exploit/exploit.py --dump | Dump da ROM de boot | mem.bin | Recebe 0x20000 bytes em exynos990.bootrom.bin. |
| Etapa | Observação |
|---|
| 1 | Entre no modo de download. |
| 2 | Crie ou atualize sboot.bin com exploit/merge.py quando necessário. |
| 3 | Use o fluxo assinado de chave personalizada para alcançar o modo Crecker, um modo no estilo ODIN que aceita o fluxo de imagem de destino. |
| 4 | Envie o novo sboot.bin por meio do ODIN, Heimdall ou outro remetente compatível. |
| 5 | Execute o payload UFS. |
| 6 | Opcional: instale o CreckerRom para fluxos de One UI 7 e Strong Integrity. |
| 7 | Opcional: bloqueie o bootloader depois que a configuração de destino for concluída. |
| Etapa | Estágio | Observações |
|---|
| 1 | BootROM | Execução inicial da ROM. |
| 2 | BL1 | Transferência completa da BootROM. |
| 3 | EPBL | Transferência completa do BL1. |
| 4 | EPBL | Configura um manipulador SMC mínimo. |
| 5 | BL2 | O EPBL carrega o BL2. |
| 6 | BL2 | Transferência parcial para o BL2. |
| 7 | LK | O BL2 usa o EPBL para carregar o LK, mas o LK não é executado imediatamente. |
| 8 | Monitor EL3 | O BL2 usa o EPBL para carregar o Monitor EL3. |
| 9 | Monitor EL3 | O EPBL descriptografa o Monitor EL3. |
| 10 | Monitor EL3 | Transferência completa para o Monitor EL3. |
| 11 | Monitor EL3 | Inicializa e configura o manipulador SMC estendido. |
| 12 | LK | A execução salta para o LK. |
| 13 | LK / Monitor EL3 | O LK chama o manipulador SMC do Monitor EL3 para carregar as partes TrustZone. |
| 14 | ODIN / destino personalizado | O boot continua para o ODIN ou o destino configurado. |
| Parte | Início | Fim |
|---|
fwbl1.img | 0x0 | 0x3000 |
epbl.img | 0x3000 | 0x16000 |
bl2.img | 0x16000 | 0x82000 |
lk.bin | 0xDB000 | 0x35B000 |
el3_mon.img | 0x35B000 | 0x39B000 |
| Estágio | Endereço de carga |
|---|
BL1 | 0x02022000 |
EPBL | 0x02026000 |
BL2 | 0x15600000 |
LK | 0xE8000000 |
EL3_MONITOR | 0xBFE80000 |
ID da fonte _boot_device | Caminho da fonte de boot |
|---|
1 | Caminho UFS, fluxo de carga UFS compartilhado. |
2 | Caminho de inicialização eMMC/SDMMC, fluxo mmc_card_detect_and_init. |
3 | Dispositivo SDMMC/MMC 0, mmc_read_blocks(0, ...). |
4 | Caminho de carga USB. |
5 | Dispositivo SDMMC/MMC 1, mmc_read_blocks(1, ...). |
6 | Modo alternativo UFS, mesmo fluxo UFS principal que 1 com um sinalizador de modo diferente. |
7 | Caminho de leitura bruta do controlador que não é MMC/UFS/USB. |
0xB / 11 | Caminho de fallback USB e depois o mesmo manipulador USB que 4. |
| ID da fonte | Valor | Significado |
|---|
1 | 0x20 | UFS |
2 | 0x14 | eMMC |
3 | 0x00 | SDMMC_CH2 |
4 / 0xB | 0x40 | USB |
| Crédito | Contribuição |
|---|
| Chimera Tool | Primeira descoberta do exploit por volta de 2021-2022. A Chimera fornece capacidades avançadas de manutenção de Exynos em muitos dispositivos, incluindo capacidades baseadas neste exploit. |
| CVE-2024-56426 | A CVE na qual este projeto é baseado. |
| Christopher Wade | Relatou a CVE-2024-56426 à Samsung. |
| kethily-daniel | Forneceu acesso à ferramenta usada para rastreamento de pacotes USB e extração de amostras. |
| BotchedRPR | Ajudou na pesquisa inicial e na criação do carte2. |
| VDavid003 | Ajudou na engenharia reversa do PoC por meio de dumps de pacotes e testou pessoalmente em dispositivos. |
| halal-beef / hubble | Forneceu os dumps iniciais de pacotes USB e a análise do PoC durante o ciclo de pesquisa, o código de backend usado pelo script de exploit e os layouts de SoC usados pelos scripts de divisão e mesclagem. |
| VDavid003 / exynos-usbdl | Forneceu o esqueleto do payload de chave personalizada GPLv3 e o fluxo de referência de download USB Exynos usado como base para o payload de chave personalizada do Exynos990. |
| R0rt1z2 | Ajudou com a criação do payload; parte do trabalho foi baseada no projeto dele, kaeru. |
| AntiEngineer | Compartilhou conhecimento sobre ARM, dicas e suporte à pesquisa. |
| AA | Inspiração para a vulnerabilidade e primeiro uso fora da Chimera. |