PDA

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


Страницы : [1] 2 3

GoldFinch
17.12.2008, 00:18
Радар своими руками /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 тоже хреновый :)

Fertis
27.05.2009, 14:22
Мб зря апаю тему... но никто неможет ли привести пример, экспорта хотя бы одной функции? Например инфы о своем чаре. Чет поковырялся, половину непонял... :(

Be3geBJIa3
28.05.2009, 15:54
Очень интересная статья, хотелось бы продолжения. Примеры, исходники.

ratvier
28.05.2009, 18:09
Автор выкладывал где-то пример. Я надеюсь, он будет не против, если я его залью сюды.

GoldFinch
28.05.2009, 20:11
на этом форуме и выкладывал, и не пример радара, и на фасме =)

Fertis
28.05.2009, 21:10
на дельфях ниукого небудет примеров? если кто может скиньте плиз, ибо переписать на паскаль несмогу :( был бы очень признателен

xkor
28.05.2009, 21:47
Fertis, дельфи не умеет работать с thiscall типом вызова вроде, так что надо будет всё равно переходники на асме делать...

Fertis
28.05.2009, 22:36
Fertis, дельфи не умеет работать с thiscall типом вызова вроде, так что надо будет всё равно переходники на асме делать...

Расстроил :'(

А никто это с дельфями несвязывал? Просто учить другие языки времени нету.

GoldFinch
29.05.2009, 01:29
переходник для 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;

Fertis
29.05.2009, 08:55
спасиб, пойду попробую ченить сделать =\ хотя все равно не до конца все понял

PanAm
29.05.2009, 16:00
Fertis, :p
Прикрути LUA движок к линяги, и можно будет писать аддоны как в ВоВ. :D

Murdoc
29.05.2009, 16:24
Автор выкладывал где-то пример. Я надеюсь, он будет не против, если я его залью сюды.

э... и что демонстрирует данный пример? у меня он 1 раз подвесил тачку, 2 раза запорол клиента, 2 раза просто не запустился(файл занят) и еще пару раз незапустился с другой ошибкой. и ехе и длл лежали в папке систем клиента.

alexteam
29.05.2009, 17:55
Murdoc, отвечаем вопросом на вопрос.
на какие хроники расчитан данный пример ?.

GoldFinch
29.05.2009, 18:07
Murdoc, там написано, что это POC (proof of concept). Он тестировался на конкретном клиенте С6, и его надо дорабатывать напильником чтобы он заработал на другом клиенте. Кроме того, т.к. это POC, никакой полезной функциональности там нет, а есть только пример работы с API клиента напрямую.

murc
29.05.2009, 21:57
Народ а как вызывать из енджин.длл функции отправки пакетов ?

Sherman
02.06.2009, 10:31
Engine:=GetModuleHandle('engine.dll');
UGameEngine_Init := Ptr(Engine+$0025CA40);
asm
call UGameEngine_Init
end;


например так =)
(Код не имеющий к реальности почти никакого отношения)

Arseny
05.06.2009, 02:11
перед тем как отправить пакет от имени engine.dll надо еще заполнить стек отправки
вчера стал ковырять функцую отправки пакета на сдачу манора - в принципе механизм тот же, что и в других функциях Л2, можно разбить на следующую цепочку:
1. преварительные действия, нас не интересуют в общем-то. Могут интересовать, чтобы подобрать место для перехода на наш код.
2. чтение из стека Л2, подготовка параметров для обработки - самая интересная часть, нас интересует больше всего. Именно в этот момент нам доступны внутренние данные пакетов при получении и перед отправкой, именно этот код нужно дублировать в нашей программе.
3. последующие действия клиента, как правило, не представляют интереса.

Murdoc, у меня этот пример убил клиент Ц4, хотя я почитал как он переписывается под Ц4. Но именно он подтолкнул меня к написанию собственного аналога, и дал кое-какое понимание о внутренней работе клиента и том, что и как надо в нём перехватывать. После чего был написан аналог по механизму работы для Ц4, который опробован на конкретном клиенте, на вин XP и Висте, сама ДЛЛка работает стабильно, программа-приемник периодически вылетает. Сейчас обдумываю как лучше сделать отправку пакета от имени клиента... вариантов два - или создать свой стек и заполнить его, после чего вызвать нужную функцию с указателем на мой стек, или же внедриться в функцию и внаглую прописывать в нужных местах значения(ессно передаются через переменные). Сами проги на дельфи, код, отвечающий за перехват функций клиента - ассемблер... без ассемблера никак вообще тут.

dmitry501
05.06.2009, 05:59
перед тем как отправить пакет от имени engine.dll надо еще заполнить стек отправки
вчера стал ковырять функцую отправки пакета на сдачу манора - в принципе механизм тот же, что и в других функциях Л2, можно разбить на следующую цепочку:
1. преварительные действия, нас не интересуют в общем-то. Могут интересовать, чтобы подобрать место для перехода на наш код.
2. чтение из стека Л2, подготовка параметров для обработки - самая интересная часть, нас интересует больше всего. Именно в этот момент нам доступны внутренние данные пакетов при получении и перед отправкой, именно этот код нужно дублировать в нашей программе.
3. последующие действия клиента, как правило, не представляют интереса.
<SKIP>.

Если заинтересовался этой темой пиши в ПМ мне или Sherman - у
Есть небольшие наработки, как раз по С4 и возможен обмен знаниями :)

destructor
02.07.2009, 23:12
Народ а как вызывать из енджин.длл функции отправки пакетов ?

и как её найти?:D

Arseny
02.07.2009, 23:22
что найти? функцию? или ДЛЛ? если ДЛЛ - то поройся в папке с игрой, если функцию - поройся в ДЛЛке с помощью текстового просмотрщика (типа того, что в тотал командере)

destructor
02.07.2009, 23:32
Arseny, она "не экспортируемая" (функция отправки пакетов)

Arseny
04.07.2009, 19:14
сама функция SendPacket - да, неэкспортируемая, но большую часть пакетов можно вызвать через экспортируемые функции, которые в конечном итоге вызывают SendPacket. Я сам не стал заморачиваться на отлов сенда, просто внедрился в код функции Request... для получения указателя на объект UNetworkHandler, и потом просто вызываю сам нужные мне функции, передавая в них свои параметры, вызываю от имени перехваченного объекта.

GoldFinch
05.07.2009, 23:09
можно и не в ольке.
сдампи engine.dll, если запакована, и поищи в IDA
импорты можно и не чинить, если тольк send() найти

Arseny
06.07.2009, 21:32
GoldFinch, без Ольки
Имена функций смотрю через HexWorkshop, адреса через GetProcAddress делаю. Всё в процессе запуска ДЛЛки в работу, цепляется в любой момент к игре. Для моих задач подходит такой метод. Принцип внедрения в код - получаем адрес функции, считываем записанный там джамп, запоминаем, записываем туда джамп на свой обработчик, в своем обработчике в конце прописываем джамп по тому адресу, который мы запомнили. Естесственно всё на ассемблере.

roma_
24.09.2009, 18:27
Пишу свой радар для клиента Linage2 C4. Перехватываю пакеты раскодирую все ок.
Столкнулся с проблемой эмуляции нажатия клавиш и кнопок мыши и отправкой их клиенту.
Есть программа Evelina которая решила эту проблему.
Может кто сталкивался, работает или решил эту проблему?
Если кто нить работает предлагаю совместно подумать.

QaK
24.09.2009, 22:17
roma_, какой смысл в кликере, если пакеты норм перехватываются и расшифровываются?

Arseny
25.09.2009, 12:09
эмуляцию нажатия кнопок можно сделать через функцию PostMessage. Только там одна маленькая загвоздка - если встречаются русские символы, то надо использовать Unicode вариант PostMessageW
Вообще для C4 есть хороший радар L2Control, правда он платный.

alexteam
25.09.2009, 12:39
а зачем если можно "тыкнуть пакетом" ? =\

destructor
10.12.2009, 13:01
В отдельном потоке, в цикле, клиент принимает пакеты вызывая ws2_32.recv(), расшифровывает их, добавляет в очередь пакетов методомгде этот код в клиенте?

Fertis
16.12.2009, 11:46
Блин, чет на дельфях невыходит сделать :\ неужели ни у кого нету хотя бы самых простых исходников? Помогите плз

GoldFinch
16.12.2009, 21:31
где этот код в клиенте?
поставь бряк на ws2_32.recv и увидишь где

xkor
17.12.2009, 03:31
destructor, только в клиенте руофа бряк на recv можешь не стараться ставить, не срабатывает...

Блин, чет на дельфях невыходит сделать :\ неужели ни у кого нету хотя бы самых простых исходников? Помогите плзчто именно сделать не выходит?

Fertis
17.12.2009, 10:16
Ну вроде описал классы, экспорт функции недопонял до конца и как ее использовать :\ уже все перепробывал, вот хотелось бы чтоб выложили исходник показывающий пример использования хотя бы одной функции, а дальше думаю разберусь...

Функцию экспортирую так, но чую что неправильно :-]:
function GetUser(ID: integer): User; stdcall; external 'Engine.dll' name 'GetUser';

Так же ГолдФинч давал вот это, я так и не понял как этим пользоватся ><
function foo(obj:TObj , arg1:T1, arg2:T2);stdcall;
asm
pop eax //адрес возврата, временно сохраняем в eax
pop ecx //аргумент obj, записываем в ecx как того требует __thiscall
push eax //записываем сохраненный адрес возврата
jmp [foo] //вызываем метод
end;

xkor
17.12.2009, 15:23
Fertis, импорт ты не не допонял а вообще не понял ничего кроме того что он должен быть...

Fertis
17.12.2009, 19:17
не... да я уже много че и как перепробывал... нужно экспортировать функцию и описать класс User, не? У меня голова просто уже совсем не варит. Или я походу вообще делаю что то не так, выложите лучше пример чтоли, как использовать хоть одну функцию... а то надоело все наугад делать :\

xkor
18.12.2009, 00:35
Fertis, ок, вот так хукаю функцию UNetworkHandler::AddNetworkQueue
HookProc('engine.dll','?AddNetworkQueue@UNetworkHa ndler@@UAEHPAUNetworkPacket@@@Z',
@UNetworkHandler_AddNetworkQueue_Hook,@UNetworkHan dler_AddNetworkQueue_Original);

в результате при вызове клиентом AddNetworkQueue сначала вызывается моя UNetworkHandler_AddNetworkQueue_Hook:
procedure UNetworkHandler_AddNetworkQueue_Hook(NetworkPacket : Pointer); stdcall;
asm
push ecx
push [ebp+8]
push ecx
call UNetworkHandler_AddNetworkQueue_New
pop ecx
end;
которая собсно всего лишь прослойка к полноценной функции UNetworkHandler_AddNetworkQueue_New:
procedure UNetworkHandler_AddNetworkQueue_New(unh: Integer; np: PNetworkPacket); stdcall;
begin
// тут код для логирования того что пришло в функцию

// сохраняем указатель на объект UNetworkHandler
nh:=Pointer(unh);

// Вызываем клиентскую UNetworkHandler::AddNetworkQueue
UNetworkHandler_AddNetworkQueue_Call(np);
end;

ну просто для импорта достаточно засунуть в UNetworkHandler_AddNetworkQueue_Original указатель на UNetworkHandler::AddNetworkQueue и вызвать UNetworkHandler_AddNetworkQueue_Call, короче примерно так:
var
nh: Pointer; // <-- в эту переменную надо засунуть указатель на объект UNetworkHandler
UNetworkHandler_AddNetworkQueue_Original: procedure(NetworkPacket: Pointer); stdcall;

procedure UNetworkHandler_AddNetworkQueue_Call(NetworkPacket : Pointer); stdcall;
asm
mov ecx, nh
mov esp, ebp
pop ebp
jmp [UNetworkHandler_AddNetworkQueue_Original]
end;

begin
UNetworkHandler_AddNetworkQueue_Original:=GetProcA ddress('engine.dll','?AddNetworkQueue@UNetworkHand ler@@UAEHPAUNetworkPacket@@@Z');

// вызываем импортированную функцию
UNetworkHandler_AddNetworkQueue_Call(параметр);
end.

Добавлено через 4 минуты
UNetworkHandler_AddNetworkQueue_Hook и UNetworkHandler_AddNetworkQueue_Call прослойки нужные для того чтоб перейти от thiscall к stdcall соглашению

Fertis
18.12.2009, 10:48
пасиба, щас поковыряюсь )

Cooper85
20.01.2010, 16:08
NetworkPacket: Pointer
А кто-то может поделится примерной структурой этого дела ?
А-ля ПХ на мой взгляд не подходит.
Структура NetworkPacket содержит отдельно ID пакета, размер данных пакета (без ID), данные пакета (без ID).
Это читал.

Добавлено через 10 часов 0 минут
DWORD - id пакета (id+sub id пакета), незанятые байты - мусор
DWORD - длина данных пакета без id и без длины

ratvier
21.01.2010, 00:14
DWORD - id пакета (id+sub id пакета), незанятые байты - мусор
по сути - мусор, но всё же это выравнивание

DWORD - длина данных пакета без id и без длины
последний раз, когда я там ковырялся, под длину выделялся WORD, а оставшиеся 2 байта - выравниевание O_o

а после этого шёл указатель на "тело" пакета, как-то так:

#pragma pack(push,1)
struct NetworkPacket
{
char ID;
char u1;
char u2;
char u3;
short length;
char u4;
char u5;
char* data;
};
#pragma pack(pop)

_______________________________________________
in pivo veritas %)) и пофиг что не правда %))))

Cooper85
21.01.2010, 03:51
struct NetworkPacket
{
char ID;
char u1; //subid
char u2;
char u3;
short length;
char u4; //=0
char u5; //=0
char* data;
};
Как-то так у меня получается...:mad:
Офф, здешний тестовый сервер.

