Todos os posts
Inteligência Artificial

Engenharia reversa com IA: construí um meter de MMORPG

Comecei o WS-engine sem nenhuma experiência prévia em engenharia reversa com IA . Em quatro meses saí do zero a um meter de dano funcional para um MMORPG, com decoder próprio de protocolo binário, janela de interface em Windows e sincronização comunitária opcional. O par de programação em todas as e

19 min de leitura 39 views
Engenharia reversa com IA: construí um meter de MMORPG

Comecei o WS-engine sem nenhuma experiência prévia em engenharia reversa com IA. Em quatro meses saí do zero a um meter de dano funcional para um MMORPG, com decoder próprio de protocolo binário, janela de interface em Windows e sincronização comunitária opcional. O par de programação em todas as etapas foi o Claude Code, operado pelo terminal, lendo e escrevendo código junto comigo. Este artigo é o case técnico desse processo, sem publicar números de pacote, nomes de tag ou offsets do protocolo analisado.

Por que construí um meter de MMORPG sozinho

Antes do WS-engine existir, pensei em desistir várias vezes porque engenharia reversa com IA não era um atalho mágico — era disciplina séria com um ajudante paciente. Jogo um MMORPG com comunidade pequena há anos e sempre quis ver meu dano em tempo real estilo Details do WoW. Nunca existiu ferramenta oficial pra esse jogo e os projetos amadores que apareceram ao longo dos anos morriam porque o autor cansava ou o protocolo mudava e ninguém atualizava. Topei fazer, mesmo sem background em pacotes de rede, porque percebi que a IA tinha chegado num ponto que me permitia estudar e produzir em paralelo.

Projeto é pessoal e não comercial, feito por diversão e aprendizado. Não tem equipe, roadmap de produto, nem monetização. Isso importa porque muita conversa pública sobre engenharia reversa com IA assume um contexto empresarial com equipe especialista; o que faço aqui é o oposto — uma pessoa só, programando à noite, usando IA como professor que também digita o código junto. O tom do artigo vem dessa realidade.

