Крипт и декрипт
Клиент Piercing Blow криптует пакеты (и не только) методом сдвига бит. Методы крипта и декрипта можно без усилий получить из
i3BaseDx_Cli.dll.
public static void Shift(byte[] buffer, int bits)
{
int length = buffer.Length;
byte first = buffer[0];
byte current;
for (int i = 0; i < length; i++)
{
if (i >= (length - 1))
{
current = first;
}
else
{
current = buffer[i + 1];
}
buffer[i] = (byte)(current >> (8 - bits) | (buffer[i] << bits));
}
}
public static void Unshift(byte[] buffer, int bits)
{
int length = buffer.Length;
byte last = buffer[length - 1];
byte current;
for (int i = length - 1; (i & 0x80000000) == 0; i--)
{
if (i <= 0)
{
current = last;
}
else
{
current = buffer[i - 1];
}
buffer[i] = (byte)(current << (8 - bits) | buffer[i] >> bits);
}
}
Code: C#
Tcp пакеты
Структура клиентского Tcp пакета:
class TcpPacket
{
ushort Length { get; set; }
ushort Opcode { get; set; }
byte[] Data { get; set; }
}
Code: C#
При этом размер пакета не криптуется, а комбинируется с флагом 0x8000.
ushort length =| 0x8000
Code: C#
Таким образом, при получении пакета от клиента, нам нужно получить размер данных, это делается так:
int length = BitConverter.ToUInt16(_buffer, 0) & 0x7FFF;
Code: C#
В размере пакета не учтён размер опкода, поэтому с буффера нужно получить на 2 байта больше полученной длины.
byte[] buffer = new byte[length + 2];
Buffer.BlockCopy(_buffer, 2, buffer, 0, buffer.Length);
Unshift(buffer, _bits);
Code: C#
Сам сдвиг рассчитывается следующим образом:
// Id - идентификатор текущего соединения.
_bits = Id % 7 + 1;
Code: C#
В ответ сервер отправляет не криптованные данные, структура которых ничем не отличается от клиентских.
Udp пакеты
Piercing Blow, Point Blank и Project Blackout для обмена данными между игроками использует одноранговую сеть P2P.
Структура Udp пакета
public class UdpPacket
{
public byte Id { get; set; }
public byte Slot { get; set; }
public float Time { get; set; }
public byte Session { get; set; }
public ushort Length { get; set; }
public byte[] Data { get; set; }
}
Code: C#
Первые
13 байт* в которые входят Id, Slot, Time, Session, Length - не криптованы, это касается как клиентских, так и серверных пакетов. Data же криптована всё тем же сдвигом бит, только для получения сдвига используется длина пакета:
int bits = length % 6 + 1;
Code: C#
*длина заголовка Udp пакета может меняться от версии к версии.
Так же, изучите тему
с чего начать написание BattleServer в режиме Relay, чтобы применить полученные знания на деле.
Есть вопросы или дополнения - велком.