brat
21.01.2010, 04:38
NetworkPacket: Pointer
А кто-то может поделится примерной структурой этого дела ?


PNetworkPacket = ^TNetworkPacket;
TNetworkPacket = packed record
id: byte; // ID пакета
res: byte; // тут ничего нужного нет
id2: Smallint; // второй ID если есть
size: Cardinal; // размер данных
data: Pointer; // указатель на данные
end;

Cooper85
22.01.2010, 04:18
Теперь другая проблема. Менеджмент памяти в чужом процессе...:)
reallocmemory при изменении размера данных пакета очевидно не выход...
Если выделять память самостоятельно, то интересно по завершению обработки пакета в дебрях л2 уже выделенный линейкой блок будет освобождаться , или мной созданный. В первом случае - утечка памяти, во втором - как мне освобождать созданные блоки, по таймеру что ли, или по следующему вызову функции скорее всего...

Или все-таки с reallocmemory прокатит...
зы: это все про хук на UNetworkHandler_AddNetworkQueue

xkor
22.01.2010, 04:38
Cooper85, у меня не вышло заставить UNetworkHandler_AddNetworkQueue принимать мои пакеты, как я только не выделял память - клиент вылетает с критом при попытке вызвать эту функцию...
ЗЫ хотя возможно эт из за того что я её вызывал в отдельном потоке, лень мне было пробовать вызвать её в еёном потоке)

Cooper85
26.01.2010, 21:52
Там как я понял, свой менеджер памяти (и не один наверно) в виде класса FMallocWindows(FMalloc). Причем один экземляр FMalloc объявлен в экспорте Core.dll. Наверно тот который инициализируется вместе с AppInit(..).
Теперь интересует все про представление сишных классов в памяти...:mad: В частности, как получить указатель на метод класса, имея указатель на экземпляр в памяти.

murc
26.01.2010, 22:12
Тебе для чего это ?

Cooper85
26.01.2010, 22:52
murc,
заставить UNetworkHandler_AddNetworkQueue принимать мои пакеты

murc
27.01.2010, 03:53
может тогда проще DispatchNetworkQueue хукнуть, подменив указатели на выходе ?

destructor
27.01.2010, 14:38
а волкер делает так: хукает на WSAAsyncSelect()... а дальше стратегическая тайна.

Добавлено через 48 секунд
может тогда проще DispatchNetworkQueue хукнуть, подменив указатели на выходе ?тогда теряем оригинальные пакеты?

murc
27.01.2010, 19:00
Причем тут WSAAsyncSelect() и AddNetworkQueue ?

Теоретически (для Интерлюдии)
call DispatchNetworkQueue@UNetworkHandler
в [edi] - адрес структуры TNetworkPacket
меняем на свое, вуаля читем что состряпали
Теоретически все должно пройти норм.

Upd Попробовал вчера подменить в тике клиента когда DispatchNetworkQueue возвращает ноль.. access violation гдето в обработчике пакета, дальше стало лень..

Maxno
28.01.2010, 04:53
народ... вот есть список функций в dll в оригинале.. но как мне получить список функций уже с дампа... т.е. если вот xkor приводил пример перехвата функции "UNetworkHandler::AddNetworkQueue"... она выглядит как "?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPa cket@@@Z".. как получить?

ЗЫ: список функций взят от Gracia Final Epilogue (Plus)

xkor
28.01.2010, 09:32
Maxno, список экспортируемых функций у дампа и у оригинальной длл одинаковый
UNetworkHandler::AddNetworkQueue - название функции как оно выглядит до компиляции внутри исходников
?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPa cket@@@Z - название функции как оно выглядит в экспорте длл, открываешь длл любым РЕ вьювером и смотришь экспорт...

ra1n0
29.01.2010, 12:30
чтобы перевести ?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPa cket@@@Z в более читабельный вид(прим. UNetworkHandler::AddNetworkQueue) ,можно воспользоваться undname.exe
поставляемой в комплексе с VS.

murc
05.02.2010, 19:46
Продолжая тему про AddNetworkQueue, хочу поделится своими наработками, может кому-нибуть будут полезными ...

Что бы добавить свой пакет в массив, нужно выделить память, но просто выделить мало, нужно выделить где-то внутри ла2. Для выделения памяти я юзал ф-ию "L2MemoryAlloc", ее можно легко найти, она находится рядом с AddNetworkQueue. Выглядит она следующим образом:

L2MemoryAlloc(cmd: PWideChar; Len: integer): Pointer;

В качестве параметров используются строки "NetCmd", "NetPacket" и размер. Строки указывают для чего резервируется память и выделяется в соответствующем месте. Вообще выделение памяти здесь звучит довольно не корректно, т.к выделения памяти по сути происходит не всегда и зависит от аргументов. Стоит еще отметить то, что вызывать нужно поразному для конкретного аргумента(cmd), не знаю с чем это связано, но при вызове ф-ии в регистрах должно быть то, что должно быть, иначе будет ошибка. Для выделения памяти под сам пакет и под структуру NetworkPacket, которую в дальнейшем мы будем добавлять, я юзал такие ф-ии:

function L2MemoryAllocNetCmd(len: integer): Pointer; stdcall;
asm
push NetCmd
push len
mov edx, [$01E6D6A4]
mov ecx, [edx]
mov edx, [ecx]
mov eax, [edx]
call eax
end;

function L2MemoryAllocNetPacket: Pointer; stdcall;
asm
push NetPacket
push $0C
mov edx, [$01E6D6A4]
mov ecx, [edx]
mov eax, [ecx]
mov edx, [eax]
call edx
end;

Вообще это копипаст из клиента и адресс 01E6D6A4 будет действителен только для конкретных хроник - ИТ, найти в другом клиенте не должно вызвать проблем.
В первом случае мы выделяем память, куда положим свой пакет без его длинны, ID и если есть то и SubID. Во втором под структуру NetworkPacket. Заполняем и вызываем примерно таким образом:

procedure AddNetworkQueue(NetworkPacket: PNetworkPacket); stdcall;
asm
mov ecx, [$00BFF558] - UNetworkHandler
mov edx, [ecx]
mov eax, [edx+$84]
push NetworkPacket
call eax
end;

Проверялось на Интерлюдии, должно работать везде впринципе. Самое главное выделить память без ошибок.

xkor
05.02.2010, 22:22
murc, думаю клиенту при вызве этих функций важно лишь содержимое ecx, ибо по соглашению thiscall там должен быть указатель на объект которому принадлежит метод, а остальные регистры по идее не обязаны содержать то что содержат)

Yegor
10.05.2010, 15:03
Товарищи, вы получив какие то данные из процесса l2 оперируете ими прямо в рамках внедренной dll или какимто макаром шлете основной программе (через sendmessage или по сети)? Ведь на внедряемый код наложено очень много ограничений. Вот цитата из статье с WASMа:

"Компилятор Delphi обычно генерирует в процедурах короткие переходы (JMP SHORT), но при большом размере процедуры могут появиться переходы по абсолютным адресам, поэтому внедряемый код желательно писать используя короткие процедуры, используя как можно меньше условий и циклов."

Как можно быть уверенным что что все переходы делфи сделала "короткими".
Так же как отлаживать внедренную dll? Как хотябы ее выгрузить из памяти процесса что бы я ее мог перекомпилировать и внедритль наново?

GoldFinch
10.05.2010, 15:09
Yegor, эта цитата относится только к тем длл которые были внедрены в чужой процесс своим кривым загрузчиком. Если загружать длл через LoadLibrary или нормальным загрузчиком таких проблем нет.
Отлаживать - так же как и клиент =)
Чтобы выгрузить - пиши код который выгрузит %)

xkor
10.05.2010, 17:21
Если загружать длл через LoadLibrary или нормальным загрузчиком таких проблем нет.кстати, не встречал нормального PE загрузчика в исходниках или хотяб в obj файле чтоб в свою прогу можно было норм внедрить? я чтот не смог найти чтоб работало и на XP и на висте с 7кой(

GoldFinch
10.05.2010, 21:29
xkor, на wasm.ru/forum периодически проскакивает, вот этот например (выглядит правда страшно)
http://wasm.ru/forum/viewtopic.php?id=36993

А чем LoadLibrary плоха? Особенно если инжектить длл при создании процесса.

Вообще если дллка простенькая, без наворотов, (без TLS, импортов, file align = 0x1000) то ей надо только релоки настроить, а это несложно.

xkor
10.05.2010, 23:19
А чем LoadLibrary плоха? Особенно если инжектить длл при создании процесса.да мне не для инжектов а для кое каких других извращений)

Yegor
11.05.2010, 10:07
GoldFinch, непойму все таки как отлаживать мою dll. Сейчас пишу тв Delphi. Точнее как запустить отладку нашгел, но каждый раз после перекомпиляции dll получается прийдется перезагружать l2?

xkor
11.05.2010, 10:47
Yegor, именно, а кто говорил что будет просто)

GoldFinch
11.05.2010, 20:08
Yegor, напиши в длл код который позволит выгрузить себя и загрузить новую версию длл, если надо ;)

Эдвадко
11.05.2010, 21:34
Yegor, напиши в длл код который позволит выгрузить себя и загрузить новую версию длл, если надо ;)

Это как-то мудрено очень. К тожу-же, чуть напортачишь в
подгружаемой dll и клиент вылетает с ошибкой.
Я инжектируемую dll пишу, чтоб была возможно более простая.
Только перехват команд от клиента и от сервера и отсылка в основной
модуль программы. Связь между dll и модулем делал раньше через
mapped file а сейчас по IP(UDP).
На будущее, это позволит собирать инфу с нескольких клиентов запущеных на разных компах в один коммандный центр.

Yegor
12.05.2010, 00:09
GoldFinch, это то я напишу, но вот Delphi для отладки dll хочет сама запускать процесс в который её будет загружать.


Эдвадко, в l2ext от Alexteamа похоже сделано так же, начну сначала с общения через message а потом и tcp\ip задействую.

Эдвадко
12.05.2010, 07:44
[QUOTE=Yegor;88284]GoldFinch, это то я напишу, но вот Delphi для отладки dll хочет сама запускать процесс в который её будет загружать.

Я например отладчик не пользую - ну так получилось.
В качестве отладчика использую ту-же внедряемую dll

Удалось перехватить какую функцию - хук начинает логировать
адреса вызова этой функции и параметры вызова.

Потом ползаю по дизассемблированой engine.dll по соотв. адресам и смотрю че и как.

static DWORD HookProcAdr;

void __declspec(naked) __stdcall HookProcE9()
{
static DWORD SavedRetAddr,SavedArg0,SavedArg4,SavedArg8;
__asm push ebp
__asm mov ebp,esp
__asm pushad

__asm mov eax,[ebp+4] //RetAddr
__asm mov SavedRetAddr,eax
__asm mov eax,[ebp+8] //Arg0
__asm mov SavedArg0,eax
__asm mov eax,[ebp+12] //Arg4
__asm mov SavedArg4,eax
__asm mov eax,[ebp+16] //Arg8
__asm mov SavedArg8,eax

static char str[100];
_snprintf(str,100,"%u",*(PBYTE)SavedArg0);
MappedText(str,0xFFFFFF00);

fprintf(LogFile,"HookE9 %x %x %x %x %02x\n",SavedRetAddr,SavedArg0,SavedArg4,SavedArg8,*(PBYT E)SavedArg0);

__asm popad
__asm pop ebp
__asm push HookProcAdr
__asm retn
}

Xen
12.05.2010, 08:25
Ломать проще, чем самому это строить ) в очередной раз убеждаюсь

Yegor
14.05.2010, 20:18
GoldFinch, ты ранее писал переходник для вызова с++ функций с соглашением ThisCall из делфи. А можно сделать переодник дял того чтобы функция делфи вызывалась как ThisCall?

Добавлено через 2 часа 51 минуту
Вопрос снят, получилось

n1ghtmare
17.05.2010, 00:32
Откопал в недрах форума это:

struct NetworkPacket
{
unsigned char* id, _padding1, exid, _padding2;
unsigned short size, _padding3;
unsigned char* data;
};

Вопрос: актуально ли это дял руофа? Потомутчо size какимто странным образом стабильно больше 1024... Заметил что все значения кратны 8. Что делать? И что есть _padding1, _padding2, _padding3 ? Нечто неизвестное?

Yegor
17.05.2010, 00:36
n1ghtmare, Актуально, как раз курю эту же тему. Size определяется верно. Единственнонепонтно по поводу paddingx, значения в них меняются.
И еще не уверен по поводу exid. В нем в пакетах без второго id почему то идет значение 255.

RocknRolla
17.05.2010, 00:37
а автор темы не может просты нужные файлы собрать в патч и выложить где нибудь?

n1ghtmare
17.05.2010, 00:38
Тоесть с size проблемы уменя? 1024+ он не должен быть?

Yegor
17.05.2010, 00:43
нет, у меня значение колеблется от нескольких байт до тысяч в зависимости от пакета. Если что пиши в личку спишемся в аське.

xkor
17.05.2010, 05:05
NetworkPacket имеет такую структуру:
первый байт - id пакета, второй - мусор, дальше smallint число (двухбайтовое целое число со знаком), если пакет имет дополнительный id то это он, в противном случае -1 (в шестнадцатиричном виде 0xFFFF), при работе с логин сервером эти два байта - мусор, дальше беззнаковое 4хбайтовое целое число означающее размер данных в пакете (уже без байт размера и ИДишников), ну и наконец указатель на данные пакета.
На дельфи выглядет это так:
TNetworkPacket = packed record
id: Byte;
res: Byte; // мусор
id2: Smallint;
size: Cardinal;
data: Pointer;
end;

Yegor
17.05.2010, 11:39
xkor, уже пакеты больше 65к есть?

