Digimon Masters Online – Yggdrasil

A um bom tempo atrás eu comecei a jogar Digimon Masters Online (recomendo, um ótimo MMORPG de Digimon), o jogo é bem interessante e tem um game play bem divertido. De certa forma minha curiosidade foi além com esse jogo, lembrei da época que tentei fazer um “emulador” do servidor de Ragnarok e tentei seguir o mesmo caminho com esse jogo, utilizei uma ferramenta bem útil para *packet sniff* conhecida como Wireshark (um dos motivos de eu te utilizado essa ferramenta foi por que o jogo possui uma proteção, conhecida como hackshield, então não poderia utilizar um WPE Pro por exemplo, mais a frente falarei como removi essa proteção[…], nas últimas atualizações o jogo não tá usando mais hackshield, mas só por curiosidade, utilizei Ollydbg para remover), e por sorte, a comunicação entre o cliente e servidor não possui nenhum tipo de criptografia, assim dei início ao Yggdrasil.

O jogo utiliza dois aplicativos para sua inicialização, o primeiro é o DMLauncher.exe que verifica atualizações no servidor (provavelmente FTP ?) e faz uma comparação nos arquivos do cliente, caso algum esteja modificado e/ou desatualizado, ele baixa um novo e substitui o modificado e/ou desatualizado, o que é um problema, pois precisamos fazer algumas modificações no GDMO.exe (executável principal do jogo). Se você tentar inicializar direto o GDMO.exe, ele vai pedir para executar o DMLauncher.exe, então precisamos descobrir qual comando utilizado para inicialização do GDMO.exe, na grande maioria dos casos, tanto o Launcher com o próprio executável do aplicativo são ofuscados/criptografados (um exemplo clássico é o ASprotect que o Grand Chase utiliza em seu executável principal). Por incrível que pareça, não há nenhum tipo de criptografia/ofuscação/whatever no executável, podemos editar sem nos preocupar. Então utilizei para saber como o DMLauncher.exe inicializa o GDMO.exe a ferramenta IDA Pro, vasculhando um pouco o executável, cheguei a seguinte função:

Inicialização do GDMO.exe

Inicialização do GDMO.exe

Como você pode observar na imagem, a função StartDMO_Exe vai chamar um CreateProcessW com o nome do processo(nesse caso GDMO.exe) e com um commandLine, que será o “true”, isso nos permite executar de forma fácil o executável apenas utilizando o cmd e digitando “GDMO.exe -true”, simples não ?

Após essa primeira etapa, a segunda é conseguir modificar o GDMO.exe para conectar ao nosso IP (eu vou optar em utilizar o 127.0.0.1, localhost, por que fica mais fácil para fazer meus próprios testes). O que é uma piada, por que até o executável principal não tem nenhuma proteção e ofuscação, então mais uma vez utilizei o IDA Pro para localizar o IP e um editor hexadecimal para modificar o executável. Essa é a função que ler o IP do Login Server:

Login Server IP

Basta abrir qualquer editor hexadecimal e procurar por “account.dmo.joymax.com”, e modificar para um IP qualquer, no caso coloquei 127.0.0.1 e o resto preenchi com 00 (hex) e ele conectou, faça um backup do GDMO.exe sem modificação, ele será importante para conectar no servidor oficial e fazer packet sniff e analisar eles.

Como atualizei o cliente, decidi da uma analisada e percebi que aparentemente chutaram o balde e não estão utilizando mais nenhuma proteção (antigamente Hackshield), então não vai ser necessário ficar horas no ollydbg para remover a proteção. Eu utilizei a partir desse momento o WPE Pro para fazer o sniff e analise dos pacotes.

Acho que é importante antes de falar sobre a estrutura dos pacotes, falar como o servidor se comporta, essa conclusão foi feita a partir de analises feitas com tentativa e erro, mas acredito que isso seja o mais próximo de como o servidor é:

Estrutura do Server

A parte inicial é a autenticação feita entre o cliente e o servidor de login, o trabalho do servidor de login é basicamente gerenciar se a conta existe ou a senha está correta, enviar uma lista de canais (que é um socket IP::Porta) e atualizar se o cliente solicitar, verificar se o servidor está em manutenção e coisas do tipo. Cada canal é um servidor de personagens, cada servidor vai gerenciar os personagens da sua conta e informações básicas (level, localização, digimon[…]) e ele está vinculado a um único servidor de mapas, que é onde o jogo em sí se passa).

Finalmente agora vamos falar sobre a estrutura dos pacotes, que é a parte mais importante, vamos a um exemplo: Este é um pacote que é enviado do cliente para o servidor, o que esse pacote faz é basicamente pegar o login, senha e todas as informações do computador (?) e enviar para o servidor, o servidor verifica se o login existe, senha está correta e por fim envia as informações para o cliente (nesse caso a lista de servidores e outras informações), pacote:

Informações do Login

