
Exploit PSP para GPUs AMD navi31 (RX 7900) que desativa as verificações de assinatura de firmware, permitindo que a placa carregue firmware SMU, SDMA, MEC, IMU e RLC não assinado; não persistente após reinicialização a frio.
Um exploit de PSP (Platform Security Processor) para placas AMD navi31 (série RX 7900). Provavelmente adaptável a outras famílias de produtos adjacentes também.
Ele desativa a verificação de assinatura de firmware do PSP, para que a placa carregue firmware de IP não assinado (SMU, SDMA, MEC, IMU, RLC) que de outra forma recusaria. Pense em gerenciamento de energia personalizado, limites de clock ou qualquer outra coisa que resida no firmware que o fabricante assina e você não.
Nada é gravado na flash. O patch vive na memória do PSP e é aplicado durante um warm boot; um ciclo de energia a frio o apaga e a placa volta ao estado de fábrica. Esse warm boot é o "Wake and Break": a placa acorda, nós a convencemos a ficar muito alta imediatamente e a coagimos a neutralizar as verificações de assinatura. :-)
Testado em uma RX 7900 XTX. Veja Status.
python3 wakebreak.py 25=/path/to/firmware.bin
Isso grava o patch, faz o warm-boot da placa e envia sua imagem como firmware
tipo 25. Se imprimir accepted, o PSP aceitou uma imagem que normalmente teria
rejeitado.
Precisa de algo para testar? ipfw_images.py lista o firmware que seu driver
realmente carrega e grava um par de teste — uma imagem genuína e uma cópia com um bit
invertido na assinatura, de modo que o firmware em si é idêntico byte a byte:
python3 ipfw_images.py # what does this card load?
python3 ipfw_images.py 25 # -> /tmp/fw_25_{ok,bad}.bin
python3 wakebreak.py 25=/tmp/fw_25_bad.bin
O firmware de fábrica rejeita fw_25_bad.bin. Com o patch aplicado, ele é aceito.
Essa é toda a demonstração.
python3 -m venv venv
venv/bin/pip install -r requirements.txt
make verify # are the shipped artifacts intact?
make selftest # offline sanity checks, no card touched
Você precisa de um host Linux com a placa acessível através do
driver AMD do tinygrad (PCIe ou sua ponte
USB). Consulte requirements.txt para um patch do tinygrad que seu host necessita.
Existem quatro builds de firmware navi31 conhecidos, e o patch precisa corresponder.
O perfil a é o padrão e cobre o mais comum. Se você tiver um dump
da flash SPI da sua placa, o identify.py informará:
python3 identify.py FLASH.bin
# -> sos-build c: wakebreak.py --sos-build c
Caso contrário, basta experimentá-los. Adivinhar errado é inofensivo: o patch verifica o que está prestes a modificar, encontra algo que não reconhece, não escreve nada, e a placa inicializa normalmente.
python3 wakebreak.py --sos-build c 25=/tmp/fw_25_bad.bin
Confirmado na placa testada (RX 7900 XTX, perfil a):
| firmware adulterado, placa original | rejeitado |
| firmware adulterado, com patch | aceito |
| após ciclo de energia a frio | rejeitado novamente — a placa está original |
NOTA: Os perfis b, c e d são compilados e verificados offline, mas nunca foram executados em hardware. Se você tiver uma placa que corresponda ao perfil b, c ou d, por favor, informe se funciona!
O patch em si consiste em algumas centenas de bytes de assembly ARM, em hook/*.S. Os blobs compilados acompanham o repositório, então você não precisa de um cross compiler para usar isto. Se você quiser recompilá-los de qualquer forma:
make rebuild # needs arm-none-eabi binutils
make rebuild CROSS=/path/to/arm-none-eabi-
A build se recusa a instalar qualquer coisa cujo hash não corresponda aos bytes que foram testados em um cartão, então uma toolchain diferente não pode alterar silenciosamente o que é gravado no seu PSP.
wakebreak.py the exploit
identify.py which --sos-build does this card need?
ipfw_images.py build a signed/tampered firmware pair to test with
selftest.py offline checks
hook/ the patch: ARM sources and built blobs
firmware/ two stock AMD firmware images the exploit needs to get in
firmware/ contém imagens AMD não modificadas, distribuídas publicamente. São versões antigas, mantidas porque o caminho de entrada passa por elas.
Não abordado aqui de propósito: leia o código. wakebreak.py tem cerca de 600 linhas comentadas e os comentários explicam o mecanismo, as verificações de segurança e por que cada etapa está ordenada da forma que está. TL;DR: duas trusted applications padrão da AMD são carregadas, uma delas é convencida a executar uma cadeia que pode escrever na memória do PSP, o patch é colocado na cópia residente do bootloader, e então a placa é reiniciada (warm boot) nele.
MIT, veja LICENSE. Faça o que quiser com isso.
Foi usado auxílio pesado de LLM na produção deste trabalho. Isso não significa que o autor não tenha ideia do que realmente está acontecendo aqui. muito esforço de contestação e trabalho manual foi envolvido só para chegar a este ponto. Você pode não gostar dos artefatos de python mal feitos ou o que for, mas não poderá discutir o fato de que sua placa Navi31 agora, de repente, carrega blobs de componentes de firmware não assinados. Obrigado pela atenção.