xkor
17.05.2010, 11:56
Yegor, нет, но смысла экономить на памяти в структуре корейци не видели, как собсно и я, а процессор с 4мя байтами работает как минимум не хуже чем с 2мя, а скорее даже лучше...

Yegor
17.05.2010, 12:06
xkor, лучше бы они не экономили впервых хрониках выделяя под поле для хранения количества предметов 8 байт а не 4 :)

xkor
17.05.2010, 14:08
Yegor, ну ктож знал что барыги будут обладать миллиардами)

n1ghtmare
17.05.2010, 14:39
И всетаки не понятно. Пробовал уже всё, и байти переворачивал, и структуру менял, но size стабильно больше 1024 =/
Вот первые 3 пакета логин сервера (числа парами, сначала обычное затем перевернутое)
Пример (не пакет) Рас:
[12:22:41] 5518
[12:22:41] 36373
[12:22:41] 5518
[12:22:41] 36373
[12:22:41] 5518
[12:22:41] 36373
Пример (не пакет) Два:
[12:22:44] 5523
[12:22:44] 37653
[12:22:44] 5523
[12:22:44] 37653
[12:22:44] 5523
[12:22:44] 37653
Пример (не пакет) Три:
[12:22:46] 5355
[12:22:46] 60180
[12:22:46] 5355
[12:22:46] 60180
[12:22:46] 5355
[12:22:46] 60180

Здесь явно мусор потомутчо числа то одинаковые везде, а размер как минимум меняется =/

Yegor
17.05.2010, 14:48
n1ghtmare, а ты уверен что нет ошибки при передаче структуры в программу анализирующую пакеты? Как ты передаешь? Код в студию.

n1ghtmare
17.05.2010, 14:57
Ну я даже стал меседжбоксы выводить из дллки, тоесть проблема не в этом.

Структура:

struct NetworkPacket
{
unsigned char* id;
unsigned char* res;
short id2;
unsigned short size;
unsigned char* data;
};


Хук:

int __fastcall UNetworkHandler_AddNetworkQueue_hook(UNetworkHandl er* This, int /*edx*/, NetworkPacket* packet)
{
// Полезная нагрузка перехвата
mBotHandle = FindWindow(0, L"mBot");
if (mBotHandle)
{
COPYDATASTRUCT cd;
wchar_t str[10];
_itow_s((int)packet->size, str, 8);
cd.lpData = &packet->data;
cd.dwData = 0;
cd.cbData = packet->size;
SendMessage(mBotHandle, 0x004A, 0, (LPARAM)&cd);
MessageBox(0, str, L"Error", MB_OK);
}
else
{
MessageBox(0, L"mBotHandle = 0", L"Error", MB_OK);
}
//-----------------------------------------
return (*UNetworkHandler_AddNetworkQueue)(This, 0/*чтоугодно*/, packet);
}

xkor
17.05.2010, 15:59
n1ghtmare, помойму структура должна быть такой:struct NetworkPacket
{
unsigned char id;
unsigned char res;
short id2;
unsigned int size;
unsigned char* data;
};

n1ghtmare
17.05.2010, 18:42
Проблема решена, спасибо Yegor. А в структуре инт не обязателен, ведь эти 2 байта равны 0.

Yegor
18.05.2010, 04:23
Для выделения памяти в процессе л2 под структуру пакета можно исползовать AllocMem из winApi или надо использовать внетренние средства?

Добавлено через 2 часа 5 минут
Получилось заюзать некоторые из л2 функций, правда пока те что не требую параметров. Тоже критовало, но оказалось что при вызове любой из этих функций надо в регистр ecx записывать адрес UNetworkHandler ;).

Prixmegently
18.05.2010, 22:32
Чтобы добавить свой пакет в очередь с помощью AddNetworkQueue надо "выделять" память с помощью ла2. Murc там писал об этом, сам не пробовал. В остальном все зависит от функции.

Те "функции" что ты юзал - методы __thiscall поэтому и адрес объекта в ECX.

Yegor
25.05.2010, 18:12
Все что спрашивал ранее уже сделал и на удивление работает.

Следующий вопрос, каким образом можно не пустить перехваченный пакет клиенту, у меня 2 соображения:

1) Не вызывать хукнутую AddNetworkQeue, но тут хз как корректно освободить память занятую пакетом.

2) Пакет пустить но изменить его id на несуществующий, но тут неизвестно как поведет себя клиент.

А какие вы знаете варианты?

Prixmegently
25.05.2010, 19:05
Не вызывай оригинал, только не забудь что это функция и нужно вернуть INT (0 например). Проблем вроде не возникало, "блокировал" входящие пакеты давно, точно не помню.

Yegor
25.05.2010, 20:24
Prixmegently, а кто освободит память занимаемую пакетом? Или это делает вызывающая функция?

xkor
25.05.2010, 21:21
Yegor, никто ибо вызывающая функция понятия не имеет когда пакет будет обработан...

Yegor
25.05.2010, 23:27
xkor, а что же делать? :(

Prixmegently
26.05.2010, 00:11
А что это так критично? Ну можешь поизвращаться и заменить содержимое пакета. Тогда он будет обработан и память освободится.

Yegor
26.05.2010, 00:33
Prixmegently, ну как бы потери памяти всегда критичны.

CodeMonkey
20.06.2010, 03:50
а зачем если можно "тыкнуть пакетом" ? =\

как? именно тыкнуть клавишу, а не послать пакет на использование предмета/скилла? подскажи:)

Yegor
20.06.2010, 04:29
CodeMonkey, вытащить скилл(предмет) на панель в игре, послать команду - нажата клавиша F1 .. F12. Окно не обязательно должно быть развернуто. ГГ должен быть убит.

CodeMonkey
20.06.2010, 06:09
с убитым гг послать нажатие кнопки хоть в активное, хоть не в активное окно куча способов. а вот с ним...:eek:
ps: подскажите, пожалуйста, как хукнуть такую функцию
unsigned char __thiscall Class::Func(int)
делаю так:

var
Class_Func_Original: function (i:word):byte;stdcall;
Class:dword;

......................
function Class_Func_Call(i:word):byte;stdcall;
asm
mov ecx,Class
mov esp,ebp
pop ebp
jmp [Class_Func_Original]
end;

function Class_Func_New(unh:integer;i:word):byte;stdcall;
begin
Class:=dword(unh);
Send('Class Func New');
Class_Func_Call(i);
end;

function Class_Func_Hook(i:word):byte;stdcall;
asm
push ecx
push [ebp+8]
push ecx
call Class_Func_New
pop ecx
end;
и клиент вылетает с ошибкой где то в оригинальной функции
Send отрабатывает, отсюда делаю вывод, что функция хукнута, но видимо где-то намудил с параметрами:(

alexteam
20.06.2010, 11:51
убитым гг послать нажатие кнопки хоть в активное, хоть не в активное окно куча способов. а вот с ним
переменуй екзешку приложения на osk.exe и спокойно посылай
нажатие кнопки хоть в активное, хоть не в активное окно

Morfik
21.06.2010, 01:54
мб хто таки разбирался, в структуре User храниться айди профессии? И есть ли он для других чаров(например lvl нету :) )

сори, посмотрев формат пакета UserInfo это int _xunk3;

другой вопрос, зная идентификатор клана, как можно узнать его имя?

Yegor
21.06.2010, 02:01
Сервер не то что lvl но даже количество hp mp для мобов не шлет. Все приведено к основанию 100.000.000. ID професии точно есть, но где - ХЗ.

CodeMonkey
21.06.2010, 04:55
другой вопрос, зная идентификатор клана, как можно узнать его имя?
Можно в AddNetworkQueue поймать пакет с id 89
Через апи клиента хз

alexteam
21.06.2010, 12:11
зная идентификатор клана, как можно узнать его имя
все таки проще с клиентской очереди вытягивать нужное, и вести "учет" чем ковырять память.
ибо как минимум более менее универсально.


procedure PckFromServer_89();stdcall;//PledgeInfo
var
ClanID : integer; ClanName, AllyName:string;
begin
with parser do
begin
offset := 1;
ClanID := RD(offset);
ClanName := RS(offset);
AllyName := RS(offset);
end;
packets.PckPledgeInfo(ClanID, ClanName, AllyName)
end;

ID професии точно есть, но где - ХЗ
в чар\юзеринфо. уровень для чаринфо не приходит.

Yegor
21.06.2010, 15:52
Нужно автоматизировать немного авторизацию на логин сервере с помощью клиента. Пакеты на логин серер шлются тем же методом или есть какой то другой, а то сервер никак не реагирует на мой пакет выбоора сервера из списка.

Prixmegently
27.06.2010, 01:00
Шлются другим, принятые добавляются в очередь тем же.

xkor
27.06.2010, 01:24
мда, походу уже пол форума умеет клиент на кусочки разбирать)

Yegor
27.06.2010, 03:03
xkor, Не пол форума. В этой ветке программинг постоянно обитает только несколько человек, остальные сидят в ветке "Аси" :) .
Пора эту тему и еще пару подобных перенести куда нить подальше.

Sherman
27.06.2010, 07:49
Я не избранный, перенесете, читать будет нечего. :(

xkor
27.06.2010, 13:27
Sherman, не боись, всё на местах останется)

Morfik
27.06.2010, 15:17
public: virtual void __thiscall UNetworkHandler::RequestPledgeWarList(int,int)

подскажет кто назначение параметров int,int ?) надо как то получить список клан варов, тоесть заствить сервер прислать их список

alexteam
27.06.2010, 15:42
1 - хз. второй по идее страница.

CodeMonkey
28.06.2010, 00:37
пакет RequestPledgeWarList:d(Unknown)d(Tab)
мне кажется 1 int - unknown, 2 - Tab :)
1 не ид клана случаем? лови пакет смотри что там первое dword шлется

Yegor
28.06.2010, 01:12
D017=RequestPledgeWarList:h(subID)d(Page)d(Tab)

Морфик ты хочешь оправдать платность своего 4гея?

Morfik
28.06.2010, 01:46
D017=RequestPledgeWarList:h(subID)d(Page)d(Tab)

Морфик ты хочешь оправдать платность своего 4гея?

возможно будут некоторые возможности из радаров, но ничего особого дабы не привлекать внимание инновы.

ЗЫ: описание пакетов то я и сам могу прочитать, тока все равно не очень ясно что такое d(Page)d(Tab) - мб одно из них тип варов (кинули вы, кинули вам, двухсторонки). Да и писать хук лишний раз лень, думал мб кто уже делал.

Yegor
28.06.2010, 02:04
Morfik, надо посмотреть при премем пактов что означеют эти значения

Эдвадко
29.06.2010, 02:05
Это все для того, чтобы высвечивать игроков из кланов с которыми вар ?

Может проще завести файлик с именами игроков и кланов, о которых хочется знать, что они бегают вблизи ?
И при разборе пакетов CharInfo сравнивать имена из файла с именем чара и названием клана ?

