- Joined
- May 29, 2007
- Messages
- 2,167
- Reaction score
- 899
shiftSize = ((offset) % 7) + 1
class PROTOCOL_BASE_CONNECT_ACK : Packet // Opcode 514 (0x202)
{
public override void WriteImpl()
{
WriteH(0); // ?
WriteD(Session.Id); // <-- This
WriteH(Session.Salt);
// ...
}
}
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);
// ...
}
}
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;
}
}
S2MOPacketBase::SetPacketRandSeed(randSeed);
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);
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.
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.
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;
}