Antes de começar, pesquisei projetos semelhantes feitos para outros jogos. Encontrei repositórios de ferramentas comunitárias para Aion 2, Blue Protocol, Tera e Lost Ark — todos usam a mesma técnica geral de ler o tráfego de rede sem modificar o cliente. Isso me deu a confiança de que o caminho existia e já tinha sido trilhado por outras pessoas. Faltava eu descobrir como fazer dentro do meu stack preferido (C# e .NET).

Legalidade: Lei 9.609/98, DMCA 1201(f) e Sega v. Accolade

Antes de qualquer código, estudei o terreno legal. Entrar em engenharia reversa com IA sem olhar isso primeiro é um erro que custa caro depois. A Lei 9.609/98, que no Brasil regula a proteção da propriedade intelectual de programa de computador, não traz uma regra explícita autorizando engenharia reversa. O artigo 6º, inciso IV, é o dispositivo mais próximo: ele permite a integração de um programa a um sistema aplicativo ou operacional quando essa integração for tecnicamente indispensável às necessidades do usuário, e desde que para o uso exclusivo de quem a promoveu. Não equivale ao DMCA — é uma permissão estreita, pensada mais para compatibilidade do que para análise.

Essa estreiteza da lei brasileira é algo que todo mundo que quer fazer engenharia reversa com IA no Brasil precisa entender antes de começar. Nos EUA, 17 U.S.C. §1201(f) prevê uma exceção específica para engenharia reversa, mas sob condições: só se destina a identificar e analisar elementos de um programa necessários para alcançar interoperabilidade com outro programa, quando esses elementos não foram previamente disponibilizados e desde que a interoperabilidade seja o objetivo. O caso Sega Enterprises Ltd. v. Accolade (977 F.2d 1510, 9th Cir. 1992) reconheceu, sob condições parecidas, que a cópia intermediária feita durante engenharia reversa pode se qualificar como fair use quando feita para fins de interoperabilidade e quando não há outro meio de obter os elementos funcionais protegidos. Nenhum dos dois dispositivos é um salvo-conduto geral.

Além da lei, existem os termos de uso do próprio jogo. O MMORPG analisado neste projeto é publicado pela Aigrind LLC — este trabalho não é afiliado, patrocinado ou endossado pela Aigrind. Termos de uso de jogos online frequentemente proíbem contratualmente modificação do cliente, interferência no serviço e análise do software, e um contrato pode restringir contratualmente o que a lei permitiria em tese. Nada neste artigo é aconselhamento jurídico — se você for repetir qualquer passo em outro contexto, consulte um advogado especializado em direito digital na sua jurisdição.

Arquitetura: do pacote TCP à janela de interface

A arquitetura inteira do projeto se divide em quatro etapas, cada uma com responsabilidade estreita. Essa separação em etapas pequenas foi o que tornou tratável fazer engenharia reversa com IA sem ficar perdido no caminho — cada etapa tem entrada e saída definidas e dá pra testar em isolamento. A primeira é a captura passiva da rede: um processo externo do Wireshark grava o tráfego numa pasta local e um loop no C# relê esse arquivo enquanto ele é escrito, usando compartilhamento de leitura. Nenhuma modificação do cliente do jogo acontece aqui — só leitura do que já passa pela placa de rede.

A segunda etapa é o parser do protocolo binário. Ele lê os bytes capturados, reconhece os envelopes, descomprime o que estiver comprimido e emite eventos estruturados: alguém causou dano em alguém, alguém curou alguém, uma invocação apareceu, um jogador entrou na área. Em paralelo, um processo auxiliar lê dados do cliente do jogo para enriquecer esses eventos com informações que não vêm pelo cabo, como classes de personagens — mantenho os detalhes dessa parte abstratos de propósito, para não dar roteiro operacional.

A terceira etapa é o modelo de combate. Em memória, agrego os eventos: dano total por jogador, dano por segundo, dano recebido, cura efetiva descontando overheal, atribuição de dano de invocação ao dono. É aqui que ficam as regras de domínio do meter — classificar entidades, decidir quando uma luta começou e terminou, lidar com casos limítrofes como uma invocação que apareceu antes da captura começar.

A quarta etapa é a interface. Rodo um WinForms simples que hospeda um controle WebView2, e o painel visual é HTML, CSS e JavaScript. É uma janela separada do jogo, aberta no desktop como qualquer outro aplicativo — não é overlay por cima do cliente. A separação me permitiu iterar o visual sem recompilar o executável e reaproveitar conhecimento web pra fazer transições e animações que seriam tedioso em WPF puro.

Dois arquivos de banco local completam o quadro: um SQLite para persistir histórico de capturas e um conjunto de JSONs para caches de nomes, classes e guildas vistas. Essa separação impede que a performance do painel seja afetada por queries ao SQLite durante combates intensos — leituras do cache são imediatas, escritas são batches assíncronas.

Captura via dumpcap e Npcap

Qualquer fluxo de engenharia reversa com IA voltado a protocolos de rede começa pela captura confiável do tráfego. A captura de pacotes é feita pelo dumpcap.exe, que vem junto com o Wireshark, e pelo driver Npcap que acompanha a instalação. O usuário do WS-engine precisa instalar o Wireshark como dependência; o executável do projeto detecta o caminho do dumpcap no primeiro boot e salva em um JSON de configuração ao lado do próprio executável. Depois disso, cada ciclo de captura é só spawnar o dumpcap como processo filho com o filtro BPF correto e deixá-lo escrevendo pcapng na pasta de capturas.

O parser em C# abre o mesmo arquivo em modo de compartilhamento de leitura e consome os pacotes conforme vão sendo gravados. Essa combinação de produtor externo mais consumidor em processo próprio funciona bem porque o dumpcap é maduro, estável e trata detalhes de baixo nível que eu não precisei reimplementar — timestamps, truncamento, rotação. Não injeto código no cliente do jogo, não modifico pacote em trânsito, não falo com o servidor; apenas leio o que já passa.

Decidir qual interface de rede escutar foi uma dor própria. O programa enumera adaptadores via o próprio dumpcap, escolhe o que tem internet ativa e salva no JSON de configuração. Em máquinas com VPN ligada ou múltiplas placas, essa heurística às vezes escolhe errado — a solução documentada é apagar o JSON e deixar o programa redetectar na próxima abertura. Esse tipo de detalhe operacional só aparece em produção com usuários reais, não dentro da minha máquina de teste.

Mapeando um protocolo binário desconhecido com ajuda de IA

Foi na etapa de entender o protocolo que automatizar engenharia reversa com IA mostrou mais valor concreto. O protocolo do jogo não é público nem documentado. Minha única matéria-prima eram capturas pcapng gravadas durante sessões reais. O trabalho se transformou em um loop iterativo: gravar uma sessão com situações conhecidas (eu dei dano X no mob Y), hipotetizar como esse evento está codificado nos bytes, escrever um pedaço de código que extrai aquilo da captura, rodar contra uma segunda captura diferente para ver se a hipótese se sustenta.

O Claude Code entrou aqui como par de programação, que é no fundo o coração prático de qualquer engenharia reversa com IA bem-feita. Sentava com ele no terminal, abria uma captura, dizia "nessa sessão eu dei 751.386 de dano em cinco jogadores, cadê esse número no arquivo?". Ele propunha varreduras, escrevia scripts de análise, lia o output comigo e refinava hipóteses. Em algumas rodadas, acertou de primeira — identificou um envelope comprimido observando repetição de prefixos. Em outras, errou feio e eu precisei refazer o raciocínio.

Dois conceitos acabaram sendo centrais. O primeiro é TLV (Tag-Length-Value): cada mensagem traz um identificador do tipo, um tamanho do payload e os dados. O segundo é varint, codificação de inteiros em comprimento variável onde cada byte carrega sete bits de dado mais um bit indicando "ainda tem mais". Juntos, formam um framing comum em protocolos de jogos — compacto e barato de parsear. Reconhecer esse padrão foi o salto que destravou o resto do trabalho.

Alguns envelopes carregam payload comprimido. Depois de identificar o padrão, implementei a descompressão e passei a enxergar o conteúdo real desses pacotes — eventos de combate em lote, broadcasts de área, atualizações de estado. Compressão aqui é LZ4, otimizada para velocidade; para arquivos de assets do próprio cliente (não trafegados pela rede durante jogo), o jogo usa Brotli. São dois universos separados que às vezes confundem quem está começando.

Decidi omitir deste artigo qualquer número de tag específico, layout de struct ou offset. Primeiro porque esses detalhes mudam a cada patch — já vi um valor estável por meses migrar de um dia pro outro. Segundo porque engenharia reversa com IA responsável é pelo processo, não pelo mapa. Quem quer entender a técnica aprende aqui; quem quer um mapa pronto do protocolo pra outros fins não vai encontrar.

Decoders em C#: do byte à estrutura

É nessa etapa de decoder que engenharia reversa com IA sai do campo da pesquisa e vira software mantível. Escrever decoders em C# é a parte onde se gasta mais tempo depois que você já entendeu o framing. Para cada tipo de evento identificado, há uma classe decoder dedicada que recebe o buffer de bytes, lê os campos na ordem conhecida, trata os varints, descomprime o que precisa descomprimir, e emite um objeto tipado que o resto do programa consome. Essa separação em decoders por tipo foi uma das primeiras decisões arquiteturais e me pagou dividendos todas as vezes que precisei trocar a interpretação de um campo.

Trabalhar com varint em C# obriga alguns cuidados. O leitor precisa saber parar quando o bit de continuação cai, suportar valores que extrapolam int32 e preservar a posição no buffer para o próximo campo. Escrevi um helper único de leitura varint que todos os decoders usam, com testes unitários cobrindo os casos limítrofes — zero, valor pequeno, valor grande, bytes malformados. Esse helper único é a cola que mantém o conjunto previsível.

Descompressão LZ4 é feita via uma dependência estabelecida da comunidade .NET; não reinventei a roda. Para alguns envelopes, a descompressão é condicional baseada em um flag — o decoder pai precisa olhar esse flag antes de decidir se instancia um decompressor ou passa o buffer direto. Esse tipo de regra sutil é o que mais quebra em patch: às vezes o jogo adiciona um byte novo antes do payload comprimido e seu parser passa a ler lixo. A defesa é teste de regressão com capturas antigas rodando contra o parser atual.

Brotli entra num caminho totalmente separado. O cliente do jogo distribui boa parte dos assets dentro de um arquivo com extensão própria do publisher, cujo conteúdo é comprimido com Brotli. Eu uso essa descompressão apenas para ler dados estáticos do jogo offline — nunca durante uma sessão ativa — e os dados extraídos entram no pipeline como complemento para enriquecer o decoder de rede com informação que não vem no cabo (como mapeamento entre identificador numérico de item e nome legível).

Essa suíte de regressão é a disciplina que separa engenharia reversa com IA sustentável de projeto que morre após o primeiro patch. Testar decoder sem jogo rodando é obrigatório. Mantenho um conjunto de capturas pcapng de referência salvas no repositório, com asserts automatizados que comparam totais de dano, cura, dano recebido e participantes contra ground truth coletado manualmente das sessões em que as capturas foram gravadas. Qualquer mudança no decoder passa por essa suíte antes de merge. É esse teste que me permite dormir tranquilo depois de refatorar um decoder — se o número bate, o comportamento está preservado.

WinForms + WebView2: por que uma janela separada venceu WPF

UI é a última parte de qualquer projeto de engenharia reversa com IA desse tipo — sem ela, o decoder é só um arquivo de log. A escolha de janela separada em vez de overlay sobre o cliente foi deliberada. Overlay exige hooks de janela ou DirectX, aumenta a chance de o antivírus flagar como aplicação invasiva, e me prenderia num paradigma gráfico que eu não domino. Janela separada WinForms é opcional pro usuário manter visível em segundo monitor, deslocada para o lado, redimensionada à vontade. Perde o apelo imersivo, ganha simplicidade e portabilidade.

Dentro do WinForms, o controle WebView2 da Microsoft hospeda um Chromium que renderiza HTML, CSS e JavaScript locais, servidos como arquivos do próprio executável. A ponte entre o C# e o JavaScript do painel é feita por mensagens via PostWebMessageAsJson e um listener no lado JS. O backend em C# empurra snapshots do estado atual do combate em ciclos curtos; o painel recebe, calcula a UI e renderiza. Essa separação me permite iterar visual sem recompilar o executável a cada ajuste.

Por que não WPF nativo? Experimentei no começo e abandonei. WPF puro teria sido uma segunda curva de aprendizado em cima da já íngreme curva do protocolo. Com WebView2, reaproveito conhecimento web — flexbox, variáveis CSS, animações de barra — e consigo preencher o painel visualmente competitivo em dias, não semanas. O custo é embarcar o runtime do WebView2 como dependência; no Windows 11 ele já vem instalado, no Windows 10 pode precisar de instalação manual.

Supabase como backend anônimo pra community sync

Projetos de engenharia reversa com IA ganham quando a comunidade compartilha dados que nenhum usuário sozinho conseguiria coletar. O WS-engine tem um recurso opcional de sincronização comunitária que compartilha caches básicos entre usuários — nicks observados, classes vistas, mapeamento jogador/guilda. A primeira vez que o programa abre, ele gera um GUID aleatório salvo num arquivo local chamado ws-engine.client-id.txt. Esse GUID é a única identidade usada no backend; nenhum nome, e-mail, IP, telemetria de uso ou dado pessoal entra na equação.

Decidi deixar a sincronização ligada por padrão e documentar como desligar. É opt-OUT, não opt-IN. A razão é prática: o valor da ferramenta cresce com a cobertura — quanto mais usuários contribuem nicks observados, mais rápido novos usuários vêem a tabela preenchida ao entrar numa luta. Se o padrão fosse opt-IN, a maioria nunca ligaria e a ferramenta ficaria pobre. A troca é razoável porque o dado trafegado é absolutamente banal.

O backend é um Supabase gratuito. Qualquer cliente com a URL pública e a anon-key pode escrever qualquer registro — modelo de trust leve, adequado pra uma comunidade pequena. Se um dia aparecer troll poluindo o cache, o procedimento documentado é um reset: apagar o arquivo client-id.txt para o cliente, limpar as tabelas afetadas no backend e seguir. Nenhum sistema de autenticação por usuário faria sentido no volume e no risco atual.

Distribuição no Windows: falso positivo de antivírus e releases

Quem faz engenharia reversa com IA costuma subestimar a parte de entregar o programa pros usuários finais. Distribuição é o problema que não aparece no desenvolvimento mas custa suporte na vida real. O WS-engine é publicado como ZIP em GitHub Releases, extraído em qualquer pasta pelo usuário final. O executável principal pede UAC porque precisa capturar pacotes e ler o processo do cliente. Essa combinação — binário não assinado, pede admin, lê rede, lê processo — é literalmente o perfil comportamental de um trojan para o Windows Defender. Falso positivo é regra, não exceção.

A documentação do projeto gasta parágrafos explicando como adicionar exceção no antivírus, porque é o primeiro problema que novo usuário enfrenta. Já perdi usuários que simplesmente apagaram o ZIP achando que era vírus. A assinatura digital de código resolveria boa parte disso, mas emitir um certificado de code signing custa centenas de dólares por ano, dinheiro que não existe num projeto pessoal sem monetização. Aceito a fricção.

Releases são publicadas manualmente via o repositório do GitHub, cada uma com changelog curto em português e o ZIP compactado da pasta do executável. Nenhum auto-update: o programa avisa quando há release nova e aponta pra página — a atualização é manual. Autoupdater exigiria assinatura e infraestrutura própria. Para o volume atual, a atualização manual já funciona e não gera suporte adicional significativo.

O que a IA fez bem e onde ela quebrou

Terminando com honestidade sobre engenharia reversa com IA no cenário real. A IA foi excelente em algumas tarefas e enganosa em outras. Entre os acertos: analisar o header PE do executável do jogo para confirmar que o binário é nativo C/C++ e não está packeado, com entropia da seção de código em faixa normal. Esse diagnóstico inicial poupou dias — se o binário tivesse packing, a análise estática seria inviável e eu teria mudado de abordagem. Outro acerto foi inferir que o dispatch de mensagens não era um switch indexado por tag imediata, e sim virtual dispatch C++ via vtable, baseando-se em padrões de instrução identificados por scan direto na seção de código.

Entre os erros, que também são parte honesta da conversa sobre engenharia reversa com IA: a IA sustentou por algumas rodadas a hipótese de que o byte alto de um identificador de entidade seria estável — invocações sempre começariam com um valor fixo, mobs com outro. Patch do jogo migrou esse byte alto para um valor completamente diferente e todos os componentes que dependiam da hipótese quebraram juntos. A lição foi dura: byte alto de identificador quase sempre é alocação arbitrária do servidor, não semântica. A fonte de verdade estrutural (um evento de spawn com layout válido) é canônica; o resto é namespace numérico mutável.

Outro erro memorável foi uma hipótese inicial de que existiria um "roster estrutural separado" dentro de um envelope comprimido, carregando lista de jogadores presentes na área. Horas de investigação, scripts probe, análises de nested tags. Resultado: aquilo que o scan achava era só chat aninhado no mesmo envelope, nenhum roster estruturado existia. Precisei desfazer o pipeline que já tinha montado em cima da hipótese errada. Deu certo justamente porque voltar atrás com a IA é barato — pedi pra ela ler os logs do probe comigo e, no segundo ciclo, ela mesma identificou a confusão. Sem IA, esse projeto não teria saído do papel no meu nível inicial de conhecimento. Com IA, saiu — e aprendi muito no caminho. Pra ver outros projetos técnicos nessa linha, dá uma volta pelo ModoDev.

Avalie este artigo

0.0 · 0 avaliações

Continue lendo

Comentários

Carregando comentários...

Deixe seu comentário