Most visitors online was 8830 , on 6 Feb 2024
Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!
Join Today!What about encryption key used for encrypt/decrypt functions in the cracked client you gave?View attachment 157112
attached image is one of a slot.
packet is composed of a HEADER + 5 slots DATA.
but, in Returns(572), all packets has changed.
View attachment 157112
attached image is one of a slot.
packet is composed of a HEADER + 5 slots DATA.
but, in Returns(572), all packets has changed.
Does the client DC after getting character list packet or before?I tried login using cracked client of a3 returns provided by prologos,
But don't know where the problem is, client crashes on login and on LS it shows user disconnected.
Does the client DC after getting character list packet or before?
Then there might be slight difference in the packet structure format hence while trying to parse it the client is crashing (Maybe array out of bounds?)Before character packet,
As I entered username and password pressed enter and client crashes,
login packet is received by login agent and login server, but disconnects as client crashes
Then there might be slight difference in the packet structure format hence while trying to parse it the client is crashing (Maybe array out of bounds?)
class Config
{
public static int m_ConstKey1 = 0x241AE7;
public static int m_ConstKey2 = 0x15DCB2;
public static int m_DynamicKey = 0x4C478BD;
public const int p_Type562 = 0x0C;
public const int p_Type578 = 0x0A;
public static int p_DynamicKey1 = 0x02;
public static int p_DynamicKey2 = 0x01;
public static uint p_ConstKey_En = 0xA7F0753B;
public static uint p_ConstKey_De = 0xAAF29BF3;
}
class Crypt
{
public static byte[] Decrypt(byte[] packet, int Type = Config.p_Type578)
{
//[0]-[11]: Packet Header
for (int i = Type; i + 4 <= packet.Length; i += 4)
{
if (i == Config.p_Type578)
{
uint wProtocol = (BitConverter.ToUInt32(packet, i) * Config.p_ConstKey_De) >> 16;
var wProtocolByte = BitConverter.GetBytes(wProtocol);
Buffer.BlockCopy(wProtocolByte, 0, packet, 10, 4);
continue;
}
int DynamicKey = Config.m_DynamicKey;
for (int j = i; j < i + 4; j++)
{
byte pSrc = packet[j];
packet[j] = (byte)(packet[j] ^ (DynamicKey >> 8));
DynamicKey = (pSrc + DynamicKey) * Config.m_ConstKey1 + Config.m_ConstKey2;
}
}
return packet;
}
public static byte[] Encrypt(byte[] packet, int Type = Config.p_Type578)
{
//[0]-[11]: Packet Header
for (int i = Type; i + 4 <= packet.Length; i += 4)
{
if (i == Config.p_Type578)
{
uint wProtocol = (uint)((BitConverter.ToUInt16(packet, i) << 16) + (Config.p_DynamicKey1 << 8) + Config.p_DynamicKey2) * Config.p_ConstKey_En;
var wProtocolByte = BitConverter.GetBytes(wProtocol);
Buffer.BlockCopy(wProtocolByte, 0, packet, 10, 4);
Config.p_DynamicKey2 = (byte)Config.p_DynamicKey1 + Config.p_DynamicKey2;
Config.p_DynamicKey1 = (byte)Config.p_DynamicKey1 + 0xB3;
continue;
}
int DynamicKey = Config.m_DynamicKey;
for (int j = i; j < i + 4; j++)
{
packet[j] = (byte)(packet[j] ^ (DynamicKey >> 8));
DynamicKey = (packet[j] + DynamicKey) * Config.m_ConstKey1 + Config.m_ConstKey2;
}
}
return packet;
}
}
As usual prologos saving the day1. Login packet has been changed. It must be treated with LA.
2. encrypt/decrypt function is substantially the same as 562.
578, to encrypt/decrypt the protocol part of the header in a new way.
*Examples of encrypt/decrypt function in C#
Code:class Config { public static int m_ConstKey1 = 0x241AE7; public static int m_ConstKey2 = 0x15DCB2; public static int m_DynamicKey = 0x4C478BD; public const int p_Type562 = 0x0C; public const int p_Type578 = 0x0A; public static int p_DynamicKey1 = 0x02; public static int p_DynamicKey2 = 0x01; public static uint p_ConstKey_En = 0xA7F0753B; public static uint p_ConstKey_De = 0xAAF29BF3; }
Precisely, using the random number to encrypt the part of the protocol. However, to work well, just above code.Code:class Crypt { public static byte[] Decrypt(byte[] packet, int Type = Config.p_Type578) { //[0]-[11]: Packet Header for (int i = Type; i + 4 <= packet.Length; i += 4) { if (i == Config.p_Type578) { uint wProtocol = (BitConverter.ToUInt32(packet, i) * Config.p_ConstKey_De) >> 16; var wProtocolByte = BitConverter.GetBytes(wProtocol); Buffer.BlockCopy(wProtocolByte, 0, packet, 10, 4); continue; } int DynamicKey = Config.m_DynamicKey; for (int j = i; j < i + 4; j++) { byte pSrc = packet[j]; packet[j] = (byte)(packet[j] ^ (DynamicKey >> 8)); DynamicKey = (pSrc + DynamicKey) * Config.m_ConstKey1 + Config.m_ConstKey2; } } return packet; } public static byte[] Encrypt(byte[] packet, int Type = Config.p_Type578) { //[0]-[11]: Packet Header for (int i = Type; i + 4 <= packet.Length; i += 4) { if (i == Config.p_Type578) { uint wProtocol = (uint)((BitConverter.ToUInt16(packet, i) << 16) + (Config.p_DynamicKey1 << 8) + Config.p_DynamicKey2) * Config.p_ConstKey_En; var wProtocolByte = BitConverter.GetBytes(wProtocol); Buffer.BlockCopy(wProtocolByte, 0, packet, 10, 4); Config.p_DynamicKey2 = (byte)Config.p_DynamicKey1 + Config.p_DynamicKey2; Config.p_DynamicKey1 = (byte)Config.p_DynamicKey1 + 0xB3; continue; } int DynamicKey = Config.m_DynamicKey; for (int j = i; j < i + 4; j++) { packet[j] = (byte)(packet[j] ^ (DynamicKey >> 8)); DynamicKey = (packet[j] + DynamicKey) * Config.m_ConstKey1 + Config.m_ConstKey2; } } return packet; } }
1. Login packet has been changed. It must be treated with LA.
2. encrypt/decrypt function is substantially the same as 562.
578, to encrypt/decrypt the protocol part of the header in a new way.
*Examples of encrypt/decrypt function in C#
Code:class Config { public static int m_ConstKey1 = 0x241AE7; public static int m_ConstKey2 = 0x15DCB2; public static int m_DynamicKey = 0x4C478BD; public const int p_Type562 = 0x0C; public const int p_Type578 = 0x0A; public static int p_DynamicKey1 = 0x02; public static int p_DynamicKey2 = 0x01; public static uint p_ConstKey_En = 0xA7F0753B; public static uint p_ConstKey_De = 0xAAF29BF3; }
Precisely, using the random number to encrypt the part of the protocol. However, to work well, just above code.Code:class Crypt { public static byte[] Decrypt(byte[] packet, int Type = Config.p_Type578) { //[0]-[11]: Packet Header for (int i = Type; i + 4 <= packet.Length; i += 4) { if (i == Config.p_Type578) { uint wProtocol = (BitConverter.ToUInt32(packet, i) * Config.p_ConstKey_De) >> 16; var wProtocolByte = BitConverter.GetBytes(wProtocol); Buffer.BlockCopy(wProtocolByte, 0, packet, 10, 4); continue; } int DynamicKey = Config.m_DynamicKey; for (int j = i; j < i + 4; j++) { byte pSrc = packet[j]; packet[j] = (byte)(packet[j] ^ (DynamicKey >> 8)); DynamicKey = (pSrc + DynamicKey) * Config.m_ConstKey1 + Config.m_ConstKey2; } } return packet; } public static byte[] Encrypt(byte[] packet, int Type = Config.p_Type578) { //[0]-[11]: Packet Header for (int i = Type; i + 4 <= packet.Length; i += 4) { if (i == Config.p_Type578) { uint wProtocol = (uint)((BitConverter.ToUInt16(packet, i) << 16) + (Config.p_DynamicKey1 << 8) + Config.p_DynamicKey2) * Config.p_ConstKey_En; var wProtocolByte = BitConverter.GetBytes(wProtocol); Buffer.BlockCopy(wProtocolByte, 0, packet, 10, 4); Config.p_DynamicKey2 = (byte)Config.p_DynamicKey1 + Config.p_DynamicKey2; Config.p_DynamicKey1 = (byte)Config.p_DynamicKey1 + 0xB3; continue; } int DynamicKey = Config.m_DynamicKey; for (int j = i; j < i + 4; j++) { packet[j] = (byte)(packet[j] ^ (DynamicKey >> 8)); DynamicKey = (packet[j] + DynamicKey) * Config.m_ConstKey1 + Config.m_ConstKey2; } } return packet; } }
Great prologos , thanks for the code snippet.
As you mentioned 1st point about login packets are changed.
I observed login packet is of 64 bytes which was 56 bytes in case of v562.
So it would be glad if you can provide with login packet structure and its response to be send from server.
prologos Great work, Thanks, I was able to login, now trying to sort out character packetsperhaps... Try the following code to the Inferno-Login-Agent-562
*change on line 130 of Packet.cs
case 52:
desiredPacket = new byte[] { 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0 };
if (desiredPacket.SequenceEqual(packetGot))
{
var temp = CreateReverseHexPacket(cindex);
buffer[4] = temp[0];
buffer[5] = temp[1];
returnPacket = buffer;
}
break;
case 64:
desiredPacket = new byte[] { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0 };
if (desiredPacket.SequenceEqual(packetGot))
{
var temp = CreateReverseHexPacket(cindex);
buffer[4] = temp[0];
buffer[5] = temp[1];
returnPacket = buffer;
}
break;
*add function to Packet.cs
public static byte[] CreateServerList(byte[] buffer)
{
var packetLen = BitConverter.ToInt32(new byte[] { buffer[0], buffer[1], buffer[2], buffer[3] }, 0);
var newPacket = new byte[packetLen + 21];
byte[] byteArray = BitConverter.GetBytes(packetLen + 21);
Buffer.BlockCopy(byteArray, 0, newPacket, 0, 4);
Buffer.BlockCopy(buffer, 4, newPacket, 4, 6);
Buffer.BlockCopy(buffer, 10, newPacket, 31, packetLen - 10);
return newPacket;
}
*change on line 271 of LoginAgent.cs
else if (Encoding.ASCII.GetString(bytes).Substring(30, 6) == "ONLINE")
{
// Prepend welcome message to the server name data
bytes = Packet.CombineByteArray(Packet.CreateWelcomeMessage(cindex), Packet.TrimPacket(bytes));
}
else if (Encoding.ASCII.GetString(bytes).Substring(30, 6) == "ONLINE" || Encoding.ASCII.GetString(bytes).Substring(30, 7) == "OFFLINE")
{
// Prepend welcome message to the server name data
bytes = Packet.CreateServerList(bytes);
}
Perhaps the code is not perfect. However, the Test is possible.
@prologos Great work, Thanks, I was able to login, now trying to sort out character packets
Hi can you share us how you are able to login in ?
Thanks
Well take ZA562 from http://forum.ragezone.com/f487/zoneagent-562-a-1010989/ and take login agent fromYou must be registered to see links
Make some changes as mentioned above by prologos
take returns client, hex it and boom you login.
ZA 562 is the tweaked ZA itself!