Я на клан не проверяю. Только имя и карму.

}
else if (Cmd==0x31) {//31=CharInfo:
...
if (AhtungDetected(name) || (Karma>0)) {
PlaySound("Ahtung.wav", NULL, SND_FILENAME | SND_ASYNC);
swprintf(wstr, 199,L"Ahtung %s %i", name, Karma);
WriteUsrW(wstr);
Chars.SetChar(ObjectID, name, X, Y, RunSpd, MoveMul, 0x0000FF);
} else Chars.SetChar(ObjectID, name, X, Y, RunSpd, MoveMul, 0x7F7FFF);
...

destructor
29.06.2010, 04:24
Эдвадко, просто и красиво но есть минус:
если к тебе подкрался только что принятый криса тыха.....

Эдвадко
29.06.2010, 19:12
Ну, можно имя клана проверять на в хождение в список ахтунгов.
Да и как техашник подберется если у меня радар ?
А в радаре пока самое полезное это Взятие в таргет -

} else if (Cmd==0x23) { //23=TargetSelected:d(ObjectID)d(TargetID)d(X)d(Y)d( Z)d(0)
ParseMasked(SavedArg4, d(ObjectID)d(TargetID)d(X)d(Y)d(Z) 0);
Chars.SetTarget(ObjectID,TargetID);
swprintf(wstr, 199,L"%s -> %s",Chars.GetName(ObjectID), Chars.GetName(TargetID));
static DWORD PreviosID = 0;
if ((TargetID==UserID) && (ObjectID!=PreviosID)) {
PreviosID=ObjectID;
WriteUsrW(wstr);
PlaySound("TargetSelected.wav", NULL, SND_FILENAME | SND_ASYNC);
} else
WriteLogW(wstr);
fprintf(LogFile,"TargetSelected %s -> %s %i,%i,%i\n", NAME(ObjectID), NAME(TargetID), X, Y, Z);



да MoveToPawn:

} else if (Cmd==0x72) { //72=MoveToPawn:d(CreatureObjId)d(TargetObjID)d(Dist ance)d(CreatureX)d(CreatureY)d(CreatureZ)d(TargetX )d(TargetY)d(TargetZ)
ParseMasked(SavedArg4, d(ObjectID)d(TargetID)d(Distance)d(X)d(Y)d(Z)d(ToX )d(ToY)d(ToZ) 0);
Chars.SetXY(ObjectID, X, Y);
Chars.GotoXY(ObjectID, ToX, ToY, Distance);
swprintf(wstr,100,L"%s %i> %s", Chars.GetName(ObjectID), Distance, Chars.GetName(TargetID));
if (TargetID==UserID) WriteUsrW(wstr);
else if (ObjectID!=UserID) WriteLogW(wstr);
fprintf(LogFile,"MoveToPawn %s %i> %s %i,%i,%i -> %i,%i,%i\n", NAME(ObjectID), Distance, NAME(TargetID), X, Y, Z, ToX, ToY, ToZ);


Где по Distance можно прикинуть что именнно противоестественное хочет сделать со мной павнящий чар - 1000 и больше - лучник стрелу хочет всадить в мяккое место, поменьше (около 900-700) - маг скиллом хочет обласкать, еще меньше значит тирант хочет фаербол метнуть, ну а меньше 100 - это значит хотят проткнуть даггером, мечом или пикой.

CodeMonkey
26.07.2010, 20:22
xkor выше писал, как он переходит в Delphi от thiscall к stdcall, примерно так, код работает:
procedure UNetworkHandler_AddNetworkQueue_Call(Packet:PNetwo rkPacket);stdcall;
asm
mov ecx,UNetworkHandler
mov esp,ebp
pop ebp
jmp [UNetworkHandler_AddNetworkQueue_Original]
end;

procedure UNetworkHandler_AddNetworkQueue_New(unh:integer;Pa cket:PNetworkPacket);stdcall;
begin
UNetworkHandler:=Pointer(unh);
UNetworkHandler_AddNetworkQueue_Call(Packet);
end;

procedure UNetworkHandler_AddNetworkQueue_Hook(Packet:PNetwo rkPacket);stdcall;
asm
push ecx
push [ebp+8]
push ecx
call UNetworkHandler_AddNetworkQueue_New
pop ecx
end;

а если вместо функций методы класса? что-то у меня не получается.
TUNetworkHandler = class
private
UNetworkHandler:pointer;
AddNetworkQueue_Original: procedure (Packet:PNetworkPacket);stdcall;
FOnRecievePacket:TRecievePacketEvent;
procedure AddNetworkQueue_Hook(Packet:PNetworkPacket);stdcal l;
procedure AddNetworkQueue_Call(Packet:PNetworkPacket);stdcal l;
procedure AddNetworkQueue_New(unh:integer;Packet:PNetworkPac ket);stdcall;
procedure SetOnRecievePacket(const Value: TRecievePacketEvent);
public
property OnRecievePacket:TRecievePacketEvent read FOnRecievePacket write SetOnRecievePacket;
end;

procedure TUNetworkHandler.AddNetworkQueue_Call(Packet: PNetworkPacket);stdcall;
{
тут хз как делать, запутался уже
при переходе к оригинальной функции в стеке:
значение Packet
указатель на объект TUNetworkHandler
адрес возврата
}
var
p:pointer;
fnc:pointer;
begin
p:=UNetworkHandler;
fnc:=@AddNetworkQueue_Original;
asm
mov eax,fnc
mov ecx,p
mov esp,ebp
pop ebp
jmp eax
end;
end;


procedure TUNetworkHandler.AddNetworkQueue_Hook(Packet: PNetworkPacket);stdcall;
asm
push ecx
push [ebp+12]
push ecx
push Self // указатель на объект
call AddNetworkQueue_New
pop ecx
end;

procedure TUNetworkHandler.AddNetworkQueue_New(unh: integer;
Packet: PNetworkPacket);stdcall;
begin
UNetworkHandler:=Pointer(unh);
if Assigned(FOnRecievePacket) then FOnRecievePacket(Packet);
AddNetworkQueue_Call(Packet);
end;


помогите, пожалуйста. уже мозг кипит:confused:

Yegor
26.07.2010, 21:00
CodeMonkey, может на с++ сделаешь и не будеш мучать мозг?

Если пытаешся что то сделать для руооффа, то у тебя дальше возникнет проблемма совсем другого плана.

CodeMonkey
26.07.2010, 21:16
с c++ знаком мало, поэтому хочется сделать на дельфи.
если не секрет, что за проблема?

Yegor
26.07.2010, 21:25
Проблемма в том что перехват ты скорее всего будешь делать через сплайсинг используя библиотечку advapihook, так вот фрост за это с вероятнотью 101% выдает бан.

xkor
27.07.2010, 01:58
Yegor, хм, а чтож фрост тогда мне ни одного ака не забанил и моим знакомым и клиентам которые юзают мой обход фроста для пакетхака? у меня там как раз именно через тот модуль всё хукается)

CodeMonkey, классы боюсь тут не поюзать, ну по крайней мере напрямую, в "хук-функция" (хз как её более нормально обозвать, ну которая будет вызываться вместо оригинальной) передаётся только то что было передано в оригинальную функцию, следовательно никакой информации о том к какому экземпляру класса принадлежит функция если она метод нету и ничего работать не будет...

единственное возможно если использовать классовые методы (то есть перед procedure/function/полями дописать class) то может и прокатит (я не зная как компилятор такие методы обрабатывает, но по логике они будут обычными функциями), но смысла при этом в классах по моему нет ибо экземпляры класса отменяются...

ЗЫ но можно сделать "хук-функции" которые будут вызывать нужные методы нужного класса, правда учитывая что объект UNetworkHandler в клиенте только один всётаки не вижу в этом смысла

Yegor
27.07.2010, 03:35
xkor, из AdvApiHook использую только внедрение dll, правда в функцию добавил точку входа для возможности выгрузки dll из моей программы (нужно для отладки dll, чтобы постоянно не перегружать клиент).

Поначалу использовал HookProc и получил несколько банов через 30 минут юза длл не отправляя даже ни одного пакета.

xkor
27.07.2010, 04:07
Yegor, ну видимо что то не то хукал, а так эти хуки можно поймать только зная где его ставят...

CodeMonkey
27.07.2010, 07:07
кстати да, сплайсинг через эту библиотеку. через функции уже есть рабочая программа, хукаются функции UNetworkHandler::AddNetworkQueue,
FCanvasUtil::DrawLine,
FPlayerSceneNode::Render
пакеты не отправляю, только снифлю их и рисую по канве клиента. длл инжектится до гг и фроста. тестил недели 3 назад (один раз забыл про клиент и чар сидел часов 6 в игре) - банов не было. недавно искал как юзать блокируемые гг функции (в частности SendMessage), вроде бы нашел, по крайней мере, фукнция при гг работает, но вот тогда посыпались автобаны, причем как то странно: то через 20 минут весь акк уходит, иногда только чар, то бана вообще нет:eek:

Yegor
27.07.2010, 10:41
CodeMonkey, ну сейчас то нет ГГ.

Morfik
29.07.2010, 02:01
Yegor, хм, а чтож фрост тогда мне ни одного ака не забанил и моим знакомым и клиентам которые юзают мой обход фроста для пакетхака? у меня там как раз именно через тот модуль всё хукается)


3 дня писал и отлаживал утилитку, в основе которой был перехват трафика именно хуком (сплайсинг, но не из той библиотеки, хотя смысл с 5 байтами то тот же), дак вот на 3-й день и вылетел бан
Фогейму жаль, но 27.07.2010 в 17:09 Lineage 2 для аккаунта **@** [6584152] заблокирован.

Причина блокировки аккаунта: Использование стороннего ПО.
Блокировка завершится 03.08.2010 в 17:09.
через час посадил 2-го твинка на тойже утилитке с тем же хуком - благополучно просидел 2 часа....
Хз даже дописывать ли утилиту или искать другой вариант хука.

upd:
Хотя не, вру и 2-й заблочили

Фогейму жаль, но 27.07.2010 в 20:45 Lineage 2 для аккаунта *** [6584478] заблокирован.

Причина блокировки аккаунта: Использование стороннего ПО.
Блокировка завершится 03.08.2010 в 20:45.

htozdes
29.07.2010, 03:11
у меня перехвачено больше 100 функций (все через сплайсинг) и никиких банов нет...
так что вы палитесь на чем то другом, либо дело в конкретных реализациях

Yegor
29.07.2010, 23:44
htozdes, какие функции у тебя перехвачены? Нам то нужны самые заветные, AddNetworkQue и т.д. недумаю что фрост проверяет хут какой нибудь там прорисовки чего то.

Да и вообще нафиг хватать более 100 функций если все основное управление клиентом можно производить пакетами?

И еще, когда юзал сплайсинг - длл у меня была сделана на делфи.

Когда перешел на VisualStudio и заюзал другой метод, баны сразу прекратились. Возможно библиотека AdvApiHook мистера покойного Rema слишком общеизвестная и фрост выкупал просто по наличию определенной последовательности машинного кода загруженного в память процесса Л2.

htozdes
30.07.2010, 00:48
ну да у меня радар цветочки на экране рисует!
зато банов нет...

Эдвадко
30.07.2010, 00:51
AddNetworkQueue иногда не срабатывает.
Был у нас местный сервак, где защита была сделана через
правку на лету той-же engine.dll. Уже не помню точно,
но патчилась таблица вызовов обработки пакетов и еще чего-то.
Пришлось перехватывать неэкспортируемую функцию, которые
вызывают все функции разбора пакетов.
Функция обработки хука выглядела страшно -

void UserHookerParseServerPacket(DWORD SavedEAX, PDWORD StackPtr)
{
DWORD SavedRet=0;
DWORD SavedArg0=0;
DWORD SavedArg4=0;
static char str[200];
char *name;
if (StackPtr) SavedRet=*(StackPtr)-(DWORD)hEngineDll+0x2550000;
if (StackPtr+1) SavedArg0=*(StackPtr+1); //Parent_Class_Addr
if (StackPtr+2) SavedArg4=*(StackPtr+2); //parse mask

if (SavedRet == 0x28C591F) name="MacroList";
else if ((SavedRet >= 0x28C5932) && (SavedRet <= 0x28C5A41)) name=0;

else if (SavedRet == 0x28C9AAA) name="SkillList";
else if (SavedRet == 0x28C9B3A) name=0;

else if (SavedRet == 0x28CA290) name="SayPacket2";
else if (SavedRet == 0x28CA31F) name=0;

else if (SavedRet == 0x28CB0B0) name="ShortCutInit";
else if ((SavedRet >= 0x28CB0F4) && (SavedRet <= 0x028CB28B)) name=0;

Но это было давно...

А сейчас вот на офе, при переходе на Фрею изменился формат
пакета CharInfo. Не кардинально, но изменился - Скорость бега стал браться неправильно. Я по дампу пакета нашел и подправил код.
Но может где есть уже описание пакетов Фреи ?

Дальше... Название предметов я надеюсь в будущем брать из клиента
а не из настроечных файлов, а то некоторых нет.
Надеюсь на функцию -
(FARPROC&) UObject__GetName = GetProcAddress(hCore, "?GetName@UObject@@QBEPBGXZ");

И последнее. Может откроете тайну рисования непосредственно в окне клиента. А то в отдельном окошечке приходится карту рисовать.

Когда ставишь хук на UObject_ProcessEvent выдается вот что :
....
[3396] Process_Tick ecx=A93E880 ret=20045B4A
[3396] Process_Tick ecx=A93E880 ret=20045B4A
[3396] Reset ecx=A372940 ret=200626DC
[3396] Process_PreRender ecx=A93E880 ret=20045C89
[3396] Process_PreRender ecx=A93E880 ret=20045C89
[3396] Process_PostRender ecx=A93E880 ret=20045BE9
[3396] Process_PostRender ecx=A93E880 ret=20045BE9
[3396] OnTimer ecx=F91E380 ret=A99503E
...

Пре и пострендер вызываются два раза. В котором из них рисовать ?

Morfik
30.07.2010, 02:18
htozdes, какие функции у тебя перехвачены? Нам то нужны самые заветные, AddNetworkQue и т.д. недумаю что фрост проверяет хут какой нибудь там прорисовки чего то.

Да и вообще нафиг хватать более 100 функций если все основное управление клиентом можно производить пакетами?

И еще, когда юзал сплайсинг - длл у меня была сделана на делфи.

Когда перешел на VisualStudio и заюзал другой метод, баны сразу прекратились. Возможно библиотека AdvApiHook мистера покойного Rema слишком общеизвестная и фрост выкупал просто по наличию определенной последовательности машинного кода загруженного в память процесса Л2.

блин а какая разница делфи/си? ) сплайсинг он и в африке сплайсинг - Е9 и 4 байта адреса куда прыгать в начале функции - явный признак поставленого на нее хука :)

пока нашел другой метод хука,работает, осталось потестить на предмет банов)

Добавлено через 6 минут


И последнее. Может откроете тайну рисования непосредственно в окне клиента. А то в отдельном окошечке приходится карту рисовать.

Когда ставишь хук на UObject_ProcessEvent выдается вот что :
....
[3396] Process_Tick ecx=A93E880 ret=20045B4A
[3396] Process_Tick ecx=A93E880 ret=20045B4A
[3396] Reset ecx=A372940 ret=200626DC
[3396] Process_PreRender ecx=A93E880 ret=20045C89
[3396] Process_PreRender ecx=A93E880 ret=20045C89
[3396] Process_PostRender ecx=A93E880 ret=20045BE9
[3396] Process_PostRender ecx=A93E880 ret=20045BE9
[3396] OnTimer ecx=F91E380 ret=A99503E
...

Пре и пострендер вызываются два раза. В котором из них рисовать ?

http://coderx.ru/showthread.php?t=948&page=2

xkor
30.07.2010, 02:25
Morfik, сплайсинг по моему не обязательно через джамп делается, можно и через кал (но тогда потребуется дополнительный код в начале нашей функции) и через пуч + рет (но этот вариант занимает 6 байт а не 5 в начале перехватываемой функции)

Morfik
30.07.2010, 02:58
Morfik, сплайсинг по моему не обязательно через джамп делается, можно и через кал (но тогда потребуется дополнительный код в начале нашей функции) и через пуч + рет (но этот вариант занимает 6 байт а не 5 в начале перехватываемой функции)

В любом случае норм функции с E9 (джамп) и 15FF(колл) не начинаються:) вообщем спалить сам факт хука несложно.

