PDA

Просмотр полной версии : Программа дамп пакетов


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

Кусок лога программы
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

Как оно работает.

Для отправки пакетов клиент вызывает метод
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
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".

xkor
18.06.2009, 09:40
мм, а как понимать многоточие в объявлении функции?

GoldFinch
18.06.2009, 10:03
xkor, в С/С++ так обозначается переменный список параметров
например http://msdn.microsoft.com/en-us/library/ms647550(VS.85).aspx

Yegor
18.06.2009, 10:06
GoldFinch, в какой веррсии MS Visual Studio писался пример?

OllyDbg
18.06.2009, 10:15
функция с соглашением cdecl, с переменным числом параметров.
простой пример - format и подобные...

предупреждая последующие вопросы, дельфи не поддерживает функции с переменным числом параметров.
как альтернатива - написать оболочку, понимающую в качестве параметров array of variant и в зависимости от типа варианта пихать в стек.
это при желании вызыва, а вот при перехвате более удобного способа, чем прямая работа со стеком или более поздний перехват функции - нет.

з.ы. способ прост, реализации на удивление долго не было.
кто видел абиссовский ингейм на с4-интерлюде от меня (там была pledge.dll) то там был вариант обхода их защиты именно перехватом входящих пакетов и использованием неэкспортируемой SendPacket для их посылки.
кстати адрес можно найти проще... что будет работать в где-то в пределах одной хроники...
для Грации Финал:
SendPacket:=PPointer(Pdword(PDword(dword(UNetworkH andler)+$48)^)^+$6C)^;

Добавлено через 1 минуту
з.ы.ы. а вот инсталлер мне понравился :D

xkor
18.06.2009, 12:28
SendPacket:=PPointer(Pdword(PDword(dword(UNetworkH andler)+$48)^)^+$6C)^;эх, люблю я эти операции с указателями)

ЗЫ интересно, оригинальна ли в клиенте руофа эта функция.., надо будет по шаманить с ним)

GoldFinch
18.06.2009, 14:00
что будет работать в где-то в пределах одной хроники...
для Грации Финал:
SendPacket:=PPointer(Pdword(PDword(dword(UNetworkH andler)+$48)^)^+$6C)^;
вот именно, что это скорей всего будет работать в пределах одной хроники, так что чем забивать "магические" смещения полей в классах, проще сразу забить rva этой функции. Кроме того, надо еще както получить указатель на UNetworkHandler, а для этого надо либо отдельно перехватить один из его методов, например UNetworkHandler::Init, либо забить rva глобальной переменной где он лежит. Вобщем много возни ради 1 адреса.

Yegor, MSVC2008 (MSVC9)

OllyDbg
18.06.2009, 14:46
ЗЫ интересно, оригинальна ли в клиенте руофа эта функция.., надо будет по шаманить с ним)
это указатели по vtable, таблице методов класса... оригинальны? да, конечно!

я делаю иначе...
перехватываю одну из Render функций, оттуда вытаскиваю указатель на UCanvas, а из нее уже UWindowsViewport -> AController -> APawn; XInput; ULevel; UGameEngine; UNetworkHandler etc...
все смещения находит моя же длл (написанная кстати в с4 еще), используя экспортируемые функции из коре - Core.UObject::GetFullName и еще парочку... поэтому хроника из хроник мой радар переписывается за секунд 10.
единственное, что доставляет геммороя - заново описывать структуру User :) все эти аугменты и вставленные стихии заставляют копаться :<

xkor
18.07.2009, 17:29
жесть в поисках SendPacket в клиенте руофа наткнулся на какую то промежуточную функцию в которую пакет приходит в оригинальной шифровке, формат примерно такой:
procedure SendCryptPacket(unk_const: Integer; var data; size: Cardinal); cdecl;

Yegor
18.07.2009, 17:59
xkor, и что? ТЫ сможешь юзать эту функцию?

xkor
18.07.2009, 19:21
Yegor, ну если формат я понял правильно то да, но я хочу найти функцию которая вызывает эту, но через стек этого не выходит, через дизасм нашел только место где эта функция вызывается в предыдущей функции но начало предыдущей функции не найти никак...

Foxs
24.07.2009, 18:58
жесть в поисках SendPacket в клиенте руофа наткнулся на какую то промежуточную функцию в которую пакет приходит в оригинальной шифровке, формат примерно такой:
procedure SendCryptPacket(unk_const: Integer; var data; size: Cardinal); cdecl;

Хкор может на сайте пора вести хайд?
А то ты так открыто пишишь кто угодно может писать в том числе и инова

Grinch
24.07.2009, 20:32
ага хайд 400-500 ) что бы человек 5-6 могли общатся ) так мы в админки можем так же говорить :D

xkor
24.07.2009, 21:26
Foxs, скорее стоит ввести группу доверенных и спец раздел с доступом только для этой группы (в принципе уже есть пара подобных разделов)
а описание функции кстати я написал как поже оказалось неверно, и исправлять не ну буду пожалуй
ЗЫ кстати в клиенте руофа еще оказалось проблематично перехватить функцию recv, через попу её перехватить удалось только для логин сервера пока.., хотя это уже пошла друга тема так что закругляюсь)

Grinch
25.07.2009, 09:58
мне права дай тупо почитать что б :) на этот раздел

GoldFinch
25.07.2009, 12:34
хайды зло.
по постам-тем более зло, т.к. много постов - не всегда значит много полезных постов, обычно это 80% флуд.
а то что иннова перекомпилит клиент - всегда можно реверснуть по новой

destructor
18.09.2009, 20:32
UNetworkHandler
как проще всего найти его адрес?


брякать send не выдет, вернет не то и не туда, там фимида с геймшилдой.

GoldFinch
18.09.2009, 21:11
либо дебажить олькой, либо в ИДА искать в дампе.
но чтобы искать в дампе - надо снять дамп, опять же олькой

xkor
18.09.2009, 21:16
надо снять дамп, опять же олькойну дамп то можно далеко не только олькой снять, а чемнить чему не будет сопротивляться клиент...

destructor
02.10.2009, 17:24
ну с send разобрался, там все достаточно просто оказалось.

проблема с FOutputDevice::Logf, я не смогу править входящий трафик, что делать?:)

GoldFinch
25.10.2009, 01:11
Версия для Gracia Final, сервер http://coderx.ru/showthread.php?t=2071

destructor
28.10.2009, 21:48
это зачем хукаем:
//2. UNetworkHandler:: DispatchNetworkQueue
?

Добавлено через 6 минут
разобрался, GoldFinch кросавчег :D

murc
13.01.2010, 00:55
// Say2:h(psize)c(ID)s(Text)d(Type:Get.Func02)s(Targe t)
push Target // Nick
push $00000002 // TELL
push Text
push ID
push "cSdS"
push ObjectAddress
call SendPacketProcedure


Первым параметром нужно передать еще ссылку на объект. В котором находится этот метод.

xkor
13.01.2010, 01:43
murc, вроде правильно...

murc
15.01.2010, 19:10
Send (id=0x0049)
0x0000| 2B 00 95 3B 04 30 04 34 04 3D 04 3E 04 20 00 3F | ..•.............
0x0010| 04 3E 04 3A 04 30 04 00 00 02 00 00 00 43 00 54 | .............C.T
0x0020| 00 45 00 52 00 45 00 4F 00 00 00 | .E.R.E.O...

Пакет с Руофа - Say2. Может кто-нибуть знает как привести ID пакета к нормальному виду ? Что это вобще за фокус такой ?

xkor
15.01.2010, 19:15
murc, http://l2phx.pp.ru/wsvn/filedetails.php?repname=l2phx3&path=%2F3.5.x%2Funits%2Fuencdec.pas
метод TencDec.Corrector посмотри)