Показать сообщение отдельно
Старый 17.06.2009, 21:43   #1
Пользователь
 
Регистрация: 03.11.2008
Сообщений: 60
Сказал Спасибо: 3
Имеет 107 спасибок в 21 сообщенях
GoldFinch пока неопределено
По умолчанию Программа дамп пакетов

Задумал я написать бота, и потребовались мне форматы пакетов. Гуглить было лень, поэтому я смотрел их прям в клиенте. Потом мне стало лень запускать ольку, и я написал прогу которая пишет пакеты с файл. Пока что прога перехватывает пакеты отправляемые клиентом на ГС, и перехватывает сетевые логи клиента.

Кусок лога программы
Код:
send: id=0E (cdbd)
 00) c: 0E
 01) d: 00000015
 02) b: (size=0x100)
    0000: 09 07 54 56 03 09 0B 01 07 02 54 54 56 07 00 02 | ..TV......TTV...
    0010: 55 56 00 51 00 53 57 04 07 55 08 54 01 07 01 53 | UV.Q.SW..U.T...S
    0020: 00 56 55 56 01 06 05 04 51 03 08 51 08 51 56 04 | .VUV....Q..Q.QV.
    0030: 54 06 55 08 02 09 51 56 01 53 06 55 04 53 00 56 | T.U...QV.S.U.S.V
    0040: 56 53 01 09 02 09 01 51 54 51 09 55 56 09 03 04 | VS.....QTQ.UV...
    0050: 07 05 55 04 06 55 04 06 09 04 51 01 08 08 06 05 | ..U..U....Q.....
    0060: 52 06 04 01 07 54 03 06 52 55 06 55 55 51 01 02 | R....T..RU.UUQ..
    0070: 04 54 03 55 54 01 57 51 55 05 52 05 54 07 51 51 | .T.UT.WQU.R.T.QQ
    0080: 55 07 02 53 53 00 52 05 52 07 01 54 00 03 05 05 | U..SS.R.R..T....
    0090: 08 06 05 05 06 03 00 0D 08 01 07 09 03 51 03 07 | .............Q..
    00A0: 53 09 51 06 07 54 0A 50 56 02 52 04 05 55 51 02 | S.Q..T.PV.R..UQ.
    00B0: 53 00 08 54 04 52 56 06 02 09 00 08 03 53 56 01 | S..T.RV......SV.
    00C0: 05 00 55 06 08 56 04 0D 06 07 52 06 07 04 0A 06 | ..U..V....R.....
    00D0: 01 04 54 04 00 05 02 04 54 00 09 52 53 05 04 01 | ..T.....T..RS...
    00E0: 04 05 05 01 52 51 52 0D 06 51 08 09 54 53 00 0D | ....RQR..Q..TS..
    00F0: 01 02 03 54 53 01 05 03 08 56 54 07 02 54 0B 06 | ...TS....VT..T..
 03) d: E63DEFEB
-end-

log: (Send)Send Protocol Version:21

log: (Receive)VersionCheck

send: id=2B (cSdddddQ)
 00) c: 2B
 01) S: "login"
 02) d: 001340AC
 03) d: 000048D2
 04) d: 001340AC
 05) d: 251F7A19
 06) d: 87546CA1
 07) Q: 0000001D7D98B543
-end-

log: (Send)C_LOGIN Packet

log: (Receive)CharacterSelectionInfo count:-1

send: id=12 (cdhddd)
 00) c: 12
 01) d: 00000000
 02) h: 0000
 03) d: 00000000
 04) d: 00000000
 05) d: 00000000
-end-

log: (Send)CharacterSelect
Как оно работает.

Для отправки пакетов клиент вызывает метод
cpp Код:
void __cdecl SomeObj::SendPacket(const char* format,...);
где SomeObj - какойто объект клиента (в разных версиях клиента - разный),
format - ASCII строка с форматом пакета, например "cddd",
... - переменный список параметров.
Например пакет NetPing отправляется так:
someobj.SendPacket("cddd",0xB1,ping_id,0,0x1800);

Таких методов несколько, 1-2 для ЛС, и один для ГС; их задача - собрать пакет в буфер, зашифровать, и отправить используя ws2_32.send().
Этот метод, как и все остальные методы связанные с сетью, живет в engine.dll, но не экспортируется. Поэтому чтобы его перехватить, надо либо хардкодить смещения в структурах, либо сразу захардкодить ее адрес в engine.dll. В любом случае код будет привязан к конкретной версии клиента. Так как SendPacket - это виртуальный метод, удобно его перехватывать подменяя его указатель в таблице виртуальных методов (ВМТ).

При каждой отправке и приеме пакета, клиент записывает сообщение в свой внутренний лог. Для этого он использует метод core.dll
cpp Код:
void __cdecl FOutputDevice::Logf(unsigned short const * format, ...)
синтаксис этой функции эквивалентен printf.
Таких функций несколько (Logf,Logf2,...), первая из них используется клиентом для логирования сетевых событий, другие для логирования ошибок типа "текстура ххх не найдена". Так как метод экспортируемый, то его адрес можно узнать для любого клиента, но проще перехватить его подменив адрес в таблице импорта, если engine.dll распакован.

Logf вызывается после SendPacket, и после обработки принятого пакета, поэтому например для NetPing будет такой порядок сообщений:
Код:
// принят пакет от ГС NetPingPacket

// вызвана функция обработки NetPingPacket

// вызван метод отправки UNetworkHandler::NetPing(int)

send: id=B1 (cddd)    // вызвана SendPacket
 00) c: B1
 01) d: 4A38193F
 02) d: 00000001
 03) d: 00001800
-end-

log: (Send)NetPing    // вызван Logf в методе отправки пакета  UNetworkHandler::NetPing(int)

log: (Receive)NetPingPacket    // вызван Logf в функции обработки NetPingPacket
Как получить адреса SendPacket и Logf.
Если использовать IDA - посмотреть откуда вызывается ws2_32.send(), это и будет SendPacket; затем надо посмотреть DATA XREF - это будет адрес указателя в ВМТ. Если использовать ollydbg - то все проще, надо поставить бряк на ws2_32.send(), и посмотреть кто его вызывает.
Адрес Logf можно взять прямо из таблицы экспорта core.dll, и перехватить его сплайсингом, но проще посмотреть в ИДА или ольке адрес указателя в таблице импорта engine.dll, и перехватывать указатель.

В аттаче - исходники (С++, компилятор MSVC2008) для сервера ла2 abyss, клиент - gracia2, engine.dll распакован.
Список файлов:
Код:
init.cpp  // модуль инициализации длл, установки перехватов

installer.cpp // модуль цепляющий длл к клиенту
install.def // список экспортов для installer.cpp

SendDump.cpp //основной модуль дампа пакетов
SendDump.h // заголовочный файл SendDump.cpp

tools.h // вспомогательный модуль дампа буфера

SendPacketDump.vcproj //проект MSVC2008
Приветствуются любые разумные замечания, предложения, вопросы и т.п.
Не приветствуются вопросы типа "как это переписать на делфи", "что такое std::basic_ostream", "где взять адреса для С4".
Вложения
Тип файла: rar SendPacketDump.rar (4.2 Кб, 356 просмотров)
GoldFinch вне форума   Ответить с цитированием
За это сообщение GoldFinch нажился 11 спасибками от: