|
Packet.cs - читаем пакет - Разработка ПО для Perfect World - Бюро разработчиков Zhyk.Ru: создание ботов, снифферов и прочих программ для Perfect World |
21.04.2012, 19:51
|
#1
|
|
|
|
Капитан
|
Регистрация: 24.09.2010
Сообщений: 262
Популярность: 6723
Сказал(а) спасибо: 118
Поблагодарили 346 раз(а) в 104 сообщениях
|
Packet.cs - читаем пакет
Я очень долго хотел выложить что-нибудь интересное, но я некоторое время был заблокирован
Собственно кто-то решил изучить область оог, но у многих, как и у меня, пакет читался очень криво, т.е. код для чтения этого пакета был ужасен и в некоторых моментах становился не понятным
Мне пригляделся класс CPWPacket из наработок ворта, но насколько я помню - он был не полон.
В конце концов я написал свой класс, в который входят следующие методы:
|
Цитата: |
|
|
|
|
|
|
|
|
- GetType() // Возвращает тип текущего пакета
- SetType(uint tp) // Задает тип пакету
- GetLength() // возвращает длинну буфера
- GetShift() // Возвращает значение указателя
- GetBuf() // Возвращает весь буфер
- ReadUString(bool dword(?)) // Читает длину текста(CUI/Dword) и возвращает сам текст
- WriteUString(string text, bool dword(?)) // Записывает длину текста и сам текст в Unicode
- ReadAString(bool dword(?)) // Читает текст в формате ANCII
- WriteAString(string text, bool dword(?)) // Записывает длину и текст в формате ANCII
- WriteData(byte[] buf, bool dword(?)) // записывает длину данных(CUI/Dword), а потом сами данные
- ReadData(bool dword(?)) // Читает длину данных и возвращает эти данные
- ReadCUInt32() // Возвращает значение CUI
- WriteCUInt32(uint value) // Записывает значение CUI
- ReadTime(bool swap(?)) // Читает дату и время(swap - флаг(перевернуты ли байт))
- WriteFloat(float value, bool swap(?)) // Записывает значение Float(Single)
- ReadFloat(bool swap(?)) // Читает значение Float(Single)
- ReadInt32(bool swap(?)) // Читает значение Int32
- WriteInt32(int value, bool swap(?)) // Записывает значение Int32
- ReadDword(bool swap(?)) // Читает значение Dword
- WriteDword(uint value, bool swap(?)) // Записывает значение Dword
- ReadWord(bool swap(?)) // Читает значение Word
- WriteWord(ushort value, bool swap(?)) // Записывает значение Word
- WriteArray(byte[] buf, bool swap(?)) // Записывает массив байт в буфер
- ReadArray(uint length, bool swap(?)) // Читает массив байт из буфера
- WriteByte(byte bt(?)) // Записывает байт(если аргументов 0, то записывается просто нулевой байт)
- ReadByte() // Читает 1 байт
|
|
|
|
|
|
Например нам надо прочитать пару байт, дворд и CUI:
PHP код:
Packet P;
byte[] bt = P.ReadArray(2);
uint dword = P.ReadDword();
uint cui = P.ReadCUInt32();
Исходник
PHP код:
using System;
using System.Collections.Generic;
using System.Text;
namespace OOGLibrary
{
public class Packet
{
public Packet()
{
SetType(00);
}
public Packet(uint type)
{
SetType(type);
}
List<byte> buffer = new List<byte>();
uint shift = 0;
uint packtype = 0;
public uint GetType()
{ return packtype; }
public void SetType(uint tp)
{ packtype = tp; }
public uint GetLength()
{ return (uint)buffer.Count; }
public uint GetShift()
{ return shift; }
public byte[] GetBuf()
{ return buffer.ToArray(); }
public string ReadUString()
{
return Encoding.Unicode.GetString(ReadData());
}
public void WriteUString(string text)
{
WriteData(Encoding.Unicode.GetBytes(text));
}
public string ReadAString()
{
byte[] data = ReadData();
return Encoding.ASCII.GetString(data);
}
public void WriteAString(string text)
{
WriteData(Encoding.ASCII.GetBytes(text));
}
// dword/
public string ReadUString(bool dword)
{
return Encoding.Unicode.GetString(ReadData(dword));
}
public void WriteUString(string text, bool dword)
{
WriteData(Encoding.Unicode.GetBytes(text), dword);
}
public string ReadAString(bool dword)
{
return Encoding.ASCII.GetString(ReadData(dword));
}
public void WriteAString(string text, bool dword)
{
WriteData(Encoding.ASCII.GetBytes(text), dword);
}
// /dword
public void WriteData(byte[] buf)
{
WriteCUInt32((uint)buf.Length);
WriteArray(buf);
}
public byte[] ReadData()
{
uint length = ReadCUInt32();
return ReadArray(length);
}
public DateTime ReadTime()
{
return ReadTime(false);
}
public DateTime ReadTime(bool swap)
{
uint value = ReadDword(!swap);
return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(value).AddHours(4);
}
public void WriteData(byte[] buf, bool dword)
{
if (!dword)
{
WriteData(buf);
return;
}
WriteDword((uint)buf.Length);
WriteArray(buf);
}
public byte[] ReadData(bool dword)
{
if(!dword)return ReadData();
uint length = ReadDword();
return ReadArray(length);
}
public uint ReadCUInt32()
{
byte code = ReadByte();
switch (code & 0xE0)
{
case 0xE0:
return BitConverter.ToUInt32(ReadArray(4, true), 0);
case 0xC0:
byte[] bt = ReadArray(3, true);
return BitConverter.ToUInt32(new byte[] { bt[2], bt[1], bt[0], code }, 0) & 0x1FFFFFFF;
case 0x80:
case 0xA0:
return (uint)(BitConverter.ToUInt16(new byte[] { ReadByte(), code }, 0) & 0x3FFF);
}
return (uint)code;
}
public byte[] WriteCUInt32(uint value)
{
if (value <= 0x7F)
{
WriteByte((byte)value);
return new byte[] { (byte)value };
}
if (value <= 0x3FFF)
{
byte[] bt = BitConverter.GetBytes((ushort)(value + 0x8000));
Array.Reverse(bt);
WriteArray(bt);
return bt;
}
if (value <= 0x1FFFFFFF)
{
byte[] bt = BitConverter.GetBytes((uint)(value + 0xC0000000));
Array.Reverse(bt);
WriteArray(bt);
return bt;
}
if (value <= 0xFFFFFFFF)
{
List<byte> bt = new List<byte>();
bt.Add(0xE0);
byte[] arrbt = BitConverter.GetBytes((uint)value);
Array.Reverse(arrbt);
bt.AddRange(arrbt);
WriteArray(bt.ToArray());
return bt.ToArray();
}
return new byte[0];
}
public void WriteFloat(float value, bool swap)
{
byte[] bt = BitConverter.GetBytes(value);
WriteArray(bt, swap);
}
public float ReadFloat(bool swap)
{
byte[] bt = ReadArray(4, swap);
return BitConverter.ToSingle(bt, 0);
}
public void WriteFloat(float value)
{
WriteFloat(value, false);
}
public float ReadFloat()
{
return ReadFloat(false);
}
public int ReadInt32()
{
return ReadInt32(false);
}
public int ReadInt32(bool swap)
{
return BitConverter.ToInt32(ReadArray(4, swap), 0);
}
public void WriteInt32(int value)
{
WriteInt32(value, false);
}
public void WriteInt32(int value, bool swap)
{
WriteArray(BitConverter.GetBytes(value), swap);
}
public void WriteDword(uint value)
{
WriteArray(BitConverter.GetBytes(value));
}
public void WriteDword(uint value, bool swap)
{
WriteArray(BitConverter.GetBytes(value), swap);
}
public void WriteWord(ushort value)
{
WriteArray(BitConverter.GetBytes(value));
}
public void WriteWord(ushort value, bool swap)
{
WriteArray(BitConverter.GetBytes(value), swap);
}
public uint ReadDword()
{
return BitConverter.ToUInt32(ReadArray(4),0);
}
public uint ReadDword(bool swap)
{
return BitConverter.ToUInt32(ReadArray(4, swap),0);
}
public ushort ReadWord()
{
return BitConverter.ToUInt16(ReadArray(2),0);
}
public ushort ReadWord(bool swap)
{
return BitConverter.ToUInt16(ReadArray(2, swap),0);
}
public void WriteArray(byte[] buf)
{ WriteArray(buf, false); }
public void WriteArray(byte[] buf, bool swap)
{
if (swap) Array.Reverse(buf);
for (int i = 0; i < buf.Length; i++)
WriteByte(buf[i]);
}
public byte[] ReadArray(uint length)
{ return ReadArray(length, false); }
public byte[] ReadArray(uint length, bool swap)
{
byte[] ret = new byte[length];
for (int i = 0; i < length; i++)
ret[i] = ReadByte();
if (swap) Array.Reverse(ret);
return ret;
}
public void WriteByte()
{
WriteByte(0x00);
}
public void WriteByte(byte bt)
{
buffer.Add(bt);
}
public byte ReadByte()
{
if (shift >= buffer.Count)
{
Console.WriteLine("shift >= buffer.Count");
return 0x00;
}
byte ret = buffer[(int)shift];
shift++;
return ret;
}
}
}
|
|
|
Пользователь сказал cпасибо:
|
|
21.04.2012, 21:13
|
#2
|
|
|
|
Разведчик
|
Регистрация: 14.12.2009
Сообщений: 7
Популярность: 179
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
|
Re: Packet.cs - читаем пакет
а наша наука дошла до следующего
Обявлениее пакета:
Код:
class MoveStopImpl
{
public:
enum { ID = 0x0007 };
Coord3D pos;
byte orientation;
byte moveType;
WORD seqNum;
byte chkSum, qIdx;
WORD speed;
protected:
template<int mode> void format(Serializer<mode> & s)
{
s.fr(pos.x_).fr(pos.z_).fr(pos.y_)
.wr(speed).b(orientation).b(moveType)
.wr(seqNum).b(chkSum).b(qIdx);
}
};
typedef FragmentGiSpec<MoveStopImpl> FragmentGiMoveStop;
собственно, для описания пакета больше ничего не нужно. Весь остальной код работает чисто с этим классом, а раскладыванием пакетов занимаются две отдельные фабрики. Плюс объявление работает в обе стороны - т.е. пакет как и разбирается по этим правилам, так и может быть собран обратно в массив байт.
Магия С++
|
|
|
21.04.2012, 22:01
|
#3
|
|
|
|
Главнокомандующий
|
Регистрация: 20.01.2010
Сообщений: 1,539
Популярность: 22780
Золото Zhyk.Ru: 600
Сказал(а) спасибо: 43
Поблагодарили 1,717 раз(а) в 538 сообщениях
|
Re: Packet.cs - читаем пакет
|
Цитата: |
|
|
|
|
|
|
|
|
|
собственно, для описания пакета больше ничего не нужно. Весь остальной код работает чисто с этим классом, а раскладыванием пакетов занимаются две отдельные фабрики. Плюс объявление работает в обе стороны - т.е. пакет как и разбирается по этим правилам, так и может быть собран обратно в массив байт.
Магия С++
|
|
|
|
|
|
Магия прямых рук
Сами имеем схожую систему чтения / обработки пакетов.
Хочется обратить внимание тех, кто читает эту тему, что данный подход является чертовски правильным и ничего лучше пока никто не придумал
Не следует мешать в кучу пакет, как сущность и поток данных, который вычитываем. Разделение наглядно видно в приведенном во 2ом посте коде.
Последний раз редактировалось Kitsune; 21.04.2012 в 22:03.
|
|
|
22.04.2012, 16:50
|
#4
|
|
|
|
Капитан
|
Регистрация: 24.09.2010
Сообщений: 262
Популярность: 6723
Сказал(а) спасибо: 118
Поблагодарили 346 раз(а) в 104 сообщениях
|
Re: Packet.cs - читаем пакет
Интересно, но не очень понятно
Т.е.
Код:
Packet P;
byte[] bt = P.ReadArray(2);
uint dword = P.ReadDword();
uint cui = P.ReadCUInt32();
Можно записать как:
Код:
byte[] bt = new byte[2];
uint dword;
uint cui;
public void Read(Packet P)
{
P.ReadArray(bt).ReadDword(dword).ReadCUInt32(cui);
}
Я так понимаю?)
|
|
|
22.04.2012, 17:15
|
#5
|
|
|
|
Главнокомандующий
|
Регистрация: 20.01.2010
Сообщений: 1,539
Популярность: 22780
Золото Zhyk.Ru: 600
Сказал(а) спасибо: 43
Поблагодарили 1,717 раз(а) в 538 сообщениях
|
Re: Packet.cs - читаем пакет
|
Цитата: |
|
|
|
|
|
|
|
|
|
но не очень понятно
|
|
|
|
|
|
Видимо совсем не понятно
Пакет, это результат чтение данных из потока, а не средство для чтения данных.
Иными словами:
Код:
класс пакет1
{
тип1 свойство1 { get; set; }
тип2 свойство2 { get; set; }
тип3 свойство3 { get; set; }
конструктор {}
метод читать(поток птк)
{
свойство1 = птк.ЧитатьТип1();
свойство2 = птк.ЧитатьТип2();
свойство3 = птк.ЧитатьТип3();
}
метод писать(поток птк)
{
птк.Писать(свойство1);
птк.Писать(свойство2);
птк.Писать(свойство3);
}
}
|
|
|
22.04.2012, 18:05
|
#6
|
|
|
|
Капитан
|
Регистрация: 24.09.2010
Сообщений: 262
Популярность: 6723
Сказал(а) спасибо: 118
Поблагодарили 346 раз(а) в 104 сообщениях
|
Re: Packet.cs - читаем пакет
|
Цитата: |
|
|
|
|
|
|
|
|
|
Пакет, это результат чтение данных из потока, а не средство для чтения данных.
|
|
|
|
|
|
Я через отдельный метод записываю каждый полученный байт, а этот метод создает пакет(Packet)(записывает тип, длинну, а потом данные пакета), разделяет эти байт, и передает его через евент
Далее я уже читаю из этого Packet все нужные мне данные и создаю другой пакет
Иными словами:
Код:
public void WriteByte(byte bt)
{
try
{
if (!CheckCUInt32(bttype.ToArray()))
{
bttype.Add(bt);
return;
}
if (!CheckCUInt32(btlen.ToArray()))
{
btlen.Add(bt);
if (CheckCUInt32(btlen.ToArray()))
{
len = ReadCUInt32(btlen.ToArray());
if (len > 0) return;
}
else
return;
}
if (btbuf.Count < len) btbuf.Add(bt);
if (btbuf.Count == len)
{
uint type = ReadCUInt32(bttype.ToArray());
byte[] buf = btbuf.ToArray();
Packet P = new Packet();
P.SetType(type);
P.WriteArray(buf);
btbuf.Clear();
bttype.Clear();
btlen.Clear();
len = 0;
client.Read(P);
if(P.GetType() == 0x00)
{
Packet[] Packs = GetContainer(P);
for (int i = 0; i < Packs.Length; i++)
client.ReadContainer(Packs[i]);
}
}
}
catch { }
}
Добавлено через 3 часа 54 минуты
Видимо я правильно понял)
В примере Slik переменная s - класс пакета
Метод fr(FloatRead) на C# мог бы выглядеть вот так:
public Packet fr(out float value)
{
value = BitConverter.ToSingle(ReadArray(4));
return this;
}
Последний раз редактировалось FreePVP))); 22.04.2012 в 21:59.
Причина: Добавлено сообщение
|
|
|
23.04.2012, 11:49
|
#7
|
|
|
|
Главнокомандующий
|
Регистрация: 20.01.2010
Сообщений: 1,539
Популярность: 22780
Золото Zhyk.Ru: 600
Сказал(а) спасибо: 43
Поблагодарили 1,717 раз(а) в 538 сообщениях
|
Re: Packet.cs - читаем пакет
|
Цитата: |
|
|
|
|
|
|
|
|
|
В примере Slik переменная s - класс пакета
|
|
|
|
|
|
В примере silk'a
MoveStopImpl - класс пакета
Serializer<mode> & s - его реализация потока данных (скорее всего)
|
|
|
24.04.2012, 00:25
|
#8
|
|
|
|
Разведчик
|
Регистрация: 14.12.2009
Сообщений: 7
Популярность: 179
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
|
Re: Packet.cs - читаем пакет
ну как-то так, да. Более того, само описание фрагмента задает формат для содержимого фрагмента, а ответственность за форматирование контейнеров, 00-22, и прочих деталях находятся в других похожих местах. Более того, с помощью такого описания контролируется и необходимая длина данных для формирования фрагмента при помощи специального сериализатора, который только считает длину
Добавлено через 4 минуты
ну и потом, можно делать более веселые штуки, например такие
Код:
class PlayerPurchaseItemImpl
{
public:
enum { ID = 0x0048 };
struct Item
{
DWORD id;
DWORD unk;
WORD count;
WORD slot;
byte tradeSlot; // tradeSlot is a slot in market list of <22><A9>.
// Slots are not reordered after sell/buy.
template<int mode> void format(Serializer<mode> & s)
{
s.lr(id).lr(unk).wr(count).wr(slot).b(tradeSlot);
}
};
DWORD moneyLost;
DWORD unk;
BYTE unk2;
std::vector<struct Item> items;
protected:
template<int mode> void format(Serializer<mode> & s)
{
s.lr(moneyLost).lr(unk).b(unk2).arr(items, &Serializer<mode>::wr);
}
};
Последний раз редактировалось silk; 24.04.2012 в 00:29.
Причина: Добавлено сообщение
|
|
|
26.04.2012, 18:53
|
#9
|
|
|
|
Разведчик
|
Регистрация: 17.09.2009
Сообщений: 46
Популярность: 1187
Сказал(а) спасибо: 8
Поблагодарили 50 раз(а) в 13 сообщениях
|
Re: Packet.cs - читаем пакет
|
Цитата: |
|
|
|
|
|
|
|
|
|
Пакет, это результат чтение данных из потока, а не средство для чтения данных.
|
|
|
|
|
|
Эммм... Вопросик Вам - а чего бы не инкапсулировать туда же логику обработки данного пакета ?
В противном случае не вижу профита плодить десятки классов на каждый пакет, учитывая, что нужно он один единственный раз - получить его из потока. Дальше его данные обрабатываются и пакет освобождается.
При таком раскладе пакет - как средство чтения и десериализации данныых - самое то. Вот как-то так :
Код:
procedure TCharacterController.HandleS00_105RoleLockInfo(pck : TSubPacket);
var
b : byte;
begin
// byte - lock status (0=disabled, 1=enabled)
b := pck.ReadByte();
if b = 1 then self._locked := true else self._locked := false;
// dword - lock end timestanmp
self._lockEndTimestamp := pck.ReadDword();
// dword - lock duration
self._lockDuration := pck.ReadDword();
end;
учитывая, что TSubPacket сделан по аналогии с классом автора.
Последний раз редактировалось vogel; 26.04.2012 в 20:59.
|
|
|
27.04.2012, 10:28
|
#10
|
|
|
|
Разведчик
|
Регистрация: 14.12.2009
Сообщений: 7
Популярность: 179
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
|
Re: Packet.cs - читаем пакет
ну как минимум, потребность обработать один и тот же пакет в двух разных местах поставит вас в неудобное положение.
|
|
|
27.04.2012, 11:55
|
#11
|
|
|
|
Разведчик
|
Регистрация: 17.09.2009
Сообщений: 46
Популярность: 1187
Сказал(а) спасибо: 8
Поблагодарили 50 раз(а) в 13 сообщениях
|
Re: Packet.cs - читаем пакет
Для этого есть ивенты и их хэндлеры =)
|
|
|
27.04.2012, 20:17
|
#12
|
|
|
|
Капитан
|
Регистрация: 24.09.2010
Сообщений: 262
Популярность: 6723
Сказал(а) спасибо: 118
Поблагодарили 346 раз(а) в 104 сообщениях
|
Re: Packet.cs - читаем пакет
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Похожие темы
|
Тема |
Автор |
Раздел |
Ответов |
Последнее сообщение |
[Руководство] Изучаем l2 Packet Hack
|
HellFire |
Переводы |
2 |
25.09.2016 18:51 |
[Программа] Packet Monitor
|
TeedI |
Разработка ПО для Perfect World |
4 |
02.01.2012 00:01 |
L2 Packet Hack 3.5.33.163
|
jokerbad |
Общение и обсуждение, архив Lineage 2 |
0 |
01.11.2010 15:45 |
Заявление об ответственности / Список мошенников
Часовой пояс GMT +4, время: 02:28.
|
|