Hackers descobrem como reprogramar NES Tetris dentro do próprio jogo
(arstechnica.com)- A falha da kill screen de NES Tetris não é apenas um fim de jogo: ela pode ser usada como ponto de entrada para executar novos comportamentos em hardware e cartucho não modificados
- Depois do nível 155, se o cálculo da pontuação não terminar entre um quadro e outro, o fluxo de controle se quebra e o jogo pode acabar em execução arbitrária de código, lendo posições inesperadas da RAM como se fossem instruções
- A RAM de entrada da porta de controle de expansão do Famicom se sobrepõe à posição da rotina de salto, permitindo manipular o endereço para onde o jogo vai após a falha por meio dos botões dos controles 3 e 4
- A Displaced Gamers publicou um código de prova de conceito que envia o destino do salto para a tabela de recordes, fazendo o jogo ler dados de nomes e pontuações como opcodes da CPU do NES
- A utilidade prática é limitada pelos caracteres e números que podem ser inseridos e pela falta de armazenamento, mas há possibilidade de expansão para patches que evitem a falha ou para controle total da RAM
Como a falha da kill screen vira execução de código
- A falha em NES Tetris pode ocorrer quando o processador de pontuação demora demais para calcular a nova pontuação entre um quadro e outro
- Essa situação pode aparecer depois do nível 155
- Quando há atraso, parte do código de controle é interrompida pela rotina de escrita de um novo quadro
- Depois disso, o jogo salta para uma posição inesperada da RAM em busca da próxima instrução
- Em geral, esse salto inesperado faz o jogo ler dados lixo no início da RAM como se fossem código, levando a uma falha rápida
- Um vídeo recente da Displaced Gamers revelou um procedimento para fazer NES Tetris ler a tabela de recordes como instruções de máquina
- Glitches semelhantes de execução arbitrária de código já eram conhecidos em Super Mario World, Paper Mario e The Legend of Zelda: Ocarina of Time
- O método básico para inserir código externo em NES Tetris já era teorizado publicamente desde pelo menos 2021, e diz-se que métodos de controle total da RAM já eram conhecidos havia muito tempo dentro da comunidade
Controle da posição do salto via processamento de entradas do Famicom
- Esse hack depende não só da forma como Tetris falha, mas também da estrutura de entrada do Famicom
- Diferente do NES americano, o Famicom japonês tinha dois controles conectados de forma fixa ao console, e controles de terceiros podiam ser conectados à porta de expansão frontal
- O código de Tetris lê as entradas dessa porta de controles “extra”
- Com um adaptador, é possível conectar mais dois controles padrão de NES
- O Famicom tinha uma versão separada de Tetris da Bullet-Proof Software, mas essa característica de processamento de entradas funciona no código de NES Tetris
- A área de RAM que processa as entradas dos controles adicionais se sobrepõe à posição de memória da rotina de salto usada durante a falha
- Quando a rotina de salto é interrompida pela falha, essa RAM contém dados que representam os botões pressionados nos controles
- O jogador pode usar esses valores para controlar com precisão para onde o código do jogo vai após a falha
Lendo a tabela de recordes como código executável
- O método de controle de salto da Displaced Gamers exige entradas específicas nos controles
- Pressionar
upno controle 3 - Pressionar
right,leftedownno controle 4 - Para inserir
lefterightao mesmo tempo, é necessário modificar o controle
- Pressionar
- Essa entrada envia o código de salto para a área da RAM onde ficam armazenados os nomes e pontuações da lista de recordes do jogo
- Ao colocar
(Gna posição-alvo da tabela de recordes do B-Type, o jogo salta novamente para outra área da tabela de recordes - Depois disso, o jogo lê nomes e pontuações em sequência e os processa como opcodes da CPU do NES, em um estilo que a Displaced Gamers chamou de código “bare metal”
Possibilidades e limites demonstrados pela prova de conceito
- A área de entrada de nomes dos recordes permite usar apenas 43 símbolos, e as pontuações só podem conter 10 algarismos
- Por causa dessa restrição, só é possível “programar” na tabela de recordes uma parte dos opcodes disponíveis no NES
- Mesmo com entradas limitadas, foi possível criar um código de prova de conceito curto
- Os dados de exemplo incluem o nome
))"-P)e a pontuação de 8.575 na 2ª posição do A-Type - Essa rotina zera os dois algarismos mais altos da pontuação do jogo
- Isso reduz o tempo de processamento da pontuação e diminui a causa da falha, mas, se o jogador continuar jogando, a pontuação volta a atingir a “zona de risco” de falha
- Os dados de exemplo incluem o nome
- O NES Tetris original não tem armazenamento com backup por bateria, então é necessário recriar manualmente os recordes e nomes complexos exigidos a cada vez que o console é ligado
- O espaço da tabela de recordes também é limitado, o que dificulta inserir programas complexos diretamente sobre o código real de Tetris
- HydrantDude escreveu que existe uma forma de criar um bootstrapper com combinações específicas de nomes e números na tabela de recordes e, em seguida, criar outro bootstrapper para obter controle total da RAM
Possibilidade de reprogramação para além de evitar a falha
- Se o controle total da RAM se tornar possível, jogadores de alto nível também poderiam recodificar o jogo para aplicar um patch no bug de falha de NES Tetris
- Esse método pode ser especialmente útil para jogadores que tentam passar do nível 255
- Depois do nível 255, o jogo volta para o Level 0
- Expandindo o mesmo princípio, também seriam possíveis transformações como mudar Tetris para Flappy Bird, em um caso semelhante ao dos speedrunners de Super Mario World
1 comentários
Comentários do Hacker News
Exploits como esse sempre me lembram o estágio final definitivo de hacking em Accelerando, de Stross: “fazer um ataque de canal de temporização contra a superestrutura computacional do próprio espaço-tempo, tentando invadir algo por baixo dela”
Parece uma ótima maneira de provocar um decaimento do vácuo e fazer o universo dar tela azul
Gosto muito de pessoas assim
Chega a me dar vergonha eu não ter essa mentalidade hacker de tentar coisas que provavelmente são inúteis só pela diversão
O resto de nós está ocupado demais tentando sobreviver para ter tempo de fazer exploits assim, sem trocadilho intencional
Se você não quer ler o texto inteiro, mas está se perguntando “achei que cartuchos de NES rodassem a partir de ROM?”, é isso mesmo
Só que esse exploit faz a CPU saltar para a RAM usada para armazenar a tabela de recordes. Muito bacana
O processo de chegar à execução arbitrária de código é sempre mais interessante do que o que se faz depois
A obstinação de desmontar o jogo para descobrir quando e onde ele faz esse comportamento, e encontrar que parte precisa ser manipulada para inserir instruções, é admirável
Pokemon Yellow: https://www.youtube.com/watch?v=Vjm8P8utT5g
Super Mario World: https://www.youtube.com/watch?v=hB6eY73sLV0
A execução arbitrária de código é acionada por shellcode de verdade. Literalmente executada manipulando um casco de Koopa dentro do jogo
Quanto tempo até alguém rodar Doom dentro de Tetris?
Tempo bem desperdiçado
Pergunto de verdade. Eu costumava considerar até coisas divertidas como perda de tempo, mas, depois de pagar o preço de viver sob estresse alto por muito tempo, fui mudando de ideia com a idade
Quero tentar fazer isso com Factorio
Criar um computador gigante feito de esteiras dentro de Factorio e provocar uma falha de segmentação para escapar para fora do jogo
Encontrar execução arbitrária de código em jogos antigos é realmente fascinante
Quando vi algo assim em Super Mario World alguns anos atrás, fiquei obcecado por um tempo em entender como aquilo era possível
Digo isso no bom sentido, como elogio, embora possa soar meio maldoso: adoro ver pessoas realmente inteligentes gastando tempo e esforço enormes em algo completamente inútil
Existe algum motivo imediato para injetar código no NES Tetris? Provavelmente não. Mas o ponto não é esse; é descobrir o que é possível e até onde dá para forçar código antigo e computadores primitivos a fazerem coisas
Talvez não seja “útil” no sentido clássico, mas o mesmo vale para Sudoku, palavras cruzadas ou até jogar NES Tetris em primeiro lugar
Ele permite que jogadores de alto nível evitem um travamento que impede a partida depois de certo ponto e joguem por mais tempo
Para o jogador médio, não há utilidade prática, mas, para quem quer competir por recordes, ele remove um limite e abre novas possibilidades de competição
Teoria dos números também era considerada inútil, mas hoje sustenta praticamente toda a criptografia de chave pública
A utilidade que os outros obtêm de coisas que eu faço sem gostar é um subproduto feliz, ou algo que me beneficia indiretamente, como dinheiro ou reconhecimento
Fazer algo por gostar é a forma mais direta de utilidade para a pessoa mais importante: você mesmo
Sinceramente, é surpreendente que Tetris tenha sido quebrado tão tarde
Acho que isso vai abrir uma nova era de runs any%. O objetivo é acionar a cena final ou os créditos do jogo o mais rápido possível
Meu exemplo favorito é Ocarina of Time, que já tinha exploits de ACE havia alguns anos
O jogo é tão quebrado que, manipulando a memória do jogo e editando um warp de entrada específico, dá para “zerar” em poucos minutos
O mais surpreendente é que as pessoas editam memória manualmente, usando só alguns botões e um joystick analógico
Um caso em que os créditos aparecem em 3 minutos: https://www.speedrun.com/oot/runs/z1l1627m
Ao encontrar uma falha no túnel de warp, isso acionava uma leitura fora dos limites, e antes disso a pessoa usava manipulações do joystick para escrever, logo fora do buffer, os bytes que causariam o comportamento desejado
Em um dos jogos de Pokemon, era preciso fazer um monte de transações de compra/venda para preparar a memória com precisão e então causar overflow na quantidade de itens para acionar o salto
É algo realmente fantástico. Um dia, se alienígenas atacarem, essas brincadeiras vão nos salvar
Este ACE parece depender primeiro de chegar à kill screen
Imagine se o ACE de Ocarina of Time só fosse acionado depois dos créditos finais; como ele só aconteceria depois de uma conclusão bem-sucedida, não daria para reduzir o tempo
Gosto muito desse tipo de trabalho
Isso me lembra quando programaram Flappy Bird dentro de Super Mario World usando uma falha. É insano
https://www.youtube.com/watch?v=hB6eY73sLV0