Análise de engenharia reversa de Ecco the Dolphin com Ghidra e Python
(32bits.substack.com)- Ecco the Dolphin: Defender of the Future para Dreamcast escondia cheats ativados pela entrada das iniciais no arquivo de save, e além do já conhecido
GYUGYU+XXX, vários outros inputs especiais foram identificados - A análise carregou um snapshot de memória do flycast no Ghidra para localizar o buffer de entrada e a função de processamento, rastreando a estrutura em que o resultado da transformação é comparado com 6 valores especiais
- A verificação do cheat não é feita pela própria string de entrada, mas por um valor obtido após descriptografar uma chave com uma passphrase e calcular um checksum, o que dificulta encontrá-lo apenas lendo as strings
- Um brute force em Python testou entradas de 1 a 8 caracteres e confirmou que
SOCCER,EXBBERX,QQRIQ,XYZZYXePOPELYestão ligados a fase bônus, modo imortal, exibição de FPS e exibição do tempo - A mesma função não fica presa a um único input:
NNSET,SOCCEReADEMVSSFabrem o jogo bônus de futebol, eAFTJSXOTtambém desbloqueia todas as fases, assim comoGYUGYU
Cheats ocultos ativados pelo nome do arquivo de save
- Ecco the Dolphin: Defender of the Future foi o último jogo de Ecco lançado oficialmente, e uma continuação acabou cancelada
- O cheat já conhecido consistia em escolher New Game na tela da VMU, digitar
GYUnas iniciais, depois inserirGYUde novo e mais três letras quaisquer sem apertar End- Ao inserir no formato
GYU GYU XXXe sair do menu, passa a ser possível selecionar todas as fases em Load game
- Ao inserir no formato
- Os inputs especiais confirmados e seus efeitos são os seguintes
GYUGYU+XXX: desbloqueia todos os níveisSOCCER+XXX: desbloqueia a fase bônusEXBBERX+XXX: modo imortalQQRIQ+XXX: exibição de FPSXYZZYX+XXX: exibição do tempoPOPELY+XXX: efeito desconhecido
Rastreando a rotina de processamento de entrada com Ghidra
- Em um snapshot de memória do emulador flycast, foi confirmado que parte das iniciais visíveis na tela era armazenada no buffer
8cfffb34 - À medida que a entrada continuava, os caracteres digitados antes eram empurrados para o buffer
8c3abf18, e essa área era usada na verificação dos cheats - Depois de carregar o snapshot no Ghidra, foi encontrada uma função no endereço
8c0334d8que lia esse buffer - Essa função transforma o buffer e verifica se o resultado corresponde a um dos 6 valores especiais da lista
GYU GYU XXXé convertido em9388D627, que bate com o primeiro valor especial da lista
Estrutura da transformação e do checksum
- O fluxo da função de transformação identificado no decompilado do Ghidra é o seguinte
- Lê uma passphrase
- Descriptografa uma chave de 1024 bytes com essa passphrase
- Usa a chave para calcular o checksum do buffer de entrada
- Criptografa a chave novamente
- Como o checksum é uma função unidirecional, é difícil inferir visualmente quais inputs geram os valores especiais
- Em uma atualização posterior, metalliczx e SideQuark confirmaram que, após a descriptografia, a estrutura seguia o polinômio padrão de checksum CRC32
- Por isso, existe uma forma mais eficiente de obter os valores desejados do que por brute force
Inputs encontrados com brute force em Python
GYUGYUtem 6 letras, e o número de combinações possíveis de 6 letras é26^6 = 308,915,776- Com 7 letras, isso sobe para 8 bilhões de combinações, e com 8 letras chega a 208 bilhões, uma escala pesada para um notebook
- A implementação em Python testa os inputs com o seguinte procedimento
- Copia um bloco de memória contendo o buffer de entrada não inicializado, a passphrase e a chave
- Descriptografa a chave com a passphrase
- Coloca sequências de 1 a 8 letras no buffer de entrada
- Calcula o checksum de cada input
- Compara o resultado calculado com o valor-alvo
- O código completo foi publicado neste gist
- Mesmo a versão single-thread já produziu os resultados necessários, que apareceram antes de a versão paralela ficar pronta
Mapeamentos encontrados e efeitos reais
- A última coluna da saída indica com qual valor especial cada resultado corresponde
NNSET,SOCCEReADEMVSSFcorrespondem todos ao mesmo valor e desbloqueiam o jogo bônus de futebolAFTJSXOTdesbloqueia todas as fases, assim comoGYUGYU
- Ao inserir
SOCCER+XXXcomo iniciais, o Bonus Game é liberado e é possível jogar futebol subaquático- Isso define o bit
0x2no flag de8c3ac00c
- Isso define o bit
EXBBERX+XXXfaz a tela de Options mostrar Immortality Enabled- Enquanto estiver ativo, não é possível se afogar nem morrer
- Isso define o bit
0x400do flag em8c3abe48e o bit0x4do flag em8c3abb00
QQRIQ+XXXexibe o framerate do jogo e alguns valores de depuraçãoXYZZYX+XXXmostra o valor atual do relógio- Os dois inputs alteram valores nos endereços
8c35659ce8c3565a4
- Os dois inputs alteram valores nos endereços
- O efeito de
POPELY+XXXnão foi confirmado- Supõe-se que ele tentasse ativar um flag em
8c3b0e44, mas esse flag aparentemente só mostra a mensagem Cheats Enabled sem produzir outro efeito visível
- Supõe-se que ele tentasse ativar um flag em
1 comentários
Opiniões do Hacker News
O hash é simplesmente CRC32; mais exatamente, usa este polinômio (0x77073096; o código está errado)
https://web.mit.edu/freebsd/head/sys/libkern/crc32.c
Os inteiros descriptografados no texto são constantes desse CRC32. Sabendo que é CRC32 e conhecendo o polinômio, dá para calcular a resposta de trás para frente em tempo logarítmico, não exponencial, usando matemática modular em anéis de polinômios
Dizem que o Binwalk reconhece tabelas de polinômios CRC; fico curioso se ele conseguiria encontrar esta tabela também
Alguém precisa integrar Binwalk e Ghidra. Eles combinam muito bem
Fico curioso se há dicas para descobrir que o valor é um resultado de CRC32, ou qual polinômio/valor inicial foi usado
Quando o Ecco original saiu para Megadrive (Genesis), gastei todo o dinheiro que eu tinha juntado com esforço para comprá-lo. Aquele jogo era absurdamente difícil e, de tanta raiva, passei a tarde inteira sentado com papel e caneta até de algum jeito decifrar o sistema de senhas
Teleportei para a fase final e terminei no dia seguinte, mas fiquei me sentindo culpado por ter gastado todo o meu patrimônio em um jogo que concluí em dois dias
Você decifrou o sistema de senhas com papel e caneta? Se lembrar de algo, eu adoraria ouvir mais
Filosoficamente, eu diria que você não terminou esse jogo
Você pulou várias fases e viu só parte do conteúdo, da jogabilidade e da história pretendidos. Jogos, incluindo Ecco the Dolphin, em geral têm mais a ver com a jornada do que com o destino. Você perdeu temas e experiências como isolamento, fazer amizade com grupos externos, preservação, viagem no tempo, comunhão com dinossauros e, claro, viagem espacial
Então você não precisava se sentir tão culpado assim
Ainda assim, a fase final era incrível. Fico curioso se você ficou surpreso ao vê-la depois de pular uma parte tão grande do jogo
Usando cheats ou não, talvez você seja a única pessoa no mundo que zerou esse jogo
QQRIQ é uma abreviação fonética de “kukuriku” e significa o canto do galo em húngaro e em várias línguas. Há exemplos como o polonês “kukuryku” e o hebraico “קוקוריקו”
Isso me deixa curioso sobre como foi o processo de escolher as senhas
Gyugyu também pode ser uma referência ao filme húngaro “The Fifth Seal”
“Imagine que você está prestes a morrer e reencarnará como uma de duas pessoas: um escravo ou um senhor rico. O escravo sofre nas mãos do senhor, perde a língua e um olho, e sua esposa e seus filhos também são assassinados. Ele continua vivendo acreditando ser uma boa pessoa, porque nunca fez a outros nada tão horrível e sádico quanto o senhor. O senhor rico não tem nenhum escrúpulo moral. Não acha que o que fez foi errado e acredita que o escravo merecia ser punido. Você precisa escolher entre ser um escravo pobre, mas justo, ou um senhor rico, mas corrompido.”
Gyugyu é o nome desse escravo
https://www.imdb.com/title/tt0075467
Como os programadores desse jogo estavam em Budapest, é uma hipótese bem plausível
Popely, com o “ly” do húngaro, também era uma pista
Em francês é Cocorico, então é muito parecido
Também lembra a vila Kakariko de Zelda, onde sempre aparecem galinhas
Como curiosidade interessante, o desenvolvedor de Ecco, Ed Annunziata, quando perguntado sobre suas inspirações, respondeu: “Nunca usei LSD, mas li muito John C. Lilly”. Lilly é conhecido por trabalhos pioneiros em inteligência animal, psicoterapia com cetamina, tanques de privação sensorial e exploração da consciência
O nome “Ecco” é uma referência ao ECCO (Earth Coincidence Control Office) de Lilly. John postulava a existência de uma base sobrenatural/alienígena no lado oculto da Lua para coordenar todas as “coincidências” na Terra. Ele foi uma das primeiras pessoas a perceber o quanto os golfinhos eram inteligentes e ficou obcecado em descobrir como se comunicar com eles, a ponto de inundar metade de sua casa no Caribe para viver junto com eles. Isso é só a ponta do iceberg; se você achar interessante, recomendo muito a autobiografia dele, The Center of the Cyclone. É uma figura realmente fascinante
Fico curioso se há algum material para começar a fazer engenharia reversa de jogos de Dreamcast. Há coisas que eu queria tentar com Skies of Arcadia, mas seria bom ter técnicas mais sistemáticas do que “ver quais valores mudam entre snapshots de memória”
Para encontrar a localização de valores na RAM, esse método é praticamente a técnica padrão. Na prática, funciona muito bem
Alguns emuladores, como o Dolphin, têm ferramentas desse tipo embutidas. Ferramentas antigas de hack de jogos, como o Gameshark para N64, também usavam a mesma técnica com uma UI no console. Não sei se emuladores de Dreamcast têm uma ferramenta assim
Escrevi um post usando essa técnica no Dolphin, e o post seguinte também é sobre hack de jogos de console usando Ghidra: https://www.smokingonabike.com/2021/01/17/hacking-super-monk...
Já dei uma olhada nesse jogo. O ponto principal é fazer dump dos snapshots de memória para um arquivo e depois importá-los no Ghidra. Há várias formas de fazer o dump, e muita gente gosta do Cheat Engine
O Ghidra consegue analisar nativamente o código de máquina do processador SuperH, então só rodar a análise automática já revela muitas funções
Nos últimos anos, passei a me sentir muito mais atraído por jogos antigos e, não sei se a expressão faz sentido, eles parecem ter muito mais alma
E sinto muito pelo incidente com o carro. Obrigado pelo aviso; de agora em diante não vou deixá-lo ligado em marcha lenta na entrada da garagem
Sempre me perguntei por onde começar a aprender engenharia reversa. A maioria diz para aprender assembly primeiro, mas depois disso parece não haver muita informação concreta online
Não sei se é uma questão de ir aprendendo devagar, por tentativa e erro, os padrões comuns de x86, arm e plataformas de arcade. É difícil encontrar discussões online que entrem nos detalhes
Ferramentas como o Ghidra permitem ir ajustando o código-fonte aos poucos, mas, no fim, é preciso inferir as coisas do mesmo jeito que se faria ao tentar entender uma base de código desconhecida. A diferença, desta vez, é que não há nenhum comentário, embora também haja muitos projetos de código aberto sem comentários
Para exemplos mais próximos da realidade, vale resolver desafios em http://microcorruption.com ou https://crackmes.one/
Pessoalmente, aprendi muito mexendo no Cheat Engine. Eu o usava principalmente quando era mais novo e nunca tinha voltado a olhar para ele, então não sabia, mas é uma ferramenta muito mais poderosa do que eu imaginava
O disassembler é bastante decente, e dá para escrever o que eles chamam de “assembly scripts”, o que é bom para aprender o básico de patches de memória em assembly x86. A partir daí, você pode começar a criar seus próprios utilitários para aplicar patches em jogos do jeito que quiser
Só com o Cheat Engine já dá para aplicar patches em jogos e criar cheats absurdamente fortes
Aprendi um pouco disso na escola, mas executar passo a passo, em um debugger, os videogames de que eu me lembrava da infância me ensinou ciência da computação muito melhor do que as aulas
Quero ver um vídeo do cheat de futebol subaquático funcionando de verdade
É interessante como jogos parecidos usam inteiros fixos para bater checksums. Pitfall: The Lost Expedition também usava uma abordagem muito semelhante: convertia as entradas de botões em uma string ASCII dos botões pressionados e depois calculava o CRC
A abordagem também era quase força bruta em Python, comparando com os hashes de cheat extraídos. Também dá para ver uma tabela CRC32 escondida dentro de
decrypted_ints. Tabelas pré-geradas são fáceis demais de pesquisar. Em vez de gerar uma nova tabela com um polinômio próprio, fico curioso por que elas aparecem com tanta frequência ofuscadas, aparentemente para dificultarUm blog focado no Sega Saturn? Que surpresa
Há pouco tempo encontrei um Saturn e um pequeno pacote de CDs de jogos no armário da casa dos meus pais. Não me lembro de ter tido um, então suponho que meu irmão o tenha conseguido depois que fui para a universidade. De qualquer forma, liguei tudo e todos os jogos funcionaram bem. Mas, fora isso, não faço a menor ideia do que fazer com ele. Jogar fora, obviamente, não é uma opção
Os jogos valem uma fortuna. Em 2005, dei o meu de graça, e agora, quando procuro os preços no eBay, meu coração dispara
É só se divertir com ele
https://terraonion.com/en/producto/terraonion-mode/