12-29-2015, 01:56 PM
Крипт и декрипт
Клиент Piercing Blow криптует пакеты (и не только) методом сдвига бит. Методы крипта и декрипта можно без усилий получить из i3BaseDx_Cli.dll.
[SRC="csharp"]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);
}
}
[/SRC]
Tcp пакеты
Структура клиентского Tcp пакета:
[SRC="csharp"]class TcpPacket
{
ushort Length { get; set; }
ushort Opcode { get; set; }
byte[] Data { get; set; }
}
[/SRC]
При этом размер пакета не криптуется, а комбинируется с флагом 0x8000.
[SRC="csharp"]ushort length =| 0x8000
[/SRC]
Таким образом, при получении пакета от клиента, нам нужно получить размер данных, это делается так:
[SRC="csharp"]int length = BitConverter.ToUInt16(_buffer, 0) & 0x7FFF;
[/SRC]
В размере пакета не учтён размер опкода, поэтому с буффера нужно получить на 2 байта больше полученной длины.
[SRC="csharp"]byte[] buffer = new byte[length + 2];
Buffer.BlockCopy(_buffer, 2, buffer, 0, buffer.Length);
Unshift(buffer, _bits);
[/SRC]
Сам сдвиг рассчитывается следующим образом:
[SRC="csharp"]// Id - идентификатор текущего соединения.
_bits = Id % 7 + 1;
[/SRC]
В ответ сервер отправляет не криптованные данные, структура которых ничем не отличается от клиентских.
Udp пакеты
Piercing Blow, Point Blank и Project Blackout для обмена данными между игроками использует одноранговую сеть P2P.
Структура Udp пакета
[SRC="csharp"]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; }
}
[/SRC]
Первые 13 байт* в которые входят Id, Slot, Time, Session, Length - не криптованы, это касается как клиентских, так и серверных пакетов. Data же криптована всё тем же сдвигом бит, только для получения сдвига используется длина пакета:
[SRC="csharp"]int bits = length % 6 + 1;
[/SRC]
*длина заголовка Udp пакета может меняться от версии к версии.
Так же, изучите тему с чего начать написание BattleServer в режиме Relay, чтобы применить полученные знания на деле.
Есть вопросы или дополнения - велком.
Клиент Piercing Blow криптует пакеты (и не только) методом сдвига бит. Методы крипта и декрипта можно без усилий получить из i3BaseDx_Cli.dll.
[SRC="csharp"]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);
}
}
[/SRC]
Tcp пакеты
Структура клиентского Tcp пакета:
[SRC="csharp"]class TcpPacket
{
ushort Length { get; set; }
ushort Opcode { get; set; }
byte[] Data { get; set; }
}
[/SRC]
При этом размер пакета не криптуется, а комбинируется с флагом 0x8000.
[SRC="csharp"]ushort length =| 0x8000
[/SRC]
Таким образом, при получении пакета от клиента, нам нужно получить размер данных, это делается так:
[SRC="csharp"]int length = BitConverter.ToUInt16(_buffer, 0) & 0x7FFF;
[/SRC]
В размере пакета не учтён размер опкода, поэтому с буффера нужно получить на 2 байта больше полученной длины.
[SRC="csharp"]byte[] buffer = new byte[length + 2];
Buffer.BlockCopy(_buffer, 2, buffer, 0, buffer.Length);
Unshift(buffer, _bits);
[/SRC]
Сам сдвиг рассчитывается следующим образом:
[SRC="csharp"]// Id - идентификатор текущего соединения.
_bits = Id % 7 + 1;
[/SRC]
В ответ сервер отправляет не криптованные данные, структура которых ничем не отличается от клиентских.
Udp пакеты
Piercing Blow, Point Blank и Project Blackout для обмена данными между игроками использует одноранговую сеть P2P.
Структура Udp пакета
[SRC="csharp"]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; }
}
[/SRC]
Первые 13 байт* в которые входят Id, Slot, Time, Session, Length - не криптованы, это касается как клиентских, так и серверных пакетов. Data же криптована всё тем же сдвигом бит, только для получения сдвига используется длина пакета:
[SRC="csharp"]int bits = length % 6 + 1;
[/SRC]
*длина заголовка Udp пакета может меняться от версии к версии.
Так же, изучите тему с чего начать написание BattleServer в режиме Relay, чтобы применить полученные знания на деле.
Есть вопросы или дополнения - велком.