← cd ../

~/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.