Вернуться   CoderX :: Forums > Основные форумы > Полезности
Войти через OpenID

Полезности Исключительно для полезных тем из других разделов.
Темы тут не создаются!
Темы сюда перемещаются из других разделов, и на их старых местах остаются постоянные перенаправления.

Чат (Новых сообщений с момента вашего последнего визита нет)
Загрузка...
Задавайте ваши вопросы на форуме. Чат предназначен для небольших разговоров.
 
Ответ
 
Опции темы Опции просмотра
Старый 17.12.2008, 00:18   #1
Пользователь
 
Регистрация: 03.11.2008
Сообщений: 60
Сказал Спасибо: 3
Имеет 107 спасибок в 21 сообщенях
GoldFinch пока неопределено
По умолчанию Радар своими руками

Радар своими руками /16.12.2008/

Введение

В этой статье описывается создание "радара" - кода отображающего других игроков внутри клиента ла2. В ней рассмотрены следующие вопросы: рисование в окне клиента, получение информации об нпс и игроках хранящейся клиенте, перехват входящего пакета, перехват исходящего пакета, отправка пакета клиенту.
В свое время, когда я начинал разбираться с клиентом, я искал подобную статью, так и не нашел. Ну а раз ее нет - значит ее надо написать чтобы она была. Для понимания этой статьи необходимы базовые знания по работе клиента ла2, реверсированию и программированию. Все примеры относятся к клиенту C6, но я думаю клиенты ла2 принципиально не отличаются друг от друга.

1. Общая информация о клиенте ла2

Для начала небольшая вводная об устройстве клиента ла2. Он состоит из 1 .exe модуля и нескольких длл выполняющих строго определенные функции - GUI (nwindow.dll), движок (engine.dll), общие вспомогательные функции (core.dll). Клиент сделан на основе движка unreal engine, написан на VC++ с применением ООП. Длл экспортируют практически все методы основных классов, имена декорированы (mangling), также экспортируются таблицы методов (vftable).

2. Рисование

Основная функция радара - рисовать цели в окне клиента. Для этого нужны функции рисования, и перехват нужного участка кода клиента для вызова кода рисования радара.
Клиент для рисования как правило использует класс FCanvasUtil. Для его использования надо создать экземпляр объекта, после рисования - уничтожить его. Примерный размер объекта не более 256 байт (точное значение неизвестно). В классе FCanvasUtil есть одна нормальная функция рисования
void __thiscall FCanvasUtil::DrawLine(float x1, float y1, float x2,float y2,class FColor color,int unk) ,
где x1..y2 - четыре экранные координаты в пикселах,
color - цвет, dword 0xSSRRGGBB (SS - Saturation),
unk - неизвестный параметр, обычно равнен нулю.
Точки можно рисовать короткими штрихами, окружности аппроксимировать отрезками (или пунктиром).
Рисовать надо вместе с клиентом, в одном из методов xxx::Render(), так чтобы картинка радара рисовалась последней (верхней), порядок вызова методов клиентом неизвестен, но рисование после FPlayerSceneNode::Render() позволяет нарисовать радар правильно.

3. Получение информации о целях

Все объекты на карте поделены в клиенте на категории ("живые",лут,...) и хранятся в нектором списке. Для получения "живых" объектов (игроки,НПС) используется метод
struct User * __thiscall UNetworkHandler::GetNextCreature(float Radius,int PrevID) ,
где Radius - радиус поиска, PrevID - ИД предыдущей цели.
Метод возвращает указатель на структуру содержащую информацию о цели (см. приложение). Метод может возвращать ноль, видимо при отсутствии целей вообще. Метод можно вызывать бесконечное число раз, видимо список объектов цикличен, для того чтобы определить конец списка надо проверять повторы ИД возвращаемых целей. Перебор целей можно начинать как с PrevID=0 так и PrevID=-1 .

4. Получение информации о своем персонаже - перехват S->C пакета

Для получения структуры User по ID объекта надо вызвать метод
struct User * __thiscall UNetworkHandler::GetUser(int ID) .
ИД своего персонажа можно получить перехватив S->C пакет UserInfoPacket (#4). Теоретически этот ID можно получить в клиенте по статическому адресу, но перехват пакета очевиднее.
S->C пакеты обрабатываются в клиенте следующим образом:
В отдельном потоке, в цикле, клиент принимает пакеты вызывая ws2_32.recv(), расшифровывает их, добавляет в очередь пакетов методом
UNetworkHandler::AddNetworkQueue(NetworkPacket *) .
Структура NetworkPacket содержит отдельно ID пакета, размер данных пакета (без ID), данные пакета (без ID).
В методе UNetworkHandler::Tick(float) клиент достает пакеты из очереди методом
UNetworkHandler::DispatchNetworkQueue(NetworkPacke t * *) .
Затем по ID пакета вызывается обработчик пакета, по указателю таблицы обработчиков пакетов. Размер элемента таблицы равен 0x104 байтам - указатель на обработчик и UNICODE-имя пакета. Прототип обработчика пакета:
typedef void (__cdecl TPacketHandler)(UNetworkHandler *,char *data);
где data - указатель на данные пакета, без его ID.
Обработчик пакета дизассемблирует пакет согласно его формату, вызывает соответствующий метод UGameEngine::OnXXX() и записывает информацию о пакете во внутренний лог клиента.
Метод UGameEngine::OnXXX вызывает события в GUI или в движке клиента.
Очевидно, что перехватывать одиночный пакет удобно подменяя указатель на обработчик пакета или указатель на метод UGameEngine в его таблице методов.

5. Управление настройками радара - перехват C->S пакета и отправка пакета клиенту

Внутри клиента можно организовать достаточно удобный интерфейс используя HTML встроенный в клиент.
Для показа диалогового окна пользователю, надо отправить клиенту пакет с HTML-кодом, методом
int __thiscall UGameEngine::OnNpcHtmlMessage(struct User *npc,unsigned short *html,int unk) ,
где npc - указатель на структуру User НПС отправившего сообщение, может быть равен нулю,
html - указатель на UNICIDE-строку с HTML-кодом,
unk - неизвестный параметр, обычно равен нулю.
Если ввод данных производится кнопками, то для перехвата ввода необходимо перехватить пакет RequestBypassToServer. Клиент отправляет пакеты следующим образом:
GUI или движок клиента вызывают соответствующий метод UNetworkHandler, например
int __thiscall UNetworkHandler::RequestBypassToServer(class L2ParamStack &) .
Этот метод передает формат пакета и его данные в неэкспортируемую функцию отправки пакета
void __cdecl SendPacket(UNetworkHandler*,char*,...) .
Функция отправки пакета ассемблирует пакет в буфер согласно его формату, шифрует и отправляет на сервер через ws2_32.send() .
Для перехвата одиночного отправляемого пакета удобно перехватить указатель на метод в таблице методов UNetworkHandler.

Заключение

Я не выкладываю сам исходник радара, в его коде нет ничего сложного, и имея информацию изложенную в этой статье его можно достаточно быстро собрать.
Эта статья больше посвящена частям клиента относящимся к пакетной части клиента. Графическая часть рассмотрена вскользь без какого-либо разбора, движок клиента только упоминается, совсем не рассмотрены GUI и остальные части клиента. Буду рад если кто-нибудь дополнит эту статью или выложит что-то новое. Возможно есть смысл перевести ее на английский.

Приложение. Структуры клиента (С6)
Код:
struct User
{
int _zunk1_12[2];
int user_type; //ZERO for player
int _zunk1_34[2];
int unk_npc_spec;
int id;
unsigned short name[0x30/2];
int race;
int _zunk2;
int _xunk3;
int lvl;
int _xunk4;
int _zunk5;
int states[6];
int hp_max;
int hp;
int mp_max;
int mp;
int _xunk68[3];
int wear[14];
char _zunk9[0xC0];
int Color;
char _unk10[0x70];
APawn *Pawn;
int _zunk11[3];
int _xunk12;
int sp;
int accuracy_;
int critical;
int _xunk13;
int _xunk14;
int patk;
int evasion_;
int matk;
int mdef;
int castspd;
char _unk15[0x6C];
int atkspd;
char _unk16[0x14];
int cp_max;
int cp;
//current size=0x2CC, real size = 0x380
};

class APawn
{
char _unk[0x1BC]; //...
public:
FVector Location;
//...
};

class FVector
{
public:
    float X,Y,Z;
};
----------------------------------------------------
[C] GoldFinch

Спасибо
Arrowdodger за помощь в написании и тестировании радара
Разработчикам BSFG (Abyss) за их радар и его кривую защиту. Кстати код у binkw32.dll тоже хреновый :)

Последний раз редактировалось GoldFinch, 09.05.2009 в 16:10.
GoldFinch вне форума   Ответить с цитированием
За это сообщение GoldFinch нажился 34 спасибками от:
Старый 27.05.2009, 14:22   #2
Пользователь
 
Аватар для Fertis
 
Регистрация: 07.03.2009
Сообщений: 64
Сказал Спасибо: 33
Имеет 2 спасибок в 2 сообщенях
Fertis пока неопределено
По умолчанию

Мб зря апаю тему... но никто неможет ли привести пример, экспорта хотя бы одной функции? Например инфы о своем чаре. Чет поковырялся, половину непонял...
Fertis вне форума   Ответить с цитированием
Старый 28.05.2009, 15:54   #3
Пользователь
 
Аватар для Be3geBJIa3
 
Регистрация: 23.01.2008
Сообщений: 93
Сказал Спасибо: 31
Имеет 65 спасибок в 23 сообщенях
Be3geBJIa3 пока неопределено
По умолчанию

Очень интересная статья, хотелось бы продолжения. Примеры, исходники.
Be3geBJIa3 вне форума   Ответить с цитированием
Старый 28.05.2009, 18:09   #4
Местный
 
Регистрация: 18.02.2008
Сообщений: 141
Сказал Спасибо: 16
Имеет 66 спасибок в 30 сообщенях
ratvier
По умолчанию

Автор выкладывал где-то пример. Я надеюсь, он будет не против, если я его залью сюды.
Вложения
Тип файла: rar l2cc.rar (9.6 Кб, 1296 просмотров)
ratvier вне форума   Ответить с цитированием
За это сообщение ratvier нажился 8 спасибками от:
Старый 28.05.2009, 20:11   #5
Пользователь
 
Регистрация: 03.11.2008
Сообщений: 60
Сказал Спасибо: 3
Имеет 107 спасибок в 21 сообщенях
GoldFinch пока неопределено
По умолчанию

на этом форуме и выкладывал, и не пример радара, и на фасме =)
GoldFinch вне форума   Ответить с цитированием
За это сообщение GoldFinch нажился 2 спасибками от:
Старый 28.05.2009, 21:10   #6
Пользователь
 
Аватар для Fertis
 
Регистрация: 07.03.2009
Сообщений: 64
Сказал Спасибо: 33
Имеет 2 спасибок в 2 сообщенях
Fertis пока неопределено
По умолчанию

на дельфях ниукого небудет примеров? если кто может скиньте плиз, ибо переписать на паскаль несмогу был бы очень признателен
Fertis вне форума   Ответить с цитированием
Старый 28.05.2009, 21:47   #7
Admin!
 
Аватар для xkor
 
Регистрация: 04.08.2007
Сообщений: 2,360
Сказал Спасибо: 113
Имеет 1,566 спасибок в 651 сообщенях
xkor на пути к лучшему
По умолчанию

Fertis, дельфи не умеет работать с thiscall типом вызова вроде, так что надо будет всё равно переходники на асме делать...
__________________
Я здесь практически не появляюсь!, Skype - ikskor
xkor вне форума   Ответить с цитированием
Старый 28.05.2009, 22:36   #8
Пользователь
 
Аватар для Fertis
 
Регистрация: 07.03.2009
Сообщений: 64
Сказал Спасибо: 33
Имеет 2 спасибок в 2 сообщенях
Fertis пока неопределено
По умолчанию

Цитата:
Сообщение от xkor Посмотреть сообщение
Fertis, дельфи не умеет работать с thiscall типом вызова вроде, так что надо будет всё равно переходники на асме делать...
Расстроил :'(

А никто это с дельфями несвязывал? Просто учить другие языки времени нету.
Fertis вне форума   Ответить с цитированием
Старый 29.05.2009, 01:29   #9
Пользователь
 
Регистрация: 03.11.2008
Сообщений: 60
Сказал Спасибо: 3
Имеет 107 спасибок в 21 сообщенях
GoldFinch пока неопределено
По умолчанию

переходник для stdcall -> thiscall выглядит просто
у тебя есть указатель на thiscall метод TObj.foo
foo:=GetProcAddress(hEngine,"...");
и для вызова ты пишешь либо функцию
Код:
  function foo(obj:TObj , arg1:T1, arg2:T2);stdcall;
  asm
    pop eax //адрес возврата, временно сохраняем в eax
    pop ecx //аргумент obj, записываем в ecx как того требует __thiscall
    push eax //записываем сохраненный адрес возврата
    jmp [foo] //вызываем метод    
  end;
или метод
Код:
  function TObj.foo( arg1:T1, arg2:T2);stdcall;
  asm
    pop eax //адрес возврата, временно сохраняем в eax
    pop ecx //аргумент obj, записываем в ecx как того требует __thiscall
    push eax //записываем сохраненный адрес возврата
    jmp [foo] //вызываем метод    
  end;
GoldFinch вне форума   Ответить с цитированием
За это сообщение GoldFinch нажился 8 спасибками от:
Старый 29.05.2009, 08:55   #10
Пользователь
 
Аватар для Fertis
 
Регистрация: 07.03.2009
Сообщений: 64
Сказал Спасибо: 33
Имеет 2 спасибок в 2 сообщенях
Fertis пока неопределено
По умолчанию

спасиб, пойду попробую ченить сделать =\ хотя все равно не до конца все понял
Fertis вне форума   Ответить с цитированием
Ответ

  CoderX :: Forums > Основные форумы > Полезности



Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 21:54.

vBulletin style designed by MSC Team.
Powered by vBulletin® Version 3.6.11
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Locations of visitors to this page
Rambler's Top100

Вы хотите чувствовать себя в безопасности? чоп Белган обеспечит её!