Como você pode observar, os dois primeiros bytes é o tamanho do pacote (geralmente quando o pacote é maior que 255(0xFF em Hexadecimal) bytes, o segundo byte é escrito), os dois bytes seguintes é o header do pacote, ele é utilizado para identificar qual pacote estamos trabalhando, a parte em azul escuro é o login e senha do player, observe que o byte inicial antes da string é basicamente o tamanho do login e senha (4 bytes = 4 letras = strlen(“test”)). Para descobrir como é feito o Checksum, foi necessário um pouco de engenharia reversa no GDMO.exe, a função fica no endereço 0x00756AF0 (no último update lançado até então):

PseudoC do Checksum

Como explicado, o que a função faz é basicamente pegar o tamanho do pacote e fazer a xor com valor 6716 (caso você não saiba o que é xor, você pode encontrar informações aqui). Outra maneira é apenas observar a relação entre o tamanho do pacote e o Checksum, sempre o “0x1A” é mantido, até o momento que o pacote é maior que 0xFF, como sempre a XOR entre um valor N e 0 é sempre o valor N, você já tem 1 byte, o outro byte você descobre mesmo usando brute-force hah.

Agora que já sabemos a estrutura do servidor, a estrutura dos pacotes e a única proteção utilizada, podemos fazer um emulador do servidor, isto será útil para entender melhor como o cliente se comporta e tentar achar mais falhas, além disso também podemos criar um cliente fake para logar no servidor e também estudar o servidor, de início vamos falar apenas sober o emulador do servidor, vamos começar pelo Login Server.

O Login server é relativamente simples e fácil de emular, para isso eu utilizei C/C++ e o Winsock2 (Biblioteca de sockets para Windows). Como não há muitos pacotes no Login Server, foi um pouco mais rápido para escrever o emulador, aqui a lista de pacotes do Login Server :

Servidor → Cliente

Autenticação
2 bytes tamanho
2 bytes header 0xFFFF
2 bytes valor gerado pelo servidor, utilizado na confirmação
2 bytes checksum
Confirmação
2 bytes tamanho
2 bytes header 0xFEFF
6 bytes esse valor é relacionado aos 2 bytes da autenticação, preciso analisar melhor
2 bytes checksum
Mensagem
2 bytes tamanho
2 bytes header 0xEA0C
4 bytes desconhecido (provavelmente o tipo da mensagem ?)
n bytes texto que você vai enviar para o cliente
6 bytes string escrita NULL
2 bytes checksum
Lista de Canais
2 bytes tamanho
2 bytes header 0xE60C
1 byte quantidade de canais
4 bytes ID do canal
n bytes Nome do Canal
2 bytes status do canal ?
1 byte quantidade de personagens ?
— Se tiver mais de 1 canal, você deve repetir a mesma estrutura, id do canal, nome do canal… —
n bytes Nome do personagem do primeiro canal ?
2 bytes checksum
IP e Porta do Canal
2 bytes tamanho
2 bytes header 0x8503
4 bytes Account ID ?
4 bytes Unique ID ?
n bytes IP do Canal(Char Server)
2 bytes Porta do Canal (Char Server)
2 bytes ???
2 bytes checksum

Cliente → Servidor

Confirmar Autenticação
2 bytes tamanho
2 bytes header 0xFFFF
12 bytes desconhecido, provavelmente relacionado com os 4 bytes enviando para autenticação (necessário engenharia reversa).
2 bytes checksum

Informações do Login
2 bytes tamanho
2 bytes header 0xE50C
8 bytes desconhecido
n bytes Login
n bytes Senha
n bytes Informações do computador(sistema operacional, processador, placa de vídeo, estranho não ? )
2 bytes checksum

Atualizar lista de canais
2 bytes tamanho
2 bytes header 0xA506
2 bytes checksum

Canal selecionado
2 bytes tamanho
2 bytes header 0xA606
4 bytes ID do Canal
2 bytes checksum

Cliente está conectado
2 bytes tamanho
2 bytes header 0xFDFF
2 bytes checksum
(O pacote só serve para informar que o cliente ainda está conectado com o login server)

Com essas informações, tudo que você precisa fazer é colocar para quando você receber um pacote, decodificar o header dele, verificar o que ele faz e depois enviar as informações corretas para o cliente, lembrando de sempre respeitar o checksum, caso contrário o pacote será ignorado/descartado.

Essas são imagens do resultado do Login Server que fiz com base nessas informações:

This entry was posted in Uncategorized. Bookmark the permalink.

One Response to Digimon Masters Online – Yggdrasil

  1. henrique urameshi says:

    MUITO BOM MANO ,APRENDI MUITO COM VC , E QUERIA SABER SE VC CURTE JOGOS DE NEOGEO ??? OBRIGADO PELO BELO POST, CONTINUE MANO , E PARABÉNS 【ツ】

Leave a Reply

Your email address will not be published. Required fields are marked *