|
Опкоды, Формулы, Клиент Разбор и изучение взаимодействия клиента с сервером |
|
Опции темы | Поиск в этой теме | Опции просмотра |
20.07.2010, 18:34 | #1 |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Централизованый формат снифов
Редакция от 31 июля 2011, 13:13, версия 3.1
Редакция от 25 июля 2010, 21:00, версия 3.0
Предложения SnifferID: Код:
0 - Wad // 2005 и ранее 1 - Nomad // 2005 и ранее 2 - WoWCore // 2006 3 - Mangos (TOM_RUS) // 2006 4 - User456 // 2007 5 - Delfin // 2007 6 - Burlex // 2007 7 - WCell // 2008 8 - Kobold // 2009 9 - abdula123 // 2010 10 - Konctantin/LordJZ // 2010 11 - Йоха // 2010 Последний раз редактировалось RomanRom2; 07.08.2011 в 21:24. |
23.07.2010, 12:26 | #2 |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Вот появилось свободное время, и хотелось бы продолжить дискуссию.
Мне как-то не очень понравилась мысль о создании своего формата снифа. Лучше немножко доработать существующий. Сразу объясню почему: 1) Зачем плодить кучу форматов, потом писать конвертеры, потом опять чего-то. Это все лишний код. 2) Хоть снифы и не нужны широкому кругу пользователей, да и используются фактически только в определенными людьми, позиция многоформатности теряет свой смысл. Свой собственный формат следует вводить только в том случае, если хочется кардинально выделить свой "продукт" и сделать его "уникальным". В нашем случае это ненужно. Я изначально за обобщенный, централизованный формат. Давайте в этой тебе оставим свои "за" и "против" и согласуем надо а что не надо. Саму архитектуру формата можно разделить на 3 уровня: 1. Имя файла 2. Заголовок 3. Тело 1) Как уже говорил RomanRom2, имя файла должно носить информационных характер. Код:
[build]_[datetime(yyyy-MM-dd_HH-mm-ss-ffff)]_[SessionIndex]_[LogIndex]_[RealmIP].[pkt | raw] FirstClientOpcode - я даже не знаю, по большему счету будет всего 2 варианта, или же это CMSG_AUTH_SESSION или CMSG_REDIRECTION_AUTH_PROOF и особой информационной составляющей не носит, так как у меня раз получилось 4 сессии фактически вышло получилось бы следующее: Код:
ххх_CMSG_AUTH_SESSION_ххх ххх_CMSG_REDIRECTION_AUTH_PROOF_ххх ххх_CMSG_REDIRECTION_AUTH_PROOF_ххх ххх_CMSG_REDIRECTION_AUTH_PROOF_ххх почему так спросите вы? отвечу, наша прокси позволяет включать и выключать логирование трафика и SessionIndex в данном случае это номер сессии, а LogIndex это порядковый номер лога. (это опционально, но желательно, если запись в отдельный файл), правда в этом случае FirstClientOpcode уже будут разные. 2) Заголовок, я думаю вполне хватит и вот этого: Код:
[PKT | RAW] Version ClientBuild ClientLanguage SessionKey 3) и само тело снифа. Код:
(byte)Direction; (uint)UnixTime (uint)TickCount (uint)Opcode (byte)Flags // для того чтобы выделять что это за пакет (опционально, тоже можно договорится о спецификации) (uint)Data.Length (byte[])Data |
23.07.2010, 12:31 | #3 |
MaNGOS Dev
Регистрация: 11.03.2010
Сообщений: 468
Сказал(а) спасибо: 0
Поблагодарили 514 раз(а) в 163 сообщениях
|
Писать разные сессии в отдельнный файл очень не удобно. Теоретически это одна сессия, и все пакеты в ней взаимосвязаны. В таком случае теряется последовательность пакетов, а она для меня очень важна.
|
23.07.2010, 22:20 | #5 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
выскажусь и я.
согласен с "архитектурой": 1. Имя файла 2. Заголовок 3. Тело итак, давайте рассматривать потенциальный будущий формат 3.0; 1. === имя файлы, как я уже говорил - носит рекомендательный характер. по этому пункту мы скорее всего не договоримся, тут почему то кому что нравится. но позволю себе высказаться по этому поводу. за 5 лет снифанья и использования снифов выработались следующие ... "пожелания", назовем это так. визуально удобно, когда при вгляде на файлы идентифицируется сразу: - билд клиента - откуда снифф, название реалма. при некоторых обстоятельствах, но по факту почти не нужно. - что бы снифы все располагались по порядку - поле "имя аккаунта" реально не пригодилось. итак, что получается: 12604_4C497974.PKT теперь поговорим о формате "дата снифа". опять же, опираясь на опыт прошлых лет, полная читабельная дата в имени файла вроде yyyy-MM-dd_HH-mm-ss-ffff нафиг не нужна. по трем причинам как минимум: - дату файла можно посмотреть у самого файла. обычно эти даты совпадают - смотреть на файлы и видеть дату реально не пригодилось. важнее вот билдом клиента больше всего оперируем при обработке. например сразу видно, что вот эти сниффы будет парсить вот этим снифером. не важно какая дата снифов. - ну длиновато имя файла получается единственная цель в поле "дата" - для сортировки файлов в файловых панелях (far, tc, проводник, кто чем еще пользуется). реально больше ни для чего не нужно оказалось. в связи с вышесказанным считаю запись UnixDateTime(Now) самой оптимальной. к слову сказать, это повелось еще во времена динозавров - такое поле использовал еще wad в своем снифере но это так, лирическое отступление. поле "имя реалма" сейчас не просто доставать, да и по факту оно редко когда нужно. а адрес:порт реалма сейчас у меня лишь для небольшой статистики. я уберу. дальше, есть ньюанс с номером сессии. тут два возможных варианта: - мы пишем все сессии в один файл и не паримся с этим - мы каждую сессию пишем в отдельный файл и придется как то помечать файлы. почему? вторая сессия может быть начата в ту же секунду что и первая и тогда имя файла для второй сессии будет одинаковым. т.е. получается что то вроде такого тогда: 12604_4C497974_[1].PKT 12604_4C497974_[2].PKT именно по этой причине в имени файла у меня появились номера опкодов. я просто посчитал что это гораздо прикольней, чем просто 1, 2, ... 12604_4C497974_[01ED].PKT 12604_4C497974_[0512].PKT и поскольку у нас всего два (в последнем катаклизме три) варианта, мы прекрасно знаем, что 01ED - первая сессия и обычно не несет в своем сниффе никакой полезной информации и я такие снифы просто удаляю. а 0512 - вторая сессия, которая нам и нужна. кстати, со временем оказалось, что есть еще одна полезная фишка с записью опкода в имя файла: на катаклизме как вы знаете сейчас часто меняют опкоды. в общем это теперь сразу видно и сразу видно на что именно поменяли в этом билде не надо открывать снифф и искать там. по поводу SessionIndex_LogIndex. собственно опкод это и есть SessionIndex, а LogIndex честно говоря не знаю - зачем делать разные файлы для одной сессии. ну раз такое нужно, что ж, ничего в этом такого нет - делайте. и помечайте. получится что то вроде: 12604_4C497974_[01ED].PKT 12604_4C497974_[0512_1].PKT 12604_4C497999_[0512_2].PKT 12604_4C499376_[0512_3].PKT ... только смысла опять же не очень понимаю. время ведь тоже меняется. в общем по первому пункту (имя файла), как я уже сказал, мы скорее всего не договоримся. но повторюсь - вышесказанное есть мое видение и предложение, поддержанное пятилетним опытом работы со снифами. наверное никто так много и долго с этим делом не работал единственно о чем мы должны договориться, это о расширении файла. многие редакторы фильтруют файлы по расширению. в общем предлагаю очевидные .raw и .pkt 2. === по второму пункту полностью поддерживаю. к существующему заголовку версии 2.1 нужно добавить только ClientLanguage. оно реально нужно для автоматического определения языка при парсинге респонсов. 3 байта: [PKT | RAW] 2 байта: Version 2 байта: ClientBuild 4 байта: ClientLanguage. варианты [enUS] [enGB] [ruRU], т.е. прям с клиентского пакета (они там наоборот, SUne, BGne, URur). 40 байт: SessionKey но хочу предложить сюда, скажем, 8 байт DevelopersData 3 байта: [PKT | RAW] 2 байта: Version 2 байта: ClientBuild 4 байта: ClientLanguage 8 байт: DevelopersData 40 байт: SessionKey пусть сюда каждый разработчик складывает все что ему хочется, что ему удобно. и это поле не поддается какому либо форматированию. да и вообще, FutureFields можно сказать. поле является обязательным (наличие), но требований к полю нет никаких. такой вот прикол 3. === данные. заголовок каждого чанка данных: предложенная структура (byte)Direction; (uint)UnixTime (uint)TickCount (uint)Opcode (byte)Flags (uint)Data.Length (byte[])Data от текущей отличается выделенными полями. два вопроса: 1. зачем в заголовке опкод? он ведь в самом чанке. плюс у raw мы не можем знать опкод. 2. для чего поле Flags? я просто предлагаю здесь ничего не менять. инфы более чем достаточно. |
23.07.2010, 22:38 | #6 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
Ну Flags у нашего сниффера только требуется (вроде я не видел больше), а опкод у нас отдельно выделен, не в самом чанке он — не удобно нам по-другому. Просто в коде неудобно.
Еще я у себя храню SessionLength — время сессии в секундах, и PacketCount. Последний для корректного чтения пакетов, чтобы в конец файла можно было вдруг, если понадобится, подпись. |
23.07.2010, 22:52 | #7 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
ну так ответов на вопросы нет.
1. зачем опкод? в данном случае вопрос по другому: в чем неудобство опкода в чанке? я просто рассматриваю чанк как - опкод - данные, соответствующие этому опкоду т.е. вполне закономерно и логически законченная сущность. чанк. задумайтесь а размер чанка - в заголовке. по этому полю в заголовке удобно "пробегать" по снифу. 2. для чего флаг чанка? что там в нем? какие флаги бывают? для чего используются? я вот сейчас придумал пока писал это сообщение, что чанку можно прибавить поле в 1 байт SessionIndex. оно возможно нужно при условии, что все сессии пишутся в один снифф. без чего сейчас не может жить TOM_RUS ну и действительно, было бы удобно смотреть что в какой момент отправлено в какую сессию. а если в будущем близзы сделают несколько сессий, то поле просто необходимо будет. в общем это нужно предварительно решить, в один снифф мы сессии пишем или в разные. |
23.07.2010, 23:00 | #8 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
У опкода разная длина, плюс мы между модулями сниффа переносим чистые данные, без опкодов, поэтому и пишем в лог чистые данные. А чтобы читать чанк с опкодом, нужно знать направление пакета, прочитать опкод нужной длины, а затем данные. И зачем? Гораздо проще прочитать 4 байта опкода (учитывая, что сейчас 2 байта из них не используются вообще) и потом уже Х байт чистых данных.
Флаги у нас сейчас такие: 0x01 — пакет был создан искусственно, и подставной отправитель о нем не знает 0x02 — пакет был остановлен искусственно, и получатель его не принял 0x04 — пакет был вытащен из хвоста другого пакета (таких 85%) 0x08 — пакет был получен по-частям |
23.07.2010, 23:18 | #10 | |||
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
Цитата:
тем более непонятна следующая вещь: ну вот к примеру я, прежде чем работать с опкодом, читаю заголовок. ПОЛНОСТЬЮ. соответственно с направлением и вообще со всеми атрибутами. а вы как то частично его читаете? ну хорошо. допускаю, что заголовок чанка можно привести к формату: (byte)Direction; (uint)UnixTime (время) (uint)TickCount (точное время) (uint)Data.Length (длина Data, опкод сюда не входит. или входит???) (uint)Opcode (для RAW тут FFFFFFFF) (byte[])Data (данные без опкода) возможно это действительно немного удобнее и универсальней, в плане выравнивания полей. я за выравнивание. и за такой вот на мой взгляд логический порядок полей. Цитата:
может быть такой тип данных и в чанк включить? 4х байт нам хватит? Цитата:
тоже не знаю зачем оно вам так необходимо, когда эти данные можно легко прямо со снифа считать просто не придумаю, где оно мне могло бы пригодится... добавлено: вот сейчас подумал, что DevelopersData чисто информативные поля. например если вы сюда будете складывать жизненноважные данные, то например мои снифы не сможете обработать/распарсить. например если вы каким то специальным образом обрабатываете пакеты с флагом то я такие пакеты просто не помечаю. я его собираю весь на этапе первого куска и сюда же и складываю в снифф. т.е. например: - C.пакеты - S.пакеты - S.01F6 жирный. но от него пришел то кусочек 1420 байт. бегу по всему снифу и собираю все все все куски и складываю в pkt уже готовый и полный пакет. а все те пакеты, которые встречались пока я собирал эти недостающие куски в pkt будут записаны позже. так работает мой декодер raw-to-pkt. т.е. если вам очень нужны такие пакеты, то у меня их просто не будет. кстати, а зачем они вам потом в готовом pkt? мне вот снифы нужны для: - наполнения базы респонсов, справочников и т.п., где нужны полностью собранные и законченные пакеты. - наполнения заселения. тут я парсю пакеты А9 по сути только. - ну и конечно же посмотреть, в какой последовательности что когда отсылается, для реализации какой либо системы. тоже не вижу, зачем нужно знать, что конкретно этот 01F6 был "вытащен из хвоста другого пакета" ну серьезно расскажите? мне интересно. Последний раз редактировалось RomanRom2; 23.07.2010 в 23:32. |
|||
23.07.2010, 23:18 | #11 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
А зачем? Тем более, что в нашей реализации этого тупо не получится сделать
|
23.07.2010, 23:21 | #12 | |||
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
Цитата:
Цитата:
Цитата:
|
|||
23.07.2010, 23:43 | #13 | ||||
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
Цитата:
Цитата:
Цитата:
Цитата:
у меня вот очень просто все, пока есть данные в файле, я их читаю. если чтото завершилось с ошибкой (чтение заголовка или чтение уже данных), я такой чанк вообще не обрабатываю. и заканчиваю обработку вообще, т.к. обычно это случается в момент END_OF_FILE. ну сложите вы количество пакетов. ну будете их проверять каждый раз. по моему лишняя головная боль. это выглядит как защита, но от чего? |
||||
23.07.2010, 23:45 | #14 | |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Цитата:
|
|
23.07.2010, 23:47 | #15 | |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Цитата:
это можно сделать, правда с реконструкцией, а то наша система "немножко" зависит от самих коннектов. Для каждого соединения создаются свои экземпляры |
|
23.07.2010, 23:51 | #16 | ||
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
Это я Konctantin отвечал, до того как вы свой пост отправили...
Цитата:
Цитата:
|
||
24.07.2010, 00:07 | #17 | ||||
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
Цитата:
Цитата:
у меня сейчас тоже так же, свои экземпляры. но мне кажется это удобнее, чем в один файл писать. на самом деле один файл со всеми сессиями нужно записать только один раз, что бы понять в какой последовательности слать пакеты, что бы реализовать эту фичу у себя на сервере. но задайте честно себе вопрос. а вы правда будете использовать эту фичу у себя на сервере? лично мне и из разных файлов понятно стало, что когда слать и что когда ожидать. ну это в общем личное. Цитата:
Цитата:
смотрите: - в вашем случае лишние данные, их подсчет, запись, потом их чтение. опять подсчет при чтении, сравнение. ну и что делать, если вдруг они не совпадут? реально (к примеру) один байт в конце потерялся, у последнего чанка. а снифф 50 мегов. все в помойку? - в моем случае читаем до тех пор, пока не возникнет END_OF_FILE. всё |
||||
24.07.2010, 00:12 | #18 | ||
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
Цитата:
Цитата:
|
||
25.07.2010, 00:36 | #20 |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
итог на сегодня, текста много, а результата так и не видно... пора уже бы и договорится...
А то получается как у нас в стране, обсуждения и базара много, а результата 0... так что господа, давайте подобьем итоги, и придем к какому-то консенсусу. формат: 1) имя (мы ни к чему не договоримся, да и на чтение файла это не повлияет) по этому оставим как есть, пусть каждый пишет что хочет, но давайте оставим расширения файлов [PKT | RAW]. 2) вариант: Код:
[PKT | RAW] Version ClientBuild ClientLanguage DevelopersData SessionKey 3) Код:
(byte)Direction; (uint)UnixTime (uint)TickCount (uint)Opcode (byte)ChunkDevelopersData (uint)Data.Length (byte[])Data Если ответа не будет, то думаю можно закончить данную дискуссию и утвердить данный формат (результат в 1 пост). ЗЫ. Если мы столько будем споить и принимать решения, то позор нам всем, и никогда жить в нашей стране хорошо (я про весь СНГ) мы не будем, так как наш менталитет нам этого не даст.. |
25.07.2010, 15:49 | #21 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
ок. по пунктам:
1. согласен. имя файла - на свое усмотрение. расширение файла обязательно либо .pkt либо .raw. 2. Header, bytes[3] (R,A,W; P,K,T HeaderVersion, word (3.0) ClientBuild, uint, (число) ClientLanguage, uint DevelopersData, uint64 SessionKey, bytes[40] несколько слов о полях: - HeaderVersion. в дампе это должно выглядеть "младший байт, старший байт", т.е. так: Код:
0000000000: 50 4B 54 00 03 CB 2D 89 │ 9D 6F C4 9B 85 20 75 6D PKT☺☻╦-ЙЭo─ЫЕ um 3. (byte) Direction; для серверных чанков 0хFF, для клиентских 0хСС. (uint) UnixTime; UnixDateTime(Now). (uint) TickCount; GetTickCount(); (byte) ChunkDevelopersData; нам точно одного байта хватит? мы же хотели переменную длину заюзать? (uint) PKT.Length; длина данных, ВКЛЮЧАЯ Opcode (uint) PKT.Opcode (byte[]) PKT.Data несколько слов о полях: - ChunkDevelopersData существуют два варианта реализации - с переменной длиной и с фиксированной. лично я за фиксированную длину, читать данные проще. т.е. давайте выберем один из вариантов: 1. (uint64) ChunkDevelopersData (8 байт нам точно должно хватить на долго, учитывая что разработчиков сниферов по пальцем можно пересчитать) 2. (byte) ChunkDevelopersData.Length (bytes[])ChunkDevelopersData.Data второй вариант представляется мне гиморным в плане пробегания по снифу. представьте, что бы прочитать следующий чанк нужно 1. по первому варианту: - прочитать хидер, 1+4+4+8+4+4 байт - прочитать PKT.Data размером PKT.Length-4 байт 2. по второму варианту: - прочитать часть хидера, 1+4+4+1 байт - прочиать ChunkDevelopersData.Data размером ChunkDevelopersData.Length байт - дочитать хидер, 4+4 байт - прочитать PKT.Data размером PKT.Length-4 байт в общем я за первый вариант с фиксированной длиной ChunkDevelopersData. вопрос только в ее длине. 4 или 8 байт? - PKT формат записи пакета я настоятельно предлагаю в естественном и привычном исполнении: - длина, включая опкод - опкод - данные опкода только сделать длину поля опкода не переменной, как сейчас 2 или 4 байт, а фиксированной 4 байта. это позволит вам избежать трудности чтения невыравненных данных (подобный пример у ChunkDevelopersData с переменной длиной). еще предлагаю ввести поле SnifferID в заголовок снифа. все вы прекрасно понимаете, что поля DevelopersData каждой командой могут быть использованы на свое усмотрение. и если бы мы собрали такую информацию, то SnifferID помог бы понять, что именно находится в DevelopersData. и на стадии утверждения документа принять разработать и принять эти ID. ну например: 1 - WoWCore 2 - TOM_RUS 3 - Konctantin, LordJZ and Co. и так далее. теперь по поводу утверждения формата несколько слов. "Если ответа не будет, то думаю можно закончить данную дискуссию и утвердить данный формат". ничего личного, Костя, но так не делают. предлагаю более цивилизованный вариант, как это делается в больших софтверных компаниях, наших, европейских и американских. в кратце обычно план такой: - создается документ, описывающий некую функциональность и удовлетворяющий все стороны. - создается ревью документа с длительностью на какой то срок. скажем, на неделю. вот тут да, можно говорить, если за ревью ничего не было, то документ принимается и присваивается статус "релиз". а у нас пока что первый пункт не выполнен. то что мы долго это обсуждаем - это не долго, поверьте конечно, в бизнес-процессе существуют некие чекпоинты. давайте тоже будет цивилизованными и сделаем их. мое видение такое: - в срок до 31 июля включительно мы должны разработать и утвердить документ, описывающий формат 3.0, который всех бы удовлетворил. - в срок до 7 августа включительно будет проходить ревью документа. - 8 августа состоится релиз документа. - и еще один момент. ревью проводится среди каких то людей. кто у нас будет ревьюить? всем по моему пофигу, кроме 2-3 человек. но все же я хотел бы пригласить на ревью следющих людей: - Konctantin - LordJZ - TOM_RUS - RomanRom2 - VDm - Deamon - Nomad - abdula123 - user456 - Aven - йоха это те люди, которые я знаю, что они сделали в своей жизни снифер, активно его использовали и обрабатывали снифы, в том числе и от других "производителей". приветствуется дополнение списка ревьюверов. на самом деле многие сейчас могут сказать, чо вы ерундой страдаете, что бы создать какой то сраный формат из 10 байт. быстренько обсудили и сделали. давайте попробую ответить: во первых, ключевая фраза "быстренько". вот у нас всё так, быстренько тяп ляп и погнали. нет четких процессов. и потом получается, тут сказал, тут не сказал, тут слышал, тут не слышал. денег уже нет, а дорога еще не построена. а где деньги то? ну и так далее. да, мы в данном случае быть может стреляем из пушки по воробьям, но блин, это нужно делать! во вторых, "быстренько" мы сделать не можем, по очень простой причине - мы не собираемся каждый день вместе в своем офисе. было бы так, все было бы гораздо быстрее и легче. итак, один из финальных вариантов документа. 1. RAW. 1.1. заголовок снифа. - Header, bytes[3] R,A,W - HeaderVersion, word 3.0 Код:
0000000000: 50 4B 54 00 03 CB 2D 89 │ 9D 6F C4 9B 85 20 75 6D PKT☺☻╦-ЙЭo─ЫЕ um число, актуальная на данную сессию версия клиента. билд может быть добыт из VersionInfo экзешника, из бинарных данных экзешника, из сетевого трафика, иными способами - ClientLanguage, uint enGB, ruRU. актуальная на данную сессию локализация клиента. может быть добыта из VersionInfo экзешника, из бинарных данных экзешника, из сетевого трафика, иными способами - DevelopersData, uint64 вспомогательные данные на усмотрение разработчика. это поле не может быть использовано для хранения данных, которые могут влиять на чтение снифа. - SessionKey, bytes[40] ключ текущей сессии. 1.2. заголовок чанка - Direction, byte для серверных чанков 0хFF, для клиентских 0хСС. -UnixTime, uint стандартная функция UnixDateTime(Now). - TickCount, uint стандартная функция GetTickCount(). - ChunkDevelopersData, bytes[8] вспомогательные данные на усмотрение разработчика. это поле не может быть использовано для хранения данных, которые могут влиять на чтение снифа. - RAW.Length, unit длина данных, которые были "пойманы" снифером и подлежат записи в файл. - RAW.Data, bytes[] пойманные данные 2. PKT. 2.1. заголовок снифа. - Header, bytes[3] P,K,T - HeaderVersion, word 3.0 Код:
0000000000: 50 4B 54 00 03 CB 2D 89 │ 9D 6F C4 9B 85 20 75 6D PKT☺☻╦-ЙЭo─ЫЕ um число, актуальная на данную сессию версия клиента. билд может быть добыт из VersionInfo экзешника, из бинарных данных экзешника, из сетевого трафика, иными способами - ClientLanguage, uint enGB, ruRU. актуальная на данную сессию локализация клиента. может быть добыта из VersionInfo экзешника, из бинарных данных экзешника, из сетевого трафика, иными способами - DevelopersData, uint64 вспомогательные данные на усмотрение разработчика. это поле не может быть использовано для хранения данных, которые могут влиять на чтение снифа. - SessionKey, bytes[40] ключ текущей сессии. для PKT может быть равно нулю. 2.2. заголовок чанка - Direction, byte для серверных чанков 0хFF, для клиентских 0хСС. -UnixTime, uint стандартная функция UnixDateTime(Now). - TickCount, uint стандартная функция GetTickCount(). - ChunkDevelopersData, bytes[8] вспомогательные данные на усмотрение разработчика. это поле не может быть использовано для хранения данных, которые могут влиять на чтение снифа. - PKT.Length, unit длина игровых данных, ВКЛЮЧАЯ Opcode. - PKT.Opcode, unit значение опкода, выравненное до 32х бит. - PKT.Data, bytes[] игровые данные опкода |
25.07.2010, 15:58 | #23 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
|
25.07.2010, 16:06 | #25 |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
я со всем согласен http://ru-mangos.ru/showpost.php?p=11319&postcount=21
|
25.07.2010, 16:12 | #26 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
ок, на всякий случай, давайте я выпишу оставшиеся на данный момент нерешенные вопросы, помимо финального варианта документа.
1. - ClientLanguage. раньше это можно было легко вытащить из авторизационного трафика, там был дамп байтов enGB, enUS, буквы прямо. сейчас это переехало соттветственно в батлнет-трафик. в реалм-трафике на сколько я знаю таких данных не ходит. есть мысли, как мы будем добывать эту информацию? 2. - ChunkDevelopersData существуют два варианта реализации - с переменной длиной и с фиксированной. лично я за фиксированную длину, читать данные проще. т.е. давайте выберем один из вариантов 3. - PKT формат записи пакета я настоятельно предлагаю в естественном и привычном исполнении: - длина, включая опкод - опкод - данные опкода 4. еще предлагаю ввести поле SnifferID в заголовок снифа. все вы прекрасно понимаете, что поля DevelopersData каждой командой могут быть использованы на свое усмотрение. и если бы мы собрали такую информацию, то SnifferID помог бы понять, что именно находится в DevelopersData. и на стадии утверждения документа принять разработать и принять эти ID. ну например: 1 - WoWCore 2 - TOM_RUS 3 - Konctantin, LordJZ and Co. и так далее. |
25.07.2010, 16:24 | #27 | ||
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Цитата:
Цитата:
|
||
25.07.2010, 16:24 | #28 | |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
Оформил.
Цитата:
1) Пока нету. В нашей реализации я не представляю, как это делать 2) Давайте с фиксированной. Плюс, не надо аж 8 байт к каждому пакету. 2 хватит, имхо. В моей цитате стоит word. 3) Согласен 4) Согласен |
|
25.07.2010, 16:29 | #29 | |||
Новичок
Регистрация: 25.05.2010
Сообщений: 11
Сказал(а) спасибо: 1
Поблагодарили 14 раз(а) в 5 сообщениях
|
Цитата:
серверов и сниферов звучит несерьезно Цитата:
Цитата:
|
|||
Пользователь сказал cпасибо: | LordJZ (25.07.2010) |
25.07.2010, 16:31 | #30 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
В случае не фиксированной длины DevelopersData, сами эти данные имхо лучше засунуть в самый конец заголовка файла/чанка, чтобы была возможность читать структурами, а уже потом вручную дочитывать динамические данные.
|
25.07.2010, 16:39 | #31 | |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Цитата:
|
|
25.07.2010, 16:44 | #32 |
Новичок
Регистрация: 31.03.2010
Сообщений: 22
Сказал(а) спасибо: 2
Поблагодарили 23 раз(а) в 8 сообщениях
|
Господи, ну сделайте короткий хедер, в котором к примеру оффсет (или фиксированно с адреса там 20) на структуру блоков и длина структуры, затем оффсет данных. В самой структуре отложить типы полей, возможно с названиями (ну примерно как близзы юзают для структур в dbc, да и вообще многие структуры бд так делают). Позволит забыть на долгие годы изменения в структуре пакетов.
Насчет однобайтового признака: wad как-то юзал RECV/SEND, я предпочитал SMSG/CMSG. Временами спасало если какой-то сбой происходил. Вероятность что каша совпадет с таким признаком нулевая. И если сбой произошел то не теряется весь файл до конца, просто ищеш следующий признак. Последний раз редактировалось user456; 25.07.2010 в 16:54. |
25.07.2010, 16:50 | #33 | ||
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
Цитата:
1) вопрос пока открыт. 2) решили фиксированную. 16 бит нам точно хватит? может уж все же 32? мало ли чего запихать сюда понадобится, значением больше чем 65535. еще один какой нибудь тиккаунт... винты сейчас у всех вроде большие. 3) решили. см. ниже... 4) тогда предлагаю его поместить прямо перед SessionKey. Цитата:
а сокральный смысл всего этого в двух вещах: 1. унифицированность логики с RAW. где сначала идет длина данных (абстрактных), затем собственно эти данные. так и в PKT, длина и затем конкретные данные, соответствующие этой длине. прибавив к хидеру такую длину мы переместимся сразу на начало хидера следующего чанка. ну удобно же! иначе придется в этом месте применять эту математическую операцию. 2. давайте думать, логически завершенные данные, это все же опкод+данные. это законченная еденица сущности, чтоли. формат любого опкода можно представить как из двух полей: - ID - DATA, соответствующая этому ID никто же не пилит А9 на составлящие. там ведь еще круче: Код:
- ID = 0xA9 - DATA - ObjectsCount - UpdateType - UpdateType = 1 (create from Object) - свой набор данных - UpdateType = 2 (update Fields) - свой набор данных - UpdateType = 3 (create for self) - свой набор данных , где (например) свой набор данных UpdateType = 3 - ObjectType = 1 (item) - свой набор данных ObjectType = 1 - ObjectType = 2 (container) - свой набор данных ObjectType = 2 - ObjectType = 3 (unit) - свой набор данных ObjectType = 3 - ObjectType = 4 (player) - свой набор данных ObjectType = 4 , где (например) свой набор данных ObjectType = 4 - свой move-block - в завимости от флагов плюс дополнительные данные а у ObjectType = 1 такие флаги вообще не встречаются и соответственно данных нет... эти две причины достаточно убедительны для тебя? Последний раз редактировалось RomanRom2; 25.07.2010 в 17:02. |
||
25.07.2010, 16:56 | #34 |
Новичок
Регистрация: 22.05.2010
Сообщений: 11
Сказал(а) спасибо: 0
Поблагодарили 3 раз(а) в 1 сообщении
|
Создайте, где-нибудь Wiki-страницу формата.
На форуме минимальные отличия в описании формата не видны совершенно. |
25.07.2010, 16:57 | #35 |
Новичок
Регистрация: 25.05.2010
Сообщений: 11
Сказал(а) спасибо: 1
Поблагодарили 14 раз(а) в 5 сообщениях
|
|
25.07.2010, 16:59 | #36 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
|
25.07.2010, 17:00 | #37 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
32 бита на DevelopersData при каждом пакете и 64 в заголовке файла — согласен
|
25.07.2010, 17:19 | #38 |
Новичок
Регистрация: 22.05.2010
Сообщений: 11
Сказал(а) спасибо: 0
Поблагодарили 3 раз(а) в 1 сообщении
|
Если никак не получается решить для всего формата сразу, давайте хотя-бы определимся с заголовком:
Код:
struct FileHeader { byte signature[3]; // 'PKT' | 'RAW'. word version; // == 0x0003 - для версии 3.0. byte snifferID; // Распределить уникальные номера. uint build; // Номер сборки клиента, обратите внимание, тип uint (4 байта). byte language[4]; // Язык клиента: 'ruRU', 'enGB' и т.д. byte sessionKey[40]; // Ключ сессии, для PKT не используется и может быть заполнен как угодно (лучше нулями). uint optionalHeader; // Размер опционального заголовка в байтах, // который идет сразу после заголовка файла и содержит все, что угодно. // Если optionalHeader == 0, тогда опциональный заголовок в файле отсутствует. }; // sizeof(FileHeader) == 3 + 2 + 1 + 4 + 4 + 40 + 4 = 58 байт (align == 1) Последний раз редактировалось VDm; 25.07.2010 в 17:32. |
25.07.2010, 17:20 | #39 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
господа, поступило шикарное предложение по формату чанка:
(byte)Direction; (uint)UnixTime (uint)TickCount (uint)Data.Length (uint)DD.Length (byte[])Data (byte[])DD как вам? при этом хидер читается структурой, что удобно само по себе. после хидера идут данные опкода. после данных опкода идут DevelopersData, если DD.Length больше нуля. в данном варианте сведены к минимуму все затраты и DD стал переменной длины, что тоже должно всех устроить. правда в этом случае, к великому сожалению Константина, (uint)Data.Length будет содержать данные вместе с опкодом, а Data данные вместе с опкодом. ну в прочем это само по себе и вытекло бы, как ни крути. хех. вон VDm предлагает ту же идею и с хидером снифа. Последний раз редактировалось RomanRom2; 25.07.2010 в 17:24. |
25.07.2010, 17:23 | #40 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
RomanRom2, только опкод все-равно форматируем до 32 бит, ага?
|