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!

[RESOURCE] Packet Structure Information

◝(⁰▿⁰)◜Smile◝ (⁰▿⁰)◜
Developer
Joined
May 29, 2007
Messages
2,167
Reaction score
898
Point Blanks / Project Blackout / Piercing blow uses binary packets with a header of 4 bytes.
This header contains the information of the packet data length and packet opcode (id). Both of these values are ushorts, which are both 2 bytes each. The rest of the packet is the content, the length of the content is based on the length that set inside the header. So the packet content's length is equal to the ushort value of the first 2 bytes.



Taiga - [RESOURCE] Packet Structure Information - RaGEZONE Forums


Server packets are not encrypted at all, they are send directly without encryption. The client packets are 'encrypted' with a bit shift function. The bits of the packet are moved by x bits based on the offset that was sent in the first packet. The packet gets shifted with maximum 8 bits. I'm still not 100% sure of the offset so I use a static 'key' offset to calculate the bit shifting size.

The you can calculate the poop size by doing the following math:
Code:
shiftSize = ((offset) % 7) + 1


There is always a bit shift of at least 1 bit. 8 bits at max. The last (or overflowing) bits are moved to the beginning.
 
Newbie Spellweaver
Joined
Feb 3, 2008
Messages
58
Reaction score
46
To recieve shiftsize the client uses session id that is given by server first packet.

For Piercing Blow or others which use this engine:


Code:
class PROTOCOL_BASE_CONNECT_ACK : Packet // Opcode 514 (0x202)
{
    public override void WriteImpl()
    {
        WriteH(0); // ?
        WriteD(Session.Id); // <-- This
        WriteH(Session.Salt);
        
        // ...
    }
}

For old Point Blank or Project Blackout:


Code:
class PROTOCOL_BASE_SERVERLIST_ACK : Packet // Opcode 2049 (0x801)
{
    public override void WriteImpl()
    {
        WriteD(Session.Id); // <-- This
        WriteIP(Session.RemoteIPAddress);
        WriteH(Session.RemoteUdpPort);
        WriteH(Session.Salt);
        
        // ...
    }
}

I assign session id like this:

Code:
public class ClientManager : SingletonHelper<ClientManager>
{
    /// <summary>
    /// Session holder
    /// </summary>
    static readonly Dictionary<int, NetworkSession> _sessions
        = new Dictionary<int, NetworkSession>();


    /// <summary>
    /// Session id
    /// </summary>
    static int _sessionId = 0;


    /// <summary>
    /// Accept new client
    /// </summary>
    /// <param name="arg"></param>
    public void Accept(IAsyncResult arg)
    {
        TcpListener listener = arg.AsyncState as TcpListener;
        TcpClient client = listener.EndAcceptTcpClient(arg);


        Connected(client);


        listener.BeginAcceptTcpClient(Accept, listener);
    }


    /// <summary>
    /// Connected client
    /// </summary>
    /// <param name="client"></param>
    static void Connected(TcpClient client)
    {
        Interlocked.Increment(ref _sessionId);


        NetworkSession session = new NetworkSession() {
            Id = _sessionId
        };


        session.Accept(client);
        session.OnDisconnected += Disconnected;


        _sessions.Add(session.Id, session);


        _log.Info("New client session #{0} is connected.", session.Id);
    }


    /// <summary>
    /// Disconnected client
    /// </summary>
    /// <param name="session"></param>
    static void Disconnected(NetworkSession session)
    {
        session.OnDisconnected -= Disconnected;


        _sessions.Remove(session.Id);


        _log.Info("Client session #{0} disconnected from server.", session.Id);


        session = null;
    }
}
 
Newbie Spellweaver
Joined
Feb 3, 2008
Messages
58
Reaction score
46
In client it is named as RandSeed (rnd short number), and is used to make the same packet after encrypt to look differ.


Code:
S2MOPacketBase::SetPacketRandSeed(randSeed);
 
Newbie Spellweaver
Joined
Aug 11, 2015
Messages
55
Reaction score
16
Point Blanks / Project Blackout / Piercing blow uses binary packets with a header of 4 bytes.
This header contains the information of the packet data length and packet opcode (id). Both of these values are ushorts, which are both 2 bytes each. The rest of the packet is the content, the length of the content is based on the length that set inside the header. So the packet content's length is equal to the ushort value of the first 2 bytes.



Taiga - [RESOURCE] Packet Structure Information - RaGEZONE Forums


Server packets are not encrypted at all, they are send directly without encryption. The client packets are 'encrypted' with a bit shift function. The bits of the packet are moved by x bits based on the offset that was sent in the first packet. The packet gets shifted with maximum 8 bits. I'm still not 100% sure of the offset so I use a static 'key' offset to calculate the bit shifting size.

The you can calculate the poop size by doing the following math:
Code:
shiftSize = ((offset) % 7) + 1


There is always a bit shift of at least 1 bit. 8 bits at max. The last (or overflowing) bits are moved to the beginning.

Anyone know how packet are encrypted on the new client? (v3.41)
I'm using this way to decrypt the packets, but this isn't working all the times. Maybe there is a different key sended on the first packet?

Code:
        static int Key { get; set; }
        static int GetKey { get { return 29890; } }
        static int GetId { get { return 5404; } }
        static void SetShiftSize(int _key) { Key = _key; }
        static int GetShiftSize { get { return Key; } }

        internal static byte[] Decrypt(byte[] _packet)
        {
            int id = GetId, key = GetKey, shiftSize = GetShiftSize;
            if (shiftSize == 0 || shiftSize == -1)
            {
                shiftSize = ((id + GetKey) % 7) + 1;
                SetShiftSize(shiftSize);
            }
            byte[] bytes = UntangleBuffer(_packet, shiftSize);
            return bytes;
        }

        internal static byte[] UntangleBuffer(byte[] _buffer, int _shiftsize)
        {
            int size = _buffer.Length - 1;
            byte lastByte = _buffer[size];
            for (int ii = size; ii > 0; ii--)
            {
                _buffer[ii] = (byte)(_buffer[ii] / 2);
            }
            _buffer[0] = (byte)(_buffer[0] / 2);
            return _buffer;
        }
 
Last edited:
Back
Top