~/labs/workshops/gba-firered/03-ferramentas
Ferramentas e preparacaomGBA, Ghidra, Python, Capstone e GDB prontos para a aula.
Este capítulo deixa o ambiente pronto. Faça tudo antes da aula prática, porque download e instalação tomam tempo e atrapalham o ritmo do workshop.
São cinco peças:
mGBA roda o jogo e tem um debugger embutido.
Ghidra faz a análise estática do código da ROM.
Python roda os helpers do projeto (disassembler, busca na RAM).
Capstone a biblioteca que o disassembler usa.
GDB ARM conversa com o mGBA para análise dinâmica.
mGBA
O mGBA é o emulador. Ele também serve um servidor de debug que o GDB acessa, e é por isso que ele é a escolha do workshop.
No Ubuntu ou Debian:
sudo apt update
sudo apt install -y mgba-qt mgba-sdl
Se a sua distribuição não tiver o pacote, ou tiver uma versão antiga, baixe o AppImage oficial em https://mgba.io/downloads.html e rode assim:
chmod +x mGBA-*.AppImage
./mGBA-*.AppImage
Carregue a ROM com File, Load ROM, e aponte para rom/PokemonFireRed.gba. Deixe o
arquivo de save com o mesmo nome ao lado da ROM, como explica notes/save-prep.md,
para o jogo abrir com a opção Continue.
Ghidra
O Ghidra é a ferramenta de análise estática. Ele desmonta a ROM em instruções, acha funções, e mostra uma versão em pseudo C ao lado do Assembly.
Ele precisa de Java. Baixe o Ghidra no site oficial da NSA (https://ghidra-sre.org) ou pelo GitHub do projeto, descompacte e rode:
./ghidraRun
Na primeira vez, crie um projeto novo com File, New Project, e dê um nome como
firered-workshop. O capítulo 04 mostra a importação da ROM passo a passo.
Python e Capstone
Os helpers do projeto são scripts em Python 3. O principal depende da Capstone, que é a biblioteca de disassembly.
sudo apt install -y python3 python3-pip
pip3 install capstone
Confira se a Capstone instalou:
python3 -c "import capstone; print(capstone.__version__)"
Se aparecer um número de versão, está pronto.
O disassembler do projeto
O arquivo tools/disasm_gba.py desmonta qualquer endereço da ROM, em ARM ou Thumb.
Ele é a forma de conferir o Ghidra sem depender só dele. Foi com ele que todos os
exemplos do capítulo 02 foram gerados.
Uso:
# ARM, a partir de um endereço, com tamanho em bytes
python3 tools/disasm_gba.py 0x08000204 --size 0x34
# Thumb, basta acrescentar --thumb
python3 tools/disasm_gba.py 0x080003A4 --size 0x20 --thumb
Ele converte o endereço de memória para o offset no arquivo sozinho, usando a base 0x08000000 que o capítulo 01 explicou. Se você passar um endereço fora da ROM, ele avisa.
O buscador de RAM
O arquivo ram_find.py compara dois dumps da EWRAM e mostra quais endereços tinham um
valor antes e passaram a ter outro depois. É o que reduz a memória inteira a poucos
candidatos no capítulo 05. Ele lê dois arquivos:
ewram_hp24.bin dump da EWRAM com o HP em 24
ewram_hp21.bin dump da EWRAM com o HP em 21
E imprime os endereços onde o valor mudou de 24 para 21, testando três tamanhos: 8, 16 e 32 bits. O capítulo 05 usa isso na prática.
GDB para ARM
O GDB é o debugger que se conecta ao mGBA para parar o jogo, ler registradores e
colocar watchpoints. Você precisa de uma versão com suporte a ARM. Em muitas
distribuições o pacote é o gdb-multiarch:
sudo apt install -y gdb-multiarch
O projeto já vem com um arquivo de configuração pronto, gdbinit-gba. Ele ajusta o
GDB para ARM little endian e para o modo Thumb como padrão, que é o que o GBA mais
usa. Para ligar o GDB ao mGBA, primeiro ative o servidor de debug dentro do mGBA, no
menu Tools, Start GDB server, e depois rode:
gdb-multiarch -x gdbinit-gba
Dentro do GDB, conecte com:
target remote localhost:2345
Como confirmar que está tudo certo
Faça este teste rápido. Ele exercita as duas pontas, estática e dinâmica:
1. Rode:
python3 tools/disasm_gba.py 0x08000000 --size 0x10
Deve aparecer:
08000000: b #0x8000204
2. Abra a ROM no mGBA e veja o jogo rodar com o save.
3. Abra o Ghidra. Deixe a importação para o capítulo 04.
Se o passo 1 funciona, a ROM e o Python estão certos. Se o passo 2 funciona, o emulador e o save estão certos. Pode seguir.
O que levar deste capítulo
- mGBA roda o jogo e serve o debug na porta 2345.
- Ghidra faz a análise estática.
- tools/disasm_gba.py confere o disassembly por fora do Ghidra.
- ram_find.py compara dumps da EWRAM para achar um valor.
- gdb-multiarch com gdbinit-gba faz a análise dinâmica.