xkor
30.07.2010, 04:24
Morfik, с джампа возможно, а вот калом и уж тем более пучем спокойно, хотя да, спалить не сложно если знать где искать, а вот если не знать хер спалишь
я например одну функцию хукаю не в начале а посередине ибо там данные в более удобной форме, и вот посмотрел бы я как фрост это палить будет не зная конекретно где я хук поставил

Yegor
30.07.2010, 10:48
xkor, при желании думаю не сложно спалить. Почему бы фросту не проверять все тело критических функций на предмет совпадения с оригиналом, ну так чек сумму какую нибудь сверял бы куска кода.

Добавлено через 6 минут
Morfik, ты не хотел бы еще немного поработать над стабильностью работы своей программы, а то я и много знакомых ее недавно купили в панике обновления 20.07 но теперь ей не пользуемся. С ней ну слишком часто клиент л2 падает с критом (субьективно с аси критует гораздо реже). Видимо в длл ты что то не предусмотрел.

Morfik
30.07.2010, 13:38
Добавлено через 6 минут
Morfik, ты не хотел бы еще немного поработать над стабильностью работы своей программы, а то я и много знакомых ее недавно купили в панике обновления 20.07 но теперь ей не пользуемся. С ней ну слишком часто клиент л2 падает с критом (субьективно с аси критует гораздо реже). Видимо в длл ты что то не предусмотрел.

Пока не напишут больше конкретики с какими опциями и с каким текстом крита летают - помоч наврятли смогу.

И вообще это не место для ее обсуждения так что сори за оффтоп :)

Zul
31.07.2010, 23:43
Morfik, с джампа возможно, а вот калом и уж тем более пучем спокойно, хотя да, спалить не сложно если знать где искать, а вот если не знать хер спалишь
я например одну функцию хукаю не в начале а посередине ибо там данные в более удобной форме, и вот посмотрел бы я как фрост это палить будет не зная конекретно где я хук поставил

А ты когда хук делаешь VirtualProtect и т.п. зовешь?
Если да, то могут легко спалить захучив его. Более того тестить то они могут на любой ОС, в часности на x32, где хук можно и в драйвер засунуть.

xkor, при желании думаю не сложно спалить. Почему бы фросту не проверять все тело критических функций на предмет совпадения с оригиналом, ну так чек сумму какую нибудь сверял бы куска кода.

Не знаю как в самом фросте, но вот код линеечных функций немного динамический. Т.е. там суются nop'ы в случайные места, каждый раз в разные.

mira
13.08.2010, 14:19
вы методы нетворкхандлера чтоли сплайсите перед каждым вызовом? Сплайсинг вообще не нужен или нужен 1 раз чтоб получить указатель на сам обьект

Эдвадко
14.08.2010, 09:50
У меня другая проблема - После последнего обновления на руоффе не могу найти процесс куда внедряться.
Такое ощущение, что процесс LineageII.exe запускает l2.bin как один из своих потоков да еще и прячет его. Пытаюсь поймать его тестовыми прогами типа этой -{$APPTYPE CONSOLE}
uses Windows, NativeAPI;

var
ProcInfo, ProcIter : PSYSTEM_PROCESSES;

var i : Integer = 1;

{
Системный вызов ZwQuerySystemInformation для Windows XP.
}
Function XpZwQuerySystemInfoCall(ASystemInformationClass: dword;
ASystemInformation: Pointer;
ASystemInformationLength: dword;
AReturnLength: pdword): dword; stdcall;
asm
pop ebp
mov eax, $AD
call @SystemCall
ret $10
@SystemCall:
mov edx, esp
sysenter
end;


procedure GetSyscallProcessList();
var
Info: PSYSTEM_PROCESSES;
mPtr: pointer;
mSize: dword;
St: NTStatus;
begin
mSize := $4000;
repeat
GetMem(mPtr, mSize);
St := XpZwQuerySystemInfoCall(SystemProcessesAndThreadsI nformation, mPtr, mSize, nil);
if St = STATUS_INFO_LENGTH_MISMATCH then
begin
FreeMem(mPtr);
mSize := mSize * 2;
end;
until St <> STATUS_INFO_LENGTH_MISMATCH;
if St = STATUS_SUCCESS then
begin
Info := mPtr;
repeat
Writeln(i:3,' ',WideCharToString(Info^.ProcessName.Buffer)) ;
//NewItem^.ProcessId := Info^.ProcessId;
//NewItem^.ParrentPID := Info^.InheritedFromProcessId;
Info := pointer(dword(info) + info^.NextEntryDelta);
Inc(i);
until Info^.NextEntryDelta = 0;
end;
FreeMem(mPtr);
end;



begin
GetSyscallProcessList();
end.



Но не вижу нужного процесса.

Morfik
14.08.2010, 12:07
вы методы нетворкхандлера чтоли сплайсите перед каждым вызовом? Сплайсинг вообще не нужен или нужен 1 раз чтоб получить указатель на сам обьект

эм мы как бы сплайсим для отлова результатов работы функции)

а хукать ради получения указателя на нетворк хендл ниче не надо :)
по мне так легче его кое откуда прочитать.

htozdes
14.08.2010, 12:25
Но не вижу нужного процесса.

Вообще такая проблема наблюдается только на x86 на x64 процессы видно..
ну а проблему решить можно так:
поставь SetWindowsHookEx на свою длл либо на пустую дллку-загрузчик:

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch(fdwReason)
{
...
case DLL_PROCESS_ATTACH:
if (0!=GetModuleHandle("l2.bin")) LoadLibrary("robat.dll");
...
}
return true;
}

но мне кажется это маразм =)
проще поставить ХП64 т.к. там всегда было меньше проблем с фростом и ГГ

mira
15.08.2010, 17:10
эм мы как бы сплайсим для отлова результатов работы функции)

а хукать ради получения указателя на нетворк хендл ниче не надо :)
по мне так легче его кое откуда прочитать.

зачем ее сплайсить если можно подменить в VMT и обрабатывать входные данные и результат

прочитать по фиксированному адресу это плохая манера если уж иначе нельзя ))

xkor
16.08.2010, 00:30
mira, а если надо не в начало функции вклиниться?)
и вообще чего пристал, как хотим так и хукаем, наши хуки)

mira
16.08.2010, 09:55
сами же грите сплайсинг палитса
я и спросил зачем он нужен если надежней заменить 1 указатель и смареть(править) входные данные и результат.
Ну ваши хуки так ваши не буду отвлекать :)

xkor
16.08.2010, 11:07
mira, да он тока у егора палится...

Yegor
16.08.2010, 22:26
xkor, дык и не юзаю его поэтому, а ведь действительно у меня палился. 4 бана подряд автоматом.

mira
20.08.2010, 02:27
кто знает эта функция
SendPacket()
в принцыпе потокозащищенная? если ее вызывает клиент и одновременно прога.. или нада в критическую секцию упаковвывать?
то при активной отправке прогой пакетов клиент бывает вылетает критом

Эдвадко
20.08.2010, 07:37
Лучше не надеяться на многопоточную реализацию функции.
Непонятно как СriticalSection поможет ?
По мне по мне так надо ставить перехват на функцию и проверять
залез в нее кто-то или она свободна.

Sherman
20.08.2010, 08:37
кто знает эта функция
SendPacket()
в принцыпе потокозащищенная? если ее вызывает клиент и одновременно прога.. или нада в критическую секцию упаковвывать?
то при активной отправке прогой пакетов клиент бывает вылетает критом

В моих наработках ИГ сдавалки манора ошибок не возникало, хотя между пакетами до 100 мс было.

mira
20.08.2010, 09:55
судя по тому что вылетает стандартное окно 'генерал протекшн фолт' фейлитса поток клиента, в моем свой обработчик.
Причем крит быват во время эпиков и варов как правило шс это самый динамичный бот
если бы было чето напутано в вызове сендпакет ваще бы было не играбельно. Темболее перехватчик проверяет целостность стека - если чет не то выдаст ошбку

Guzh
06.09.2010, 18:38
Спасибо за тему, очень познавательная. Сделал свой радар и бота, только возникли вопросы:
- Как расчитать текущее положение чара при движении?
- Есть ли способ (если есть то как реализовать) узнать направление камеры (не направление персонажа)
- Как установить квестовскую стрелочку на определенного нпц/чара (какую функцию вызвать или что-то гдето поменять)
- Ктонить пробовал присоеденить к боту геодату? Если да, то какую и каким способом

Был бы очень признателен, если бы Вы помогли мне на них ответить =)

mira
06.09.2010, 20:45
при просчете траектории была уже тема насчет вычисления движения бота,правдо до конца не раскрытая
странно зачем вычислять камеру?)
квестовая стрелочка ставитса вроде из данных клиента и на самом деле не указывает на нпс а только на предопределенную точку на карте где он должен стоять.
про геодату тоже вопрос задавалса, можеш поапать тему

xkor
06.09.2010, 21:29
про геодату тут http://coderx.ru/showthread.php?t=5039 и ещё там во втором посте ссылка

Guzh
08.09.2010, 11:53
странно зачем вычислять камеру?)


Камеру вычислять хочу для удобного радара. Чтбы при движении камерой менялся радар, а не в зависимости от того,куда я смотрю.


квестовая стрелочка ставитса вроде из данных клиента и на самом деле не указывает на нпс а только на предопределенную точку на карте где он должен стоять.

Как установить эту точку?)

Добавлено через 1 минуту
про геодату тут http://coderx.ru/showthread.php?t=5039 и ещё там во втором посте ссылка

Спасибо. Все прекрасно получилось, осталось только присобачить к боту геодату.

Эдвадко
08.09.2010, 22:18
А насчет движения я делаю так

void GotoXY(DWORD id, int ToX, int ToY, int Pawn) {
FINDID(id) {
ctable *p=&table[i];
double Speed;
double dX=ToX-p->X;
double dY=ToY-p->Y;
double d = sqrt(dX*dX+dY*dY);
if ((d>Pawn) && (d>20)) {
if (p->RunSpd<=0) Speed=10; else Speed=p->MoveMul*p->RunSpd/12;
p->dX=(Speed*dX)/d; p->dY=(Speed*dY)/d;
p->MoveTicks=(d-Pawn)/Speed;
p->PawnX=ToX-(Pawn/d)*dX; p->PawnY=ToY-(Pawn/d)*dY;
p->ToX=ToX; p->ToY=ToY;
p->Visible=1;
}
}
}
......................
void Tick() {
LOOPI {
if (table[i].PickTicks) table[i].PickTicks--;
if (table[i].Visible && table[i].MoveTicks-->0) {
table[i].X=table[i].X+table[i].dX;
table[i].Y=table[i].Y+table[i].dY;
}
}
}
........................
case WM_TIMER:
Chars.Tick();
InvalidateRect(hWnd,0,TRUE);
...
break;
case WM_CREATE:
...
SetTimer(hWnd,0,100,0);
break;
.........................
} else if (Cmd==0x72) { //72=MoveToPawn:d(CreatureObjId)d(TargetObjID)d(Dist ance)d(CreatureX)d(CreatureY)d(CreatureZ)d(TargetX )d(TargetY)d(TargetZ)
ParseMasked(SavedArg4, d(ObjectID)d(TargetID)d(Distance)d(X)d(Y)d(Z)d(ToX )d(ToY)d(ToZ) 0);
Chars.SetXY(ObjectID, X, Y);
Chars.GotoXY(ObjectID, ToX, ToY, Distance);
swprintf(wstr,100,L"%s %i> %s", Chars.GetName(ObjectID), Distance, Chars.GetName(TargetID));
if (TargetID==UserID) WriteUsrW(wstr);
else if (ObjectID!=UserID) WriteLogW(wstr);
fprintf(LogFile,"MoveToPawn %s %i> %s %i,%i,%i -> %i,%i,%i\n", NAME(ObjectID), Distance, NAME(TargetID), X, Y, Z, ToX, ToY, ToZ);

//-----------------------------------------
} else if (Cmd==0x2f) { //2F=MoveToLocation:d(CharID)d(ToX)d(ToY)d(ToZ)d(Ori ginX)d(OriginY)d(OriginZ)
ParseMasked(SavedArg4, d(CharID)d(ToX)d(ToY)d(ToZ)d(X)d(Y)d(Z) 0);
Chars.SetXY(CharID, X, Y);
Chars.GotoXY(CharID, ToX, ToY, 0);
fprintf(LogFile,"MoveToLocation %s %i,%i,%i -> %i,%i,%i\n", NAME(CharID), X, Y, Z, ToX, ToY, ToZ);


......................
} else if (Cmd==0x0C) {//0C=NpcInfo:
//0C=NpcInfo:d(ObjectID)d(NpcTypeId:Get.NpcId)d(IsAt tackable)d(X)d(Y)d(Z)d(Heading)d(0)
ParseMasked(SavedArg4, d(ObjectID)d(ClassID)b(4)d(X)d(Y)d(Z)d(Heading)b(4 )
//d(MatkSpd)d(PatkSpd)d(RunSpd)d(WalkSpd)d(SwimRunSp d)d(SwimWalkSpd)d(FlRunSpd)d(FlWalkSpd)d(FlyRunSpd )d(FlyWalkSpd)
d(MatkSpd)d(PatkSpd)d(RunSpd)d(WalkSpd) 3,6*4,
//f(MoveMultiplier)f(AtkSpdMultiplier)f(CollisionRad ius)f(CollisionHeight)
8,&MoveMul, 3,8+8+8+4+4+4+5, 5,name, 5,name, 0);
//d(IDRhand:Get.ItemID)d(0)d(IDLhand:Get.ClassID)c(1 )c(isRunning)c(isInCombat)c(isALikeDead)c(Invisibl e:0,1)
//s(VisibleName)s(VisibleTitle)d(0)d(0)d(0)d(Abnorma lEffect)d(ClanID)d(CrestID)d(0)d(0)c(0)c(Team:1-blue,2-Red)
//f(CollisionRadius)f(CollisionHeight)d(0)d(0)d(0)d( 0)c(01)c(01)d(0)

//swprintf(wstr,100,L"%s %i %i %i %i %f", GetNpcName(ClassID), MatkSpd, PatkSpd, RunSpd, WalkSpd, MoveMul);
//WriteUsrW(wstr);
Chars.SetChar(ObjectID, GetNpcName(ClassID), X, Y, RunSpd, MoveMul, 0xffffff);
fprintf(LogFile,"NpcInfo %s %i %g\n", NAME(ObjectID), RunSpd, MoveMul);

Понятно, что через анус, и что где-то в клиенте все данные есть...

Grinch
09.09.2010, 00:00
Понятно, что через анус, и что где-то в клиенте все данные есть...
хз в чем ты писал, но в делфи тегах это лучше смотрится

alexteam
09.09.2010, 00:05
в пхп лучше... во всяком случае ближе к С

xkor
09.09.2010, 00:46
alexteam, а С++ ещё ближе к С++)
ЗЫ только вот открывающиеся квадратные скобки надо бы будет как нить пофиксить...

