Login & Message Server
Os dois servidores auxiliares do PangYa. Cada um tem espaço de opcode próprio começando do zero — por isso o mesmo número significa coisas diferentes dependendo do socket. Aqui estão os dois, separados.
O primeiro servidor que o cliente toca. Valida usuário e senha, mostra a lista de Game Servers e devolve a AuthKey — a credencial que o cliente apresenta depois no Game Server. Também cuida de nickname e da criação do personagem inicial.
O servidor de amigos e guild — o "MSN" do PangYa. A conexão fica aberta em paralelo com a
do Game Server. O detalhe que define esse protocolo: quase tudo trafega dentro de
um único pacote, o 0x30, que traz um
sub-opcode de 16 bits logo depois do opcode.
O quarto servidor, que ninguém falava dele. Apareceu quando eu puxei o RTTI do array de
conexões do cliente: junto com GameUnit,
MSNUnit e LoginUnit tem um
RankUnit, no connId 4. O cliente sabe montar exatamente
dois pacotes pra ele. Com o breakpoint ligado durante uma sessão inteira,
nunca disparou — o SuperSS-Dev não tem esse servidor, então o socket nunca conecta.
+0x3CTabela de pacotes
A coluna Payload vem do código do servidor, então é exata. A coluna Cliente vem do IDA e serve pra provar que o cliente realmente trata aquele opcode.
| Opcode | Dir. | Nome | Payload (servidor) | Cliente (IDA) | Descrição |
|---|
Como o cliente trata esses dois protocolos
O cliente não tem uma classe dedicada por servidor. Os mesmos dispatchers do Game Server atendem também esses sockets — o que muda é só a faixa de opcode que cada um reconhece.
Recepção: quem trata o quê
O bloco baixo do CLobbyTask (0x01–0x11)
é o Login Server — faz sentido, é ele que desenha a tela de seleção de servidor. O MSN cai
no handler comum sub_9C20A0.
A prova que fecha o caso — o case 0x03:
- servidor
pacote003escreveu32 status+str AuthKey- cliente
- lê u32, testa se é 0, lê a string e guarda em
[dword_E47E2C+0x11254]
Bate byte a byte, e o destino é justamente o global da chave que ele reapresenta no Game
Server. No MSN, o 0x2F (servidor manda u8+u32,
cliente lê u8 u32) e o 0x30 (sub-opcode
u16 primeiro dos dois lados) fecham igual.
Envio: resolvido com breakpoint
O cliente escolhe o socket como constante: monta o pacote e chama
sub_A4DAB0(connId), que indexa um array de 4 conexões na classe
WNetworkSystem. Os nomes vieram do RTTI:
GameUnit
1 = MSNUnit
3 = LoginUnit
4 = RankUnit
A busca estática não achava nenhum envio de Login. O motivo apareceu no breakpoint:
existe uma segunda cópia do construtor (sub_A4E8A0, idêntica
à sub_A4E800 — mesmo vtable, mesmo impl) e é ela que Login, MSN e
Rank usam. Eu tinha enumerado só uma das duas.
LoginUnit, 23 pro MSNUnit, 2 pro
RankUnit. E os 7 do Login são exatamente os 7 da tabela
addPacketCall do teu Login Server — conjunto idêntico.
sub_A4DAB0 capturando o endereço de retorno e o argumento, os disparos
reais bateram com a análise estática: o 0x03 do
LoginUnit saiu na hora de escolher o servidor, e o
MSNUnit disparou ao abrir a lista de amigos. O
RankUnit não disparou nenhuma vez.
0x12 é CLIENT_SHOT no Game Server e LOGIN no
Message Server. A única exceção é o 0x40, que é chat nos dois.
O que ficou em aberto
-
5 opcodes do MSN que o teu servidor não trata:
0x21,0x22,0x26,0x27e0x16B. O cliente monta e manda os cinco pelo socket do MSN — no SuperSS eles caem como "tipo desconhecido" no log. Implementar esses é ganho direto. -
Os opcodes
0x13e0x29chegam no servidor mas ninguém sabe o que pedem — o SuperSS só loga o hex. -
O
RankUnitnunca conecta porque o servidor não existe. Os dois opcodes estão no binário (sub_B292A0esub_B293E0), mas o payload deles só dá pra confirmar com o socket de pé — daria pra subir um servidor falso na porta do rank só pra ver o que chega. -
Os opcodes
0x2A–0x2Do SuperSS trata mas o cliente nunca manda: são servidor↔servidor, vindos do Game Server pro Message Server.