I suspect you are getting a C9 error, meaning you are unable to connect to the Agent/Client Server:
/tldr: The 0x6103 sent by the client sends empty username and password.
As a solution for the ClientlessSample, add this to the
Proxy.cs file.
It creates a new 0x6103 packet, inserts the missing username and password, then replaces the old 0x6103 packet and sends it.
Code:
void ClientSocketPacketReceived(Packet p)
{
//For ClientlessSwitcher
if (ShouldSwitchClient)
{
// Fake Client
// 0x2001
if (p.Opcode == 0x2001)
{
//[S -> C][2001][16 bytes]
//0D 00 47 61 74 65 77 61 79 53 65 72 76 65 72 00 ..GatewayServer.
Packet response = new Packet(0x2001);
if (!ShouldConnectToAgent)
{
response.WriteAscii("GatewayServer");
}
else
{
response.WriteAscii("AgentServer");
ShouldConnectToAgent = false;
}
response.WriteUInt8(0); //Client-Connection
response.Lock();
ClientSocket.Send(response);
//S->P:2005 Data:01 00 01 BA 02 05 00 00 00 02
response = new Packet(0x2005, false, true);
response.WriteUInt8(0x01);
response.WriteUInt8(0x00);
response.WriteUInt8(0x01);
response.WriteUInt8(0xBA);
response.WriteUInt8(0x02);
response.WriteUInt8(0x05);
response.WriteUInt8(0x00);
response.WriteUInt8(0x00);
response.WriteUInt8(0x00);
response.WriteUInt8(0x02);
response.Lock();
ClientSocket.Send(response);
//S->P:6005 Data:03 00 02 00 02
response = new Packet(0x6005, false, true);
response.WriteUInt8(0x03);
response.WriteUInt8(0x00);
response.WriteUInt8(0x02);
response.WriteUInt8(0x00);
response.WriteUInt8(0x02);
response.Lock();
ClientSocket.Send(response);
}
if (p.Opcode == 0x6100)
{
byte local = p.ReadUInt8();
string client = p.ReadAscii();
uint version = p.ReadUInt32();
//S->P:A100 Data:01
Packet response = new Packet(0xA100, false, true);
if (local != clientLocal)
{
response.WriteUInt8(0x02); //Faild
response.WriteUInt8(0x01); //Faild to connect to server.(C4)
}
else if (client != "SR_Client")
{
response.WriteUInt8(0x02); //Faild
response.WriteUInt8(0x03); //Faild to connect to server.(C4)
}
else if (version != LoginSettings.Version)
{
response.WriteUInt8(0x02); //Faild
response.WriteUInt8(0x02); //Update - Missing bytes but still trigger update message on Client, launcher will crash :/
}
else
{
response.WriteUInt8(0x01); //Sucess
}
response.Lock();
ClientSocket.Send(response);
}
if (p.Opcode == 0x6101 && ShouldConnectToAgent == false)
{
Packet response = new Packet(0xA102);
response.WriteUInt8(0x01); //Sucess
response.WriteUInt32(uint.MaxValue); //SessionID
response.WriteAscii("127.0.0.1"); //NetworkGlobal.Server_Address
response.WriteUInt16(localGWPort);
response.Lock();
ShouldConnectToAgent = true;
ClientSocket.Send(response);
}
if (p.Opcode == 0x6103)
{
//FF FF FF FF 00 00 00 00 16 00 00 9D 53 84 00
uint sessionID = p.ReadUInt32();
string username = p.ReadAscii();
string password = p.ReadAscii();
byte local = p.ReadUInt8();
//byte[] mac = p.ReadUInt8Array(6); //No need
Packet response = new Packet(0xA103);
if (sessionID != uint.MaxValue)
{
response.WriteUInt8(0x02);
response.WriteUInt8(0x02);
}
else if (username != "")
{
response.WriteUInt8(0x02);
response.WriteUInt8(0x02);
}
else if (password != "")
{
response.WriteUInt8(0x02);
response.WriteUInt8(0x02);
}
else if (local != clientLocal)
{
response.WriteUInt8(0x02);
response.WriteUInt8(0x02);
}
else
{
response.WriteUInt8(0x01); //Sucess
}
response.Lock();
ClientSocket.Send(response);
}
if (p.Opcode == 0x7007)
{
byte type = p.ReadUInt8();
if (type == 0x02)
{
Packet responseEndCS = new Packet(0xB001);
responseEndCS.WriteUInt8(0x01);
Packet responseInitLoad = new Packet(0x34A5);
ClientSocket.Send(responseEndCS);
ClientSocket.Send(responseInitLoad);
IsClientWaitingForData = true;
}
}
}
else
{
//Not sure why but after clientless->client the clients preferes to send 0x6103 twice.
if (p.Opcode == 0x6103)
{
if (agentLoginFixCounter > 0)
{
return;
}
agentLoginFixCounter++;
////Encrypted
//4 uint Token //from LOGIN_RESPONSE
//2 ushort Username.Length
//* string Username
//2 ushort Password.Length
//* string Password
//1 byte Content.ID
//6 byte[] MAC-Address
uint token = p.ReadUInt32();
string username = p.ReadAscii();
string password = p.ReadAscii();
byte locale = p.ReadUInt8();
byte[] macAddress = p.ReadUInt8Array(6);
// Spoof packet if it is invalid
if (string.IsNullOrEmpty(username))
{
Packet spoof = new Packet(0x6103, true);
spoof.WriteUInt32(token);
spoof.WriteAscii(LoginSettings.Username);
spoof.WriteAscii(LoginSettings.Password);
spoof.WriteUInt8(locale);
// write random 6 octet mac address
//Random mac = new Random();
spoof.WriteUInt16(0x0000); // 2 empty
spoof.WriteUInt8Array(macAddress);
p = spoof;
}
}
if (p.Opcode == 0x6102)
{
agentLoginFixCounter = 0;
}
if (agentConnected)
{
AgentSocket.Send(p);
}
else
{
GatewaySocket.Send(p);
}
}
}
Long explanation for solution:
Check login packet and spoof it with valid data if necessary before sending to Agent server.
- After injecting a packet using a proxy program, the gateway connection is closed and a connection is established with the Agent server.
- The Client does not have the username or password however, as these were not entered manually in the client but sent through the proxy instead.
This causes the client to send an invalid 0x6103 login packet with an empty username (and password) to the agent server after 0xA102.
Code:
19:31[NET]* Waiting for a connection...
19:32[NET]Sending 6101 - True - False -
19:32[NET]Sending 6102 - True - False - 16 07 00 68 75 6e 74 65 72 32 04 00 31 32 33 34 40 00
19:32[NET]gw_remote_recv_packets a102 - True - False - 01 D6 00 00 00 0C 00 39 34 2E 31 36 2E 31 31 35 2E 32 39 0C 3E
19:32[NET]* A connection has been made!
19:32[NET]* The connection has been made!
19:32[HANDLER]ag_remote_send_buffers 2001 - True - False - 09 00 53 52 5F 43 6C 69 65 6E 74 00
19:32[HANDLER]ag_remote_recv_packets s->p2005 - False - True - 01 00 01 C3 02 05 00 00 00 02
19:32[HANDLER]ag_local_recv_buffers c->p->s 6103 - True - False - D6 00 00 00 00 00 00 00 16 00 00 00 00 00 00
19:32[HANDLER]ag_remote_recv_packets s->p6005 - False - True - 03 00 02 00 02
19:32[NET]LoginClient Error a103 - True - False - 02 01
19:32[HANDLER]ag_local_recv_buffers c->p->s 2002 - False - False -
The resulting agent authentication packet has no username or password
Code:
19:32[HANDLER]ag_local_recv_buffers c->p->s 6103 - True - False - D6 00 00 00 00 00 00 00 16 00 00 00 00 00 00
Code:
//Encrypted
4 uint Token from LOGIN_RESPONSE D6 00 00 00
2 ushort Username.Length 00 00
* string Username
2 ushort Password.Length 00 00
* string Password
1 byte Content.ID 16
6 byte[] MAC-Address 00 00 00 00
The username and password have to be inserted before being sent to the agent server, otherwise a C9 error occurs.