ALF
18.09.2010, 23:28
Кто разобрался с написанием радара на делфи?

Guzh
02.10.2010, 17:17
Хотелось бы еще вопросик задать. Вот читал, что у рэнджера есть функция антихайда. Ктонить пробовал реализовать его? Можете подсказать как =)

xkor
02.10.2010, 19:08
Вот читал, что у рэнджера есть функция антихайда.и в чем она заключается?

Guzh
03.10.2010, 21:55
Ну вроде рэнджер позволяет видеть дагеров,которые находятся в хайде (сам не пользовался,но гдето видел инфу об этом=) ).

ALF
04.10.2010, 01:26
Скиньте плиз как вы вызываете DrawLine и DrawString

xkor
04.10.2010, 01:34
Guzh, оО, с каких пор в линяге дагеры имеют скил на невидимость??

Morfik
04.10.2010, 02:22
Guzh, оО, с каких пор в линяге дагеры имеют скил на невидимость??

прикалуешся? :)
http://base.will-ally.ru/modules.php?name=db&op=skills&type=Elf&parent_id=v&skillid=922&lvl=1&ids=101&lng=ru

xkor
04.10.2010, 10:09
Morfik, ну дык я не играл уже 2 года)

Maxno
04.10.2010, 17:20
xkor, сделали, теперь как гмы юзают хайд и делаю что хотят :)

mira
04.10.2010, 19:19
луший антихайд это AOE скилл без таргета)
не представляю как это можно обойти прогой. сервер игнорирует запрос
на выделение в таргет перса находящегося в хайде, не шлет никаких пакетов о его перемещении...

если чтото есть или когдато работало это скорей из области багоюза :cool:

xkor
04.10.2010, 19:38
mira, возможно какой то пакетик всё таки об этом невидимке проскакивает, типо что он в таргет тебя или ещё кого взял.

mira
04.10.2010, 21:55
mira, возможно какой то пакетик всё таки об этом невидимке проскакивает, типо что он в таргет тебя или ещё кого взял.

даже если так то толку. его то всеравно не даст сервер взять в таргет.
самое мудное что через /target ГМа можно было выделить в инвизе :D

htozdes
04.10.2010, 22:57
Дагер в хайде отлично берется в таргет даже если его не видно, да и пакеты о всех его действиях сервер продолжает отправлять
http://files.mail.ru/OPFPJU снято больше года назад и до сих пор работает без каких либо изменений..

mira
05.10.2010, 00:43
у меня чет не бралса на таргет :confused:

xkor
05.10.2010, 14:35
mira, нужен особый, уличный таргет)))

Guzh
06.10.2010, 03:02
Не дождался помощи,пришлось сделать самому. Все отлично работает. В таргет дагера можно взять, но ничего нельзя сделать, т.е. нажимаешь атаковать таргет слетает. Осталось научиться рисовать в окне линейки. КТонить поможет?=) Способ директХ не подходит, так как там нужно хукать до инициализации, а я подключаюсь к игре после.

Yegor
06.10.2010, 16:42
Guzh, открой самое начало этой темы, там же написано как рисовать используя функции л2.

Guzh
06.10.2010, 16:53
Guzh, открой самое начало этой темы, там же написано как рисовать используя функции л2.
Это ответ такой?=) Понятно все с вами=). Перефразирую.
Вначале написано,что рисуем после FPlayerSceneNode::Render(class FRenderInterface *), используем FCanvasUtil. Вопрос, как использовать FCanvasUtil ? Создаем вот этим FCanvasUtil::FCanvasUtil(FRenderTarget *,FRenderInterface *,EVertexShader,EPixelShader). Подскажите что передавать в виде параметров? Где их взять.
Или так, есть ли способ и как рисовать в окне игры через DX но перехватывать после инициализации?

mira
06.10.2010, 18:17
Это ответ такой?=) Понятно все с вами=). Перефразирую.
Вначале написано,что рисуем после FPlayerSceneNode::Render(class FRenderInterface *), используем FCanvasUtil. Вопрос, как использовать FCanvasUtil ? Создаем вот этим FCanvasUtil::FCanvasUtil(FRenderTarget *,FRenderInterface *,EVertexShader,EPixelShader). Подскажите что передавать в виде параметров? Где их взять.
Или так, есть ли способ и как рисовать в окне игры через DX но перехватывать после инициализации?

написали ведь что проще перехватить уже готовый обьект чем создавать новый, зачем тебе лезть в дебри

Guzh
06.10.2010, 19:52
написали ведь что проще перехватить уже готовый обьект чем создавать новый, зачем тебе лезть в дебри
А можно какую-нибудь более конструктивную помощь?

Добавлено через 59 минут
Не получается почемуто воспользоваться уже готовым канвасом

Есть кусок кода:

___:2025114F call ??0FCanvasUtil@@QAE@PAVFRenderTarget@@PAVFRenderIn terface@@W4EVertexShader@@W4EPixelShader@@@Z ; FCanvasUtil::FCanvasUtil(FRenderTarget *,FRenderInterface *,EVertexShader,EPixelShader)
...
___:202511BE call ?DrawTile@FCanvasUtil@@QAEXMMMMMMMMMPAVUMaterial@@ ABVFColor@@@Z ; FCanvasUtil::DrawTile(float,float,float,float,floa t,float,float,float,float,UMaterial *,FColor const &)
___:202511C3 mov byte ptr [ebp+74h+var_78], 0Bh
___:202511C7 lea ecx, [ebp+74h+var_254]
___:202511CD call ??1FCanvasUtil@@UAE@XZ ; FCanvasUtil::~FCanvasUtil(void)

Перехватываю:

___:2025114F call ??0FCanvasUtil@@QAE@PAVFRenderTarget@@PAVFRenderIn terface@@W4EVertexShader@@W4EPixelShader@@@Z ; FCanvasUtil::FCanvasUtil(FRenderTarget *,FRenderInterface *,EVertexShader,EPixelShader)
...
___:202511BE call ?DrawTile@FCanvasUtil@@QAEXMMMMMMMMMPAVUMaterial@@ ABVFColor@@@Z ; FCanvasUtil::DrawTile(float,float,float,float,floa t,float,float,float,float,UMaterial *,FColor const &)
___:202511C3 mov byte ptr [ebp+74h+var_78], 0Bh
___:202511C7 JMP NEAR MY_HOOK
___:202511CC nop
___:202511CD call ??1FCanvasUtil@@UAE@XZ ; FCanvasUtil::~FCanvasUtil(void)

мой кусок
My_Hook:
CODE:0FD436E0 lea ecx, [ebp-1E0h]
CODE:0FD436E6 jmp loc_FD436BC


CODE:0FD436BC push 202511CDh
CODE:0FD436C1 retn


Вылезает ошибка:
History: CAuthSocket::OnUserNetmessage <- UWindowsViewport::ViewportWndProc <- WWindow::StaticProc <- DispatchMessage <- 00550B00 1290 <- MessagePump <- MainLoop

хз почему

mira
06.10.2010, 20:37
невтыкаю что за маневры выполняет my_hook )))
ложит в ЕСХ какуюто локальную переменную
сует в стек как я понял адрес возврата.

в итоге ??1FCanvasUtil@@UAE@XZ вызываетса с какимто непонятным "экземпляром класса" когда в ЕСХ должен лежать обьект из [ebp+74h+var_254]

Добавлено через 13 минут

procedure __AddNetworkQueue_Hook;
begin
asm
pushad
mov EAX , ECX
mov UNETWORKHANDLER_a, EAX // сохряняем в глобальной переменной указатель на обьект end;
EnterCriticalSection(CSSS);
//получаем указатель на сендпакет
pSendPacket:=PPointer(Pdword(PDword(dword(UNETWORK HANDLER_a)+$48)^)^+$6C)^;
ppSendPacket:=Pointer(Pdword(PDword(dword(UNETWORK HANDLER_a)+$48)^)^+$6C);
pNetworkObject:=Ppointer(dword(UNETWORKHANDLER_a)+ $48)^;
// снимает сплайсинг отменяем перехват
TTM.ResetTrap(phtrap);
phtrap:=nil;
LeaveCriticalSection(CSSS);
IDirect3DDevice9H(idev_).StrWrite('done : packet trap unmounted',0);
// устанавливаем перехват адднетворк... через VMT таблицу (сплайс для нас слишком грубо)
InitVMTHandlers;
// устанавливаем хук на сендпакет тоже
TL2C.nhandler._hphandler:=TTM.SetupIndirectTrap(po inter(ppSendPacket),0,@_sendpacket_trap,@_postsend packet_trap,false);
//восстанавливаем все регистры и стек
asm
popad
xor eax, eax
not eax
ret 004
end;
end;


function HandleNetworkTrap:BOOL;
var
forig : pointer;
dll:DWORD;
begin
EnterCriticalSection(CSSS);
try
try
result:=false;
if UNETWORKHANDLER_a<>nil then exit;
dll:=GetModuleHandle('engine.dll');
forig:=GetProcAddress(dll,'?AddNetworkQueue@UNetwo rkHandler@@UAEHPAUNetworkPacket@@@Z');
//делаем хук через сплайсинг
phtrap:=TTM.SetupHardTrap(forig,0,@__AddNetworkQue ue_Hook);
if phtrap<>nil then begin
IDirect3DDevice9H(idev_).StrWrite('done : packet trap mounted',0);
result:=true;
end;
if phtrap=nil then begin
IDirect3DDevice9H(idev_).StrWrite('error : mounting packet trap',0);
exit;
end;
finally
LeaveCriticalSection(CSSS);
end;
except
smessage('error : setup trap critical error');
end
end;


а перехватить ченеть типа этого невозможно?)
так я получаю указатели на обьект нетворкхандлера

Guzh
06.10.2010, 20:47
my_hook ничего не делает,просто пропускает через себя
а в CX и лежит [ebp+74h+var_254], только запись другая [ebp-1E0h]

Добавлено через 10 минут

а перехватить ченеть типа этого невозможно?)
так я получаю указатели на обьект нетворкхандлера

Там я норм перехватываю, а тут я пытаюсь впихнуться в момент,когда объект Fcanvasutils уже создан, но еще не удален, как вверху предлагали воспользоваться уже готовым объектом

mira
06.10.2010, 20:53
my_hook ничего не делает,просто пропускает через себя
а в CX и лежит [ebp+74h+var_254], только запись другая [ebp-1E0h]

Добавлено через 10 минут


Там я норм перехватываю, а тут я пытаюсь впихнуться в момент,когда объект Fcanvasutils уже создан, но еще не удален, как вверху предлагали воспользоваться уже готовым объектом

уверен что var_254 этьо константа? и вообще что адреса не меняютса, ты же пользуеш прямую адресацию а не относительную

Guzh
06.10.2010, 21:39
уверен что var_254 этьо константа? и вообще что адреса не меняютса, ты же пользуеш прямую адресацию а не относительную

Программа перед тем,как сделать хук,скопировала то,что там было ( lea ecx, [ebp-1E0h]) и вычислила адрес для возврата и добавила его в пуш(CODE:0FD436BC push 202511CDh). Если адрес меняется только при загрузке, то все норм будет, а если в течении сеанса меняется(что наврядли), то будет ошибка

mira
08.10.2010, 20:05
попробывал порисовать ченеть средствами клиента, вчера поигралса..
начал с линии и квадрата... получилось как ни странно только долго искал че хукнуть чтоб CanvasUtil выловить. клиент видимо его не пользует или пользует нечасто)
в итоге хукнул ??0FCanvasUtil@@QAE@PAVFRenderTarget@@PAVFRenderIn terface@@W4EVertexShader@@W4EPixelShader@@@Z

это по всем понятиям должен быть конструктор..

функция рисующая квадрат получилась такой-

procedure uDrawRect(x,y,x1,y1:single; color : DWORD);
var
forig : pointer;
dll:DWORD;
begin
dll:=GetModuleHandle('engine.dll');
forig:=GetProcAddress(dll,'?DrawRect@FCanvasUtil@@ QAEXMMMMVFColor@@@Z');
asm
push color
push y1
push x1
push y
push x
mov ecx,uCanvas // объект возвращенный в EAX после хука конструктора
call forig
end
end;

рисовать строку не пробывал, нада шрифт создавать или тоже хукать гдето) времени уже не было

mira
09.10.2010, 01:27
строчки тоже нарисовал простейшие средствами клиента..


procedure uDrawString(x,y :integer ; pText:PWideChar; pfnt:pointer; color : DWORD);
var
forig : pointer;
dll:DWORD;
begin
dll:=GetModuleHandle('engine.dll');
forig:=GetProcAddress(dll,'?DrawString@FCanvasUtil @@QAEHHHPBGPAVUFont@@VFColor@@@Z');
asm
push color
push pfnt
push pText // шрифт взят из перехвата ??0UFont@@QAE@XZ (хз че за функция и че за шрифт) не заморачивалса)
push y
push x
mov ecx,uCanvas // в есх помещаем добытый ранее экземпляр класса
call forig
end
end;

врятли буду пользовать эти функции клиента, просто проверил для общего познания что работают =))))))))

Guzh
10.10.2010, 15:34
Спасиб, завтра гляну =)

Guzh
25.10.2010, 12:18
Еще вопросик появился. Кто-нибудь добавлял/уничтожал пакет приходящие в функцию AddNetworkQueue ? Через использование FArray::Add(int,int) и FArray::Remove(int,int,int) делали это или как-то по-другому?

mira
27.10.2010, 18:27
сначала я менял ид ненужных пакетов на $1F - action failed
клиент сам разруливал удалять не удалять. потом просто перестал вызывать для пакета оригинальную AddNetworkQueue изменений не заметил в работе. я чет думал что пакет нада удалять если он попал в DispatchNetworkQueue только :rolleyes:

Yegor
30.10.2010, 11:42
mira, менять id на $1F это хорошо придумано. Если просто не вызывать оригинал AddNetworkQeue думаю будут утечки памяти.

Кто нибудь разобрался каким образом через клиент отправить пакет на логин сервер (нужно для правильного выбора сервера), а то стандартный SendPacket игнорируется?

Morfik
30.10.2010, 12:12
Кто нибудь разобрался каким образом через клиент отправить пакет на логин сервер (нужно для правильного выбора сервера), а то стандартный SendPacket игнорируется?
может ?RequestServerLogin@UNetworkHandler@@UAEHAAVL2Para mStack@@@Z покатит? вот тока формат аргумента хз какой (class L2ParamStack &)

Yegor
30.10.2010, 13:59
Morfik, надо покурить какую функцию использует в свою очередь RequestServerLogin

Prixmegently
22.11.2010, 20:18
RequestAuthLogin -> RequestServerList -> RequestServerLogin

ancient
09.01.2011, 21:58
Разбираюсь с перехватом функций клиента и возникла непонятная ситуация: некоторые функции хукаются нормально, а некоторые вызывают криты в клиенте без видимых на то причин.

Вот пример кода:
#include <Windows.h>

#pragma pack(push, 1)
struct jmp_struct {
BYTE instruction;
DWORD argument;
};
#pragma pack(pop)

BYTE old[5];
DWORD written = 0;
jmp_struct jump;

typedef DWORD (__stdcall *t_Func)(void* param1/*, int param2*/);
t_Func Original_Func = NULL;

DWORD WINAPI Intercept_Func(void* param1/*, int param2*/) {
// Сохранение контекста класса перехваченного метода.
DWORD this_ptr = NULL;
__asm mov this_ptr, ecx;

// Восстанавливаем 5 первых байт функции.
WriteProcessMemory(GetCurrentProcess(), (void*)Original_Func, (void*)&old, 5, &written);

MessageBox(0, L"Hooked", L"", MB_OK);

// Восстановление в регистр ecx контекста класса перехваченного метода.
__asm mov ecx, this_ptr;
DWORD originalResult = Original_Func(param1/*, param2*/);

// Снова заменяем 5 байт функции на команду перехода на нашу функцию
WriteProcessMemory(GetCurrentProcess(), (void*)Original_Func, (void*)&jump, 5, &written);

return originalResult;
}

void InterceptFunctions() {
HMODULE hEngine = GetModuleHandleA("engine.dll");

/* DWORD UGameEngine::OnSocialAction(User* user, int id) */
//Original_Func = (t_Func)GetProcAddress(hEngine, "?OnSocialAction@UGameEngine@@UAEHPAUUser@@H@Z"); // Работает

/* DWORD UNetworkHandler::AddNetworkQueue(NetworkPacket* networkPacket) */
Original_Func = (t_Func)GetProcAddress(hEngine, "?AddNetworkQueue@UNetworkHandler@@UAEHPAUNetworkPa cket@@@Z"); // Не работает

if(Original_Func == 0) {
MessageBox(NULL, L"Can't get address", L"Error!", MB_OK);
return;
}

jump.instruction = 0xE9;
jump.argument = (DWORD)&Intercept_Func - ((DWORD)Original_Func + 5); // Смещение для jmp = <адрес назначения> - (<адрес jmp> + sizeof(BYTE) + sizeof(int))

ReadProcessMemory(GetCurrentProcess(), (void*)Original_Func, (void*)&old, 5, &written);
WriteProcessMemory(GetCurrentProcess(), (void*)Original_Func, (void*)&jump, sizeof(jmp_struct), &written);
}


BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {
if(ul_reason_for_call == DLL_PROCESS_ATTACH ) {
// MessageBox(0, L"Injected", L"", MB_OK);
InterceptFunctions();
}
return TRUE;
}


Перехват OnSocialAction (как и многих других функций) работает вполне успешно, а вот AddNetworkQueue перехватить не получается. В чем может быть дело?

P.S. Крит возникает в момент вызова оригинальной функции из функции-перехватчика, т.е сразу после MessageBox(0, L"Hooked", L"", MB_OK);

Guzh
11.01.2011, 16:08
У меня опять проблема, не могу заставить перса в нужное место идти.
Передаю параметры в экспортируемую функцию UNetworkHandler__MoveBackwardToLocation, и персонаж идет хз куда,но не туда,куда мне надо. Помогите найти проблему. Отсылаю так:
procedure my_MoveTo(x,y,z,x1,y1,z1:integer); stdcall;
begin
asm
push z1
push y1
push x1
push z
push y
push x
mov ecx, UNH
call adrMoveTo
end;
end;
где x,y,z координаты куда нужно попасть, а x1,y1,z1 где мы есть

xkor
11.01.2011, 19:41
Guzh, уверен что надо
push z1
push y1
push x1
push z
push y
push x
а не
push x
push y
push z
push x1
push y1
push z1
?
хотя тут то наверно правильно, но там разве только 6 параметров, вроде же ещё один параметр должен быть указывающий мышкой или клавой было инициированно движение

Эдвадко
11.01.2011, 23:09
UNetworkHandler::MoveBackwardToLocation(FVector,FV ector)
; int __stdcall UNetworkHandler__MoveBackwardToLocation(float, float, float, float, float, float)
Это в пакете intы а в параметрах функции floatы.

А про мышь там оказывется и нет ничего. Тото я при хуке не мог понять почему там то ноль то единица, хотя кнопки не жал.
__:203ACE02 6A 0F push 0Fh
___:203ACE04 68 B4 37 4E 20 push offset aCdddddd ; "cdddddd"
___:203ACE09 51 push ecx
___:203ACE0A 8B 4A 6C mov ecx, [edx+6Ch]
___:203ACE0D FF D1 call ecx
_

Guzh
12.01.2011, 10:04
Эдвадко, спасибо,все работает

Aries
19.01.2011, 16:19
Привет всем)) Спасибо за отличную тему, никогда не думал, что столько всего интересного для себя смогу найти в паблике))))
К сожаления, щас на работе сижу и нет возможности все свои мысли проверить, поэтому кое-что решил спросить тут)
1.Кто-нить сейчас вообще использует для получения списка персонажей UNetworkHandler::GetNextCreature, или все эту инфу из пакетов цепляют?
2.Если кто-то используют, то вообще какой максимум радиус стоит указывать?
3.Структура User содержит id клана(хотя еще лучше б название, но понимаю, что эт бред)? Если нет, то как еще можно это узнать? и как по id определить название клана.

Prixmegently
19.01.2011, 17:02
По-моему, легче перехватывать входящие / исходящие пакеты (естественно таким же методом) и там уже разбирать информацию про юзеров, кланы и прочее.

Aries
19.01.2011, 17:47
Ну меня пока интересует именно такой способ...
Я ток начинаю потихоньку вникать во все это дело, и на данный момент мне кажется проще попытаться вызвать нужную функцию и получить готовую структуру типа User, ведь аналогично я не могу вызвать функцию и получить пакет не гемороясь особо... да и при том этот пакет еще и разобрать надо... Я конечно понимаю, что все равно потом к пакетам перейти придется, но для начала охото попробовать именно так)

mira
20.01.2011, 11:58
структура юзер сильна меняетса от хроник к хроникам. Анализ ее сложнее. В методах гетнекст нет достаточной гибкости. Я наоборот меняя метод некстенеми менял избирательность /нексттаргет

Aries
20.01.2011, 14:45
Ну на данный момент у меня есть структура юзер) Как минимум с ГетЮзер она работает...
Только вот чем больше разбираюсь, тем больше мне кажется, что ничего дельного из этого не выйдет... Просто сначала хотелось сделать готовую программку с мин набором функций, а потом уже в сторону пакетов копать... но судя по всем надо сразу в пакеты лезть...

Как я понимаю, легко получить доступ к очереди уже не получится? ведь нет никаких экспортируемых функций для просмотра очереди?)))

ЗЫ я знаю, что я слишком наивный))))))

ЗЫЫ самое поршивое, что на работе нет возможности запустить ла2, чтоб хоть как-то тестировать...а больше свободного времени практически нет((((

mira
21.01.2011, 19:13
я ранше пользовал гетюзер, потом отвязалса от этого кода по ряду причин)
вот еще интересно что будет если ты получил структуру через гетюзер начал с ней работать а в этот момент пришол deleteobject выгружающий чара.
и вообще много вопросов на эту тему

Aries
22.01.2011, 11:38
я ранше пользовал гетюзер, потом отвязалса от этого кода по ряду причин)
вот еще интересно что будет если ты получил структуру через гетюзер начал с ней работать а в этот момент пришол deleteobject выгружающий чара.
и вообще много вопросов на эту тему
Ща проверим))))))

Блин, в моем случае этот вопрос практически не актуален, т.к. я сразу же данные переписываю, и думаю довольно сложно чтобы в момент между получением и перезаписью deleteobject пришел.

Morfik
22.01.2011, 14:37
Ща проверим))))))

Блин, в моем случае этот вопрос практически не актуален, т.к. я сразу же данные переписываю, и думаю довольно сложно чтобы в момент между получением и перезаписью deleteobject пришел.

это вполне реально, так мой радар иногда выбивает клиент в самые ответственные моменты :) но увы ничего хукать не могу - на руофе эт слишком опасно, так что о пакетах в моем случае речи быт не может (

Yegor
22.01.2011, 14:43
Morfik, как вычисляешь адрес объекта UneworkHandler ничего не хукая?

Prixmegently
22.01.2011, 18:22
Не сорвешь покровы как вы там играетесь с клиентом ничего не перехватывая?

---

А ну кажется понял :D

Aries
23.01.2011, 02:43
это вполне реально, так мой радар иногда выбивает клиент в самые ответственные моменты :) но увы ничего хукать не могу - на руофе эт слишком опасно, так что о пакетах в моем случае речи быт не может (

хм, интересно...
Я специально искуственно пробовал обрабатывать структуру Юзер, адрес которой получил и потом выгрузил персонажа... Клиент у мну не вылетает...Ток вот цифры хз какие по этим адресам получаюстя))))

mira
23.01.2011, 13:45
хм, интересно...
Я специально искуственно пробовал обрабатывать структуру Юзер, адрес которой получил и потом выгрузил персонажа... Клиент у мну не вылетает...Ток вот цифры хз какие по этим адресам получаюстя))))

если ты пишеш и читаеш не туда совсем не значит что у тебя будет ошибка. обычно это аукаетса уже когда ты уже почти дописал программу, и тут начинаютса неожиданные ошибки в самых неожиданных местах) причем найти их бывает сложнее чем переписать половину самой программы :D

Aries
23.01.2011, 17:31
если ты пишеш и читаеш не туда совсем не значит что у тебя будет ошибка. обычно это аукаетса уже когда ты уже почти дописал программу, и тут начинаютса неожиданные ошибки в самых неожиданных местах) причем найти их бывает сложнее чем переписать половину самой программы :D
ну буду надеяться на лучше))))))

Кстати,Morfik, подскажи в какую сторону копать хоть для написания радарчика без перехвата пакетов)))

Morfik
24.01.2011, 18:14
ну буду надеяться на лучше))))))

Кстати,Morfik, подскажи в какую сторону копать хоть для написания радарчика без перехвата пакетов)))

в сторону почитать хотя бы 1-й пост темы :D

supernewbie
28.01.2011, 04:30
пасаны, киньте какую-нибудь хорошую статью о VMT таблицах)
и желательно чтобы код, приведенной в ней, был на делфе...

Yegor
28.01.2011, 12:24
supernewbie, вот тут почитай вроде все есть

http://www.wasm.ru/publist.php?list=21

цикл статей - Перехват API функций в Windows NT

mira
02.02.2011, 09:18
обьект это грубо говоря указатель на структуру. Первый ее член указатель на вмт, остальные это переменные экземпляра обьекта всякие.
Вмт это массив указателей на функции (методы) обьекта

Guzh
02.02.2011, 15:08
Опять вопросик по радару назрел. При работе со списком игроков, заметил, что в списке иногда остаются те,кого рядом нету. В чем может быть проблема? Удаляю из списка когда приходит DeleteObject. Сервер Руофф.

Morfik
02.02.2011, 15:55
Опять вопросик по радару назрел. При работе со списком игроков, заметил, что в списке иногда остаются те,кого рядом нету. В чем может быть проблема? Удаляю из списка когда приходит DeleteObject. Сервер Руофф.

Видимо иногда не приходит DeleteObject, оч давно когда еще юзал l2Control и у него было такое что на радаре оставались те кого рядом нету.

mira
02.02.2011, 18:20
Видимо иногда не приходит DeleteObject, оч давно когда еще юзал l2Control и у него было такое что на радаре оставались те кого рядом нету.

истину глаголиш) нада предусматривать механизм очистки "мусора" тока я пока не воткнул как это сделать более прямо

Эдвадко
02.02.2011, 21:57
Да уж... Насчет удаления мусорных мобов и игроков я тоже не понимаю пока принципа. DeleteObject действительно приходит далеко не всегда.
Пробовал удалять по превышении расстояния от игрока, но не работает это. Странно, что когда отбегаешь от моба, он исчезает то на расстоянии
около 2000 единиц, а то и с 4000 виден.
Может вся карта игры поделена на квадраты
1 2 3
4 5 6
7 8 9
и когда скажем игрок в квадрате 1, а моб в квадратах 2 4 5, то мобы видны.
А когда моб в 3 6 7 8 9, то клиент удаляет таких мобов

С DeleteObject вообще смешно - При дропе сначала идет
DeleteObject а потом игрок этот дроп благополучно поднимает.
Пришлось при DeleteObject не удалять обьект, а помечать как невидимый
StopMove 49A136A8(Ботан) 156517,-48260,-3088
DeleteObject 4075C77D(Адена 2183)
GetItem 49A136A8(Ботан) 4075C77D(Адена 2183) 156517,-48260,-3088
InventoryUpdate

Aries
06.02.2011, 19:46
Наконец появилось немного свободного времени))
И сразу же какие-то косяки...
Пытаюсь вызвать GetNextCreature(float,int), получаю адрес ?GetNextCreature@UNetworkHandler@@UAEPAUUser@@MH@Z в engine.dll, но при вызове GetNextCreature клиент закрывается с ошибкой... Вроде простейшая экспортируемая функция, а понять не могу в чем прикол...
Думаю, мб с параметрами какие-то косяки?
Никто не подскажет в чем проблема или хотя бы в какую сторону пытаться копать?

Yegor
06.02.2011, 20:11
Aries, эта функция метод класса, наверняка при ее вызове необходемо в регистр ECX (вроде как) положить указатель на экземпляр объекта UNetworkHandler

Aries
06.02.2011, 23:53
Хм, решение конечно нашлось.... Но не могу понять одного...
Функция заработала в таком варианте(правда пока не проверил корректность,но как минимум клиент не вылетает) GetNextCreature(float,DWORD,DWORD,DWORD)
1.Параметр - радиус
2.что-то что лежит в engine со смещением 0x776574
3. 0
4.что-то что лежит в engine со смещением 0x776578

Теперь главный вопрос понять, что лежит по этим адресам...


ЗЫ корректность проверил, все работает верно...

Эдвадко
07.02.2011, 00:40
Ну куды ? Куды здесь можно засунуть четыре аргумента ?
Ну если только функция не обьявлена как fastcall- 0x776578 попадает в есх, 0 в ebx, 0x776574 - это указатель на обьект Creature,потом радиус. И на выходе указатель на следущий обьект Creature. Но тогда порядок аргументов должен быть обратный.

; Exported entry 5758. ?GetNextCreature@UNetworkHandler@@UAEPAUUser@@MH@Z

; =============== S U B R O U T I N E =======================================


; int __stdcall UNetworkHandler__GetNextCreature(float, int)
public ?GetNextCreature@UNetworkHandler@@UAEPAUUser@@MH@Z
?GetNextCreature@UNetworkHandler@@UAEPAUUser@@MH@Z proc near
; DATA XREF: ___:2051D4D8o
; qpjwqywc:off_218DF084o

var_8 = dword ptr -8
arg_0 = dword ptr 4
arg_4 = dword ptr 8

mov edx, [esp+arg_4]
fld [esp+arg_0]
mov eax, [ecx]
mov eax, [eax+690h]
push edx
push ecx
fstp [esp+8+var_8]
push 6
call eax
test eax, eax
jz short loc_203D458E
mov ecx, [eax+4]
test ecx, ecx
jz short loc_203D458E
cmp dword ptr [eax], 1
jnz short loc_203D458E
mov eax, ecx
retn 8
; ---------------------------------------------------------------------------

loc_203D458E: ; CODE XREF: UNetworkHandler::GetNextCreature(float,int)+1Bj
; UNetworkHandler::GetNextCreature(float,int)+22j
; UNetworkHandler::GetNextCreature(float,int)+27j
xor eax, eax
retn 8
?GetNextCreature@UNetworkHandler@@UAEPAUUser@@MH@Z endp

Aries
07.02.2011, 01:20
Да, все именно так...
Тогда, как я понимаю 0x776578 - указатель на объект UNetworkHandler?

Хм, т.к. со всем этим делом я еще довольно мало разбираюсь, то на будущее не подскажете как можно отследить этот объект? (на случай смены хроник и т.п.)

Эдвадко
07.02.2011, 01:48
Да его (указатель на обьект UNetworkHandler) и без смены версии клиента стоит отслеживать.
Этот обьект динамически создается в памяти, и адрес может быть разным.
А узнавать как... Ставить хук на эту-же функцию, или другую, из методов UNetworkHandler, дождаться ее вызова, запомнить ecx,
ну и хук можно снять после этого. Может по другому можно (без хука), но я пока не знаю как.

Yegor
07.02.2011, 02:09
Эдвадко, главное не получить бан до того как снимешь хук )))

Aries
07.02.2011, 09:47
Эдвако, могу подсказать, что можно без хука... И не сказал бы я, что там где-то есть динамика))
Смещение 0x776578 действительно всегда указывает на UNetworkHandler...
HMODULE hEngine = findModule( "engine.dll" );
DWORD *uNet = (DWORD*) ((BYTE*)hEngine + 0x776578);
Либо я опять где-то что-то недопонял)) Но вроде бы все именно так)))

DML
07.02.2011, 10:07
Опять вопросик по радару назрел. При работе со списком игроков, заметил, что в списке иногда остаются те,кого рядом нету. В чем может быть проблема? Удаляю из списка когда приходит DeleteObject. Сервер Руофф.
Подумай, что особенного в пакетах чар инфо приходяших после удаления объекта.

Эдвадко
07.02.2011, 19:37
Эдвако, могу подсказать, что можно без хука... И не сказал бы я, что там где-то есть динамика))
Смещение 0x776578 действительно всегда указывает на UNetworkHandler...
Когда создается объект UNetworkHandler, то конструктор выделяет соответствующий по размеру блок памяти в куче, инициализирует переменные и прочее. Когда это делается на одном и том-же компе на одной и той-же винде и т.д. то скорее всего будет один и тот-же адрес,
но чуть-что сменится и все адреса динамически создаваемых обьектов изменятся.

Aries
07.02.2011, 19:56
Эдвадко, ты действительно в этом так уверен?
Тест на 3 компах, которые есть у мну дома прошел отлично)))

Эдвадко
07.02.2011, 20:34
Ну... Не уверен я... Может это секция данных, а не куча.
Я в одном уверен - Нельзя полагаться, что такое длинное смещение 776578 всегда будет указывать на UNetworkHandler. Все сменится при очередном обновлении engine.dll. А на руоффе все только и ждут обновления - а то играть невозможно:)

Aries
07.02.2011, 23:32
Вот и я спрашивал про то как же его вычислить в случае апдейта)) ну да ладно, этим думаю стоит заниматься, когда проблемы появятся, а пока работает и хорошо))))

Подскажите еще пару моментов
1.щас на руоффе реально вообще какой-либо отладчик юзать?если да то хоть намекните,какой а то пока все мои попытки провалились))
2.В структуре юзер содержится id клана все же или нет? а то на данный момент есть рабочая структура с 6 неизвестными полями, и что-то пока хз даже как разобрать что есть что((((

Aries
09.02.2011, 13:55
Злые вы, не хотите мну помочь xD xD
Короче забил, я на это гиблое дело с попыткой разбора структуры юзер(походу знаний и опыта пока маловато), из 6 неизвестных осталось 5 неизвестных xD
А вот вопрос про дебагер актуален. Или хотя б норм дизассемблер для разбора dll посоветуйте.

Все таки решил я перейте к пакетам, хук вроде установил на AddNetworkQueue и вроде даж пока банан не словил, ну будем ждать)))) Киньте пока кто-нить,если можете, ссылки на какую-нить инфу про пакеты(ток актуальную на данный момент для руоффа желательно)

Morfik
09.02.2011, 14:03
Злые вы, не хотите мну помочь xD xD
Короче забил, я на это гиблое дело с попыткой разбора структуры юзер(походу знаний и опыта пока маловато), из 6 неизвестных осталось 5 неизвестных xD
А вот вопрос про дебагер актуален. Или хотя б норм дизассемблер для разбора dll посоветуйте.

Все таки решил я перейте к пакетам, хук вроде установил на AddNetworkQueue и вроде даж пока банан не словил, ну будем ждать)))) Киньте пока кто-нить,если можете, ссылки на какую-нить инфу про пакеты(ток актуальную на данный момент для руоффа желательно)

все будет харашо, до включения бан хамера :pardon:

Aries
09.02.2011, 14:09
Там ща за сторонее ПО сразу бессрочный бан или как?xD

Yegor
09.02.2011, 14:35
Aries, первый бан 30 дней, повторный навсегда. За все известные широкому кругу способы перехвата вызова addnetworkque банит автоматом но не сразу дабы затруднить обход защиты. Банхаимер уже не включали полтора месяца но могут запустить в любой момент. В прошлый раз банили даже тех кто был оффлайн но юзал до этого стороннее ПО.

Prixmegently
09.02.2011, 21:23
Используешь апи клиента без перехватов?

Aries
09.02.2011, 23:32
Используешь апи клиента без перехватов?

Эт кому вопрос?)
Если мне, то изначально хотел именно так... Но в итоге понял, что на этом далеко не уйдешь, и что с пакетами куда лучше работать... А там уж без перехвата никак)

Yegor
10.02.2011, 00:05
Aries, я тоже так хотел, даже большее из другого процесса запускать функции клиента не подгружая свою dll кпроцессу l2 но застрял на вычислении адреса объекта UNetworkhandler.

Aries
10.02.2011, 00:23
То ли я что-то не допонимаю, то ли хз... В чем вообще у тебя проблема вычисления адреса заключается?
Вообще пока из-за тупо загрузки длл в память приложения помоему банов еще не было, так что мб не стоит настолько серьезно заморачиваться?)))
Хотя бы тупо например загрузил длл, получил нужные адреса и выгрузил)

Morfik
10.02.2011, 01:54
Aries, я тоже так хотел, даже большее из другого процесса запускать функции клиента не подгружая свою dll кпроцессу l2 но застрял на вычислении адреса объекта UNetworkhandler.

открой идой/софтайс entry.dll руоффа - экспортируемую функцию StartLogin - вот те явный пример вызовы метода UNetworkhandler и получение на него указатель, какой же как и 4-5 постами выше)
(вот такой автологин на руоффе)

Prixmegently
10.02.2011, 02:41
Таким образом входящие пакеты напрямую обрабатывать не удастся? Вызывать функции, чтобы получать структуры чаров, мобов как-то имхо не очень.

Yegor
10.02.2011, 17:21
Morfik, ты не в курсе как на можно через апи клиента послать пакет на выбор сервера из списка на этапе загрузки? Пакет со списком серверов перехватываю. Но через SendPacket выбрать нужный не удается, 0 реакции от логин сервера, видимо откуда то по другому шлется.

Morfik
10.02.2011, 18:17
Morfik, ты не в курсе как на можно через апи клиента послать пакет на выбор сервера из списка на этапе загрузки? Пакет со списком серверов перехватываю. Но через SendPacket выбрать нужный не удается, 0 реакции от логин сервера, видимо откуда то по другому шлется.

есть апи типа RequestServerLogin

Yegor
10.02.2011, 19:07
Morfik, надо будет ее хукнуть посмотреть передаваемые параметры

Prixmegently
10.02.2011, 23:47
INT __fastcall NewRequestAuthLogin(VOID *This, DWORD EDX, WCHAR* Login, WCHAR* Password, INT i);

INT __fastcall NewRequestServerList(VOID *This, DWORD EDX);

INT __fastcall NewRequestServerLogin(VOID *This, DWORD EDX, VOID* L2ParamStack);


---

Мой пост выше все проигнорировали? :D Хотя в любом случае без перехватов много чего не реализуешь.

Yegor
11.02.2011, 01:41
Prixmegently, поподробней бы NewRequestServerLogin, что в L2ParamStack?

Prixmegently
11.02.2011, 02:05
struct TServer
{
DWORD ID, u1, IP, u2, Port;
};

L2ParamStack = (DWORD)HeapAlloc(GetProcessHeap(), 8, 20);
*(DWORD*)L2ParamStack = (DWORD)&Server;
*(DWORD*)(L2ParamStack+0x10) = 3;

Yegor
11.02.2011, 02:13
Prixmegently, а что значит EDX?

Prixmegently
11.02.2011, 02:15
http://msdn.microsoft.com/en-us/library/6xa169sk(v=vs.71).aspx

The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left.

Yegor
11.02.2011, 02:23
Prixmegently, это понятно, тоесть в EDX можно ничего не ложить , функция его не использует?

Prixmegently
11.02.2011, 02:25
да, ноль например передавать можно.

Morfik
11.02.2011, 02:44
INT __fastcall NewRequestAuthLogin(VOID *This, DWORD EDX, WCHAR* Login, WCHAR* Password, INT i);

INT __fastcall NewRequestServerList(VOID *This, DWORD EDX);

INT __fastcall NewRequestServerLogin(VOID *This, DWORD EDX, VOID* L2ParamStack);


---

Мой пост выше все проигнорировали? :D Хотя в любом случае без перехватов много чего не реализуешь.
а вот за идею такого переходника спасибо)

Aries
11.02.2011, 12:03
Ребят, кто с пакетами работает, подскажите какая сейчас там структура NetworkPacket?