Welcome!

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!

A3 returns help

Junior Spellweaver
Joined
Nov 16, 2012
Messages
101
Reaction score
21
It would be glad if some one can provide ACL file structure information about a3 returns.
The form in which bytes are stored etc etc.
 
Newbie Spellweaver
Joined
Jan 26, 2012
Messages
75
Reaction score
73
acl - A3 returns help - RaGEZONE Forums

attached image is one of a slot.
packet is composed of a HEADER + 5 slots DATA.

but, in Returns(572), all packets has changed.
but, in Returns(578), all packets has changed.
 

Attachments

You must be registered for see attachments list
Last edited:
Junior Spellweaver
Joined
Nov 16, 2012
Messages
101
Reaction score
21
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.

Thank you prologs for the reply.
I would like to know more about headers in which you have marked with Ctrl, Cmd and Protocol. What are this in header?
And does this 578 packet structure (shown in image) works with returns client ?
 
Junior Spellweaver
Joined
Nov 16, 2012
Messages
101
Reaction score
21
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.
 
Junior Spellweaver
Joined
Nov 16, 2012
Messages
101
Reaction score
21
Does the client DC after getting character list packet or before?

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
 
Joined
Jun 10, 2009
Messages
659
Reaction score
141
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?)
 
Junior Spellweaver
Joined
Nov 16, 2012
Messages
101
Reaction score
21
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?)

May be possible. Will try it out differently modifying login packets and will post results.
 
Newbie Spellweaver
Joined
Jan 26, 2012
Messages
75
Reaction score
73
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;
    }

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;
        }
    }
Precisely, using the random number to encrypt the part of the protocol. However, to work well, just above code.
 
Joined
Jun 10, 2009
Messages
659
Reaction score
141
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;
    }

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;
        }
    }
Precisely, using the random number to encrypt the part of the protocol. However, to work well, just above code.
As usual prologos saving the day :thumbup:
 
Junior Spellweaver
Joined
Nov 16, 2012
Messages
101
Reaction score
21
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;
    }

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;
        }
    }
Precisely, using the random number to encrypt the part of the protocol. However, to work well, just above code.

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.
 
Newbie Spellweaver
Joined
Jan 26, 2012
Messages
75
Reaction score
73
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.

perhaps... 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.
 
Junior Spellweaver
Joined
Nov 16, 2012
Messages
101
Reaction score
21
perhaps... 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
 
Newbie Spellweaver
Joined
Apr 5, 2008
Messages
55
Reaction score
0
I did those changes.
Client gets crashed :(
Thankyou for reply.
Ill try again.
 
Last edited:
Newbie Spellweaver
Joined
Apr 5, 2008
Messages
55
Reaction score
0
Back
Top