#1 Re: Справочная информация » Организация и анализ структур в коде » 21-01-2012 11:18

Увы, никаких баз у меня нет, и работаю я не с гта.
..и не в IDA : D
Я использую OllyDbg. Кстати, как можно приаттачить Иду к процессу игры, чтобы и процесс не был остановлен, и код был в Иде доступен для просмотра (вот прям как в Olly)?

[edit]
А можно __thiscall описывать как __cdecl и передавать this вручную?

#2 Re: Справочная информация » Организация и анализ структур в коде » 03-01-2012 21:56

Тогда в дополнение к п.1: как найти место, откуда вызывается конструктор?
Вообще примерно. По каким ниточкам идти, пользуясь отладчиком?)

#3 Re: Справочная информация » Организация и анализ структур в коде » 03-01-2012 18:40

Спасибо за труды.
От меня, как всегда, несколько вопросов (однотипных):
1. Как можно вычислить конструктор определённого объекта? У меня есть лишь начало его структуры. Хотелось бы узнать точный размер этой структуры. Я так понял из статьи, что мне поможет конструктор.
2. Функции-члены класса содержатся в структуре экземпляра класса или отдельно (в описании класса)?
3. Класс это тип данных. Значит у него есть определённый размер. Влияет ли размер функций класса на общий размер класса в памяти? Конечно, если вообще есть такое понятие, как размер функций %)

#4 Re: Программирование » DLL Loader » 19-10-2011 03:00

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

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

этот код не работает, ибо почему-то нельзя отправлять в стек значения переменных:

DWORD dwAddrToGo = (DWORD)GetModuleHandle("neededLib.dll")+0x100500;
__asm
{
    push dwAddrToGo
    ret
}

этот код подошёл бы, но портит регистр:

DWORD dwAddrToGo = (DWORD)GetModuleHandle("neededLib.dll")+0x100500;
__asm
{
    mov edx, dwAddrToGo
    jump edx
}

и действительно, обратно этот регистр уже не вернуть.

был и такой вариант:

DWORD dwAddrToGo = (DWORD)GetModuleHandle("neededLib.dll")+0x100500;
__asm
{
    xchg eax, dwAddrToGo
    push eax
    xchg eax, dwAddrToGo
    ret
}

но чувствую, что тут вновь проблема в использовании переменной (подозреваю, что xchg пашет только с регистрами).

ещё была идея перед перехватом управления поместить в стек EIP, но с этим регистром вообще ничего нельзя сделать напрямую.
также была идея пихать туда не EIP, а <адрес заменяемой функции+оффсет к нужной точке возврата>; реализовывать пока не пробовал, но думаю, что придётся опять шаманить с сохранением регистров.
сейчас пришёл к выводу, что самым халявным способом будет сделать не JMP на свою функцию, а CALL (а в конце функции будет просто ret). вот в связи с этим и интересуюсь формированием байткода команды типа "CALL 00123458".

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

#5 Re: Программирование » DLL Loader » 24-09-2011 21:11

>Делается элементарно, просто меняешь значение в структуре игрока...

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

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

#6 Re: Программирование » DLL Loader » 22-09-2011 16:39

хм.
есть где-нибудь годный гайд с примерами на тему инжекта кода?
хочу повторить код, который есть в стандартном exe (естественно вызывать его в нужное мне время и с нужными мне параметрами), но я не знаю, как найденный код перенести на C++ (сложность в том, чтобы обозначить границы действительно нужного ассемблерного кода).
найти нужные байты и адреса я смогу (Cheat Engine + Olly Dbg), но нужна мне не замена, а просто повтор.
в итоге должнен получиться "инжект кусков кода".

если нет гайдов, не мог бы кто-нибудь привести пример описания у себя функции с параметрами (здесь уже речь об описании прототипа функции, без использования ассемблерных вставок)?
и ещё. когда копаю эти функции, нередко натыкаюсь на "ненужные" параметры перед собственно вызовом функции по адресу (наряду с важными для функции значениями (передаваемыми параметрами) в стек пихаются какие-нибудь нули или единицы (независимо от параметров)). как у себя описывать такие функции (тут уже не куски кода, а описание функции на C++ с указанием её адреса в пространстве)? в смысле, есть функция void FUNCTION (int, float). я точно уверен, что важны два параметра и могу определить их в отладчике, однако в коде зачем-то в стек пихается больше значений, чем два. в общем, я даже не знаю как сформулировать вопрос grin как приложение понимает, что функция, вызываемая как FUNCTION (10, 234.55) на самом деле принимает только 2 параметра и как мне описать такую FUNCTION, если я наткнусь на непонятные "лишние" параметры в стеке?

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

#7 Re: Программирование » DLL Loader » 04-09-2011 08:08

ты не поверишь, но именно этот исходник я упомянул, он содержит один экспорт Direct3DCreate9.
: D

#8 Re: Программирование » DLL Loader » 03-09-2011 17:25

спасибо, ребята.
решил-таки заняться хуком D3D9.
так что реквестирую больше подсказок и примеров ;D

пробил экспорт из стандартной d3d9.dll (с помощью своей программки):

There are 14 functions in d3d9.dll: 

CheckFullscreen
D3DPERF_BeginEvent
D3DPERF_EndEvent
D3DPERF_GetStatus
D3DPERF_QueryRepeatFrame
D3DPERF_SetMarker
D3DPERF_SetOptions
D3DPERF_SetRegion
DebugSetLevel
DebugSetMute
Direct3DCreate9
Direct3DShaderValidatorCreate9
PSGPError
PSGPSampleTexture

скомпилил свой вариант, написанный на базе кода из поста #13 (listener), пробил в той же программке экспорт:

There are 10 functions in d3d9.dll: 

_D3DPERF_BeginEvent
_D3DPERF_EndEvent
_D3DPERF_GetStatus
_D3DPERF_QueryRepeatFrame
_D3DPERF_SetMarker
_D3DPERF_SetOptions
_D3DPERF_SetRegion
_Direct3DCreate9
_Direct3DShaderValidatorCreate9
___CPPdebugHook

в связи с этим вопросы:
1) что за подчёркивания? как экспортировать нормальные имена (в исходниках у них оригинальные названия, а не эти)?
2) что за ___CPPdebugHook? моя либа явно этого не экспортирует, но использую я C++ Builder (мало ли, чего там напридумали?).
3) я нигде не нашёл следующие функции: CheckFullscreen, DebugSetLevel, DebugSetMute, PSGPError, PSGPSampleTexture. что это такое и как бы его у себя описать?
4) (главный вопрос) нужно ли экспортировать что-либо кроме Direct3DCreate9? видел в каких-то исходниках, что экспортируют только одну её, правда через .def-файл, как в посте #17 (Alien).
5) может, где-то уже были все эти вопросы? проще конечно же дать мне ссылку, если были. гугл не помогает: пара иностранных сайтов с минимумом комментариев по коду, половина из которых естественно непонятна. прям как-то неловко изучать что-то в сетях.. grin

#9 Re: Программирование » DLL Loader » 29-08-2011 10:59

хм. вроде всё довольно легко. спасибо.

а можно сделать так?
это:
IDirect3D9 * WINAPI Direct3DCreate9(UINT SDKVersion);
описать у себя так:
void* WINAPI Direct3DCreate9(UINT SDKVersion);

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

#10 Re: Программирование » О создании скриптовых языков » 28-08-2011 16:42

не думаю, что это особо сложно, только вот зачем? он и так работает через обычный bass.dll (в этом-то и всё удобство).

#11 Re: Программирование » DLL Loader » 25-08-2011 20:54

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

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

прям на примере одной функции.

#12 Re: Программирование » DLL Loader » 25-08-2011 18:28

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

void Function (int i);

у себя я её описываю вот так:

extern "C" __declspec(dllexport) void Function ();

а приложение у себя вновь описывает, как положено изначально:

void Function (int i);

разве так не будет работать?

#13 Re: Программирование » DLL Loader » 25-08-2011 16:14

интересно.
ещё несколько вопросов ;D

1. как правильно выполнить "обёртку" функции?
так пойдёт?

extern "C" __declspec(dllexport) void ProcessSuicide() { ... }

2. в чём разница между dllexport и dllimport? вопрос, вроде как глупый, однако следующий код демонстрирует, словно пофиг, что из этого использовать:

#ifdef XLIVELESS_EXPORTS
#define XLIVELESS_API extern "C" __declspec(dllexport)
#else
#define XLIVELESS_API extern "C" __declspec(dllimport)
#endif

3. что такое __declspec(naked) void Function() {} ?
честно, я гуглил и читал это, но не понял, зачем делать функцию "без обрамления функции" (и, как это вообще понимать, я тоже не понял).

4. можно ли программно экспортировать динамический набор функций?
план таков: просматриваем секцию экспорта оригинальной DLL на предмет имён функций, дальше подставляем имя в цикле с префиксом __declspec и бла-бла-бла.
ведь вместо самой функции можно подставить указатель на неё?

while(int i=0; i<functionsCount; i++)
{
    ... // тут копаем структуру экспорта DLL на предмет имён
    name = ... ; // сюда запихиваем очередное имя функции
    extern "C" __declspec (dllexport) void* GetProcAddress(hOriginalDLL, name);
}

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

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

#14 Re: Программирование » DLL Loader » 24-08-2011 22:37

если JMP требует лишь адрес, куда нужно прыгнуть, то почему нельзя просто указать адрес функции?
вот так:

*patch = 0xE9;  // JMP
*(DWORD *)(patch+1) = pfnReplacement;  // первый байт - опкод, следующие 4 байта - операнд.

и ещё, если мы меняем код, разве не нужно юзать VirtualProtect?

#15 Re: Программирование » DLL Loader » 23-08-2011 17:16

а что ты подразумеваешь под обёрткой? типа такого?
создать в своей библиотеке функции (а точнее прототипы. нужно же?), затем сделать примерно такое:
MyProcedure1 = GetProcAddress(hOriginalDLL,"MyProcedure1");
а потом нагло экспортировать их?

ещё вопрос. да, я смотрел исходники твоего xliveless, мне понравилась эта функция:

XLIVELESS_API void injectFunction (DWORD dwAddress, DWORD pfnReplacement) {
	dwAddress += dwLoadOffset;
	BYTE * patch = (BYTE *)dwAddress;
	*patch = 0xE9;	// JMP
	*(DWORD *)(patch+1) = (pfnReplacement-(dwAddress+5));	
}

объясни, пожалуйста, что здесь происходит.
dwAddress, как я понимаю, это оффсет от Image Base процесса?
pfnReplacement - указатель на свою функцию?
вот тут я собственно не понимаю:

*(DWORD *)(patch+1) = (pfnReplacement-(dwAddress+5));

(DWORD*) - меняем размер (чтобы писать 4 байта), это понятно. а что за рассчёты такие? что за +5?

в общем, как я понимаю, просто вставляется джамп на свой адрес. а как потом нормально вернуть управление (джамп на свою функцию, там нужные нам действия, затем продолжение с того джампа) ?
прокатит, если сперва сделать джамп к себе, там первым делом вернуть оригинальный код (вместо джампа), выполнить свой код, затем в конце джампнуться на тот оригинальный код?


кстати, ещё вопрос. как вообще делаются плагины? так, чтобы правильно работали. не то, чтобы прям официально, но чтобы это было действительно расширение возможностей программы (например, QIP). в смысле, плагины это библиотеки DLL. они делаются с использованием специальных API или разработчик сам копает память и добавляет новенькое?

#16 Программирование » DLL Loader » 23-08-2011 00:13

BritishColonist
Replies: 28

привет, друзья!
есть где-нибудь литературка на тему создания загрузчиков библиотек?
я сделал свой загрузчик в виде библиотеки. если внедрить его в процесс, то он тут же поищет файлы определённого расширения рядом с запускаемым файлом этого процесса и заинжектит их в программу, но минус в том, что сам загрузчик нужно внедрять вручную (в остальном работает на пять с плюсом).
пробовал переименовать загрузчик в DLLку, нужную процессу, чтобы приложение самостоятельно скушало мою библиотеку, а заодно и кучу других библиотек (в том числе и оригинальную заменённую DLL, причём в первую очередь). проблема оказалась в том, что приложение пытается извлечь нужные ему функции из моей либы, а не из оригинала.
план был такой: при инжекте загрузчика из него вызывается функция, останавливающая все потоки (кроме собственного), загружался бы оригинальный файл, после чего менялась бы таблица импорта, лежащая в PE-хидере процесса. чувствую, что достаточно отловить, куда пихается хендл либы, которую процесс запускает сам и запихать туда хендл либы, которая инжектится загрузчиком. ну а дальше потоки возвращаются в исходное состояние и грузится остальное добро моего расширения.
прокатит ли это? если да, то как это сделать? инжектор должен быть таким, чтобы мог заменить вообще любую библиотеку (или какую-нибудь чертовски важную, типа user32).

p.s. как всегда, интересует не конкретный код, а "отправная точка".

#17 Re: Программирование » О создании скриптовых языков » 22-08-2011 19:19

пожалуйста:
http://www.megaupload.com/?d=ULESG7UJ
обязательно расскажите друзьям, если понравится.

и куда его тут можно положить, чтобы его заметили или нашли из поиска?)

#18 Re: Программирование » О создании скриптовых языков » 22-08-2011 08:08

куда позволительно залить архив с плагином, дабы скинуть сюда линк?

#19 Re: Программирование » О создании скриптовых языков » 22-08-2011 04:30

должно быть, я немного зазнался, поставив перед собой настолько сложную цель.
давно же я не посещал этот форум.. впрочем, благодарю всех за ответы.
а всем безумцам, решившим создать свой скриптовый язык (или прочие подобные вещи) я хочу сказать, что ВСЁ реализуется в C++, причём довольно просто.
пожалуй, я познал это для себя, открыв возможности си ;D

прикрепляю к посту свою последнюю на сегодняшний день разработку - проигрыватель онлайн-радиостанций для gta sa. может похвастаться некоторыми полезными настройками.
выполнен в виде .asi-плагина. написал на C++ за одну ночь)
всегда мечтал о подобном плагине и скорее всего я такой не один.
подробнейший ридми аж на двух языках прилагается к архиву, настоятельно рекомендуется прочесть его перед использованием.

p.s. Админы, если можно, переименуйте меня в мой нынешний ник: BritishColonist.

p.p.s. К сожалению ничего не прикрепилось. как заливать-то?

#20 Re: Программирование » С++. Вызов функции по адресу. » 22-08-2011 04:08

прости, должно быть, мой ответ уже будет неактуальным, но меня давненько не было на форуме grin
начнём с того, что не рекомендуется выполнять код в функции DllMain, лучше создай отдельный поток в приложении и позволь ему (приложению) окончательно запуститься и загрузить остальные библиотеки.
при инжекте библиотеки ul_reason_for_call равняется DLL_PROCESS_ATTACH, а не DLL_THREAD_ATTACH.

а вот тебе 0AB0 на C++:

bool KeyPressed(BYTE key) 
{ 
    return ((GetAsyncKeyState(key)&(1<<16))!=0); 
}

#21 Программирование » О создании скриптовых языков » 05-12-2010 23:12

BritishColonist
Replies: 17

Доброго времени суток, ребята. А особо в этой теме приветствуются люди знающие и/или участвовавшие в разработке скриптовых движков, в частности CLEO/SunnyBuilder.
/* немного автобиографии
Давно пишу скрипты для SA, и последние мои разработки сводились к сплошной работе с адресами памяти напрямую.
И я подумал, раз так, то почему бы не использовать вообще отдельную программу? Тогда юзеру даже не придётся ставить клео, качать скрипт. Тем более, включение и выключение будет максимально удобным (крестик в окошечке рулит, как никак). Так я подумал, когда хотел сделать себе сохранялку координат на клео. Расставлял тачки в сампе, а когда заглянул в окно СанниБилдера, понял, что получать координаты из сампа он категорически отказывается. А с файлами через скрипты я как работать не умел, так и не умею (кстати, тема для мануала). В то время я считал, что команда сохранения координат пашет только в режиме дебага самп-сервера (а оказалось, что работает она везде, просто не отображает какой-либо результат). Так что выход был один - использовать отдельную программку. И мне пришлось много париться, т.к. знал намного меньше, нежели сейчас. Изобретал велосипед, но учился...
В данный момент я как-то редко захожу в SA и ещё реже в Билдер, т.к. игра наскучила. Разве что, когда просят, делаю людишкам скрипты. Вообще, всё, что можно, придумано и реализовано (хотя не совсем, я лично создал пару новинок). И вот пал мой взгляд на другие игры, где можно было бы весело издеваться над игровой механикой. А для этого я решил сперва поискать инфу (ничего не нашёл), а потом и взять дело "в свои руки". Я вовсе не стремлюсь к славе и распространению своих наработок, мне лишь нужен удобный инструмент, который будет самостоятельно раскапывать бездонные структуры, добираясь до того, с чем удобно будет работать непосредственно скриптеру. Весьма вероятно, что Seemann когда-то думал точно так же.

*/

Это было, так сказать, предисловие. Собственно, основное:
Возможно эти слова будут слишком громкими, но всё же.
Планирую создать нечто вроде клео, но не для гта. Значит конкурентом данному проекту я не буду никоим образом.
Но для начала мне нужна отправная точка. Имеются некоторые вопросы относительно создания скриптового движка:
* На чём удобнее создавать? С++ или Delphi? // Изначально я учил паскаль/дельфи, так что лично мне удобнее работать с ним, но слышал, что Си наиболее гибок, среди языков высокого уровня. Стоит ли полностью переходить на Си?
* Каким образом можно внедрить код отдельных скриптов в процесс игры? //Неужто через построчное считывание скрипта, проверку в каждой строчке на имя команды (в СанниБилдере - опкод) и дальнейшую работу с переданными параметрами (в соответствии с командой)?
* Чем копать EXE? // Я, например, юзал как иду, так и олли дебаг. Ещё круто ворочает ассемблерный код программка TSearch. Я даже много чего находил и записывал всё в блокнотик. Проблема в том, что этой информации много, хранится она в неудобном виде и достаётся оттуда с трудом.
* Неужели вся работа клео-опкодов постороена на прямой работе с памятью? // В смысле, как происходит работа скрипта? Внутри игры или посредством "топорных" чтения и записи в адреса памяти?

Естественно разжёвывать всё это я не прошу. Тут возможно огромное кол-во подробностей, я уверен. Прошу лишь описать что-то вкратце, на что-то дать ссылки.

Опыт показывает, что пока за дело не возьмёшься лично ты, оно не тронется ничуть, несмотря на то, касается ли оно других. И сейчас я думаю о том, насколько хорошо то, что когда-то Seemann взялся за создание CLEO. Вот я, например, многое узнал благодаря работе в Билдере. Я благодарен автору. Я, будучи начинающим программером, нашёл применение навыков в деле, полезном не одному мне. Я создал десятки скриптов, за которые мне были благодарны люди. Но самое главное: ко мне обращались за помощью. У меня спрашивали, что и как. И, чёрт возьми, я учил их и показывал. Разве это не прекрасно? Благое дело, как никак. Вот ещё одна причина, по которой я уж очень хочу создать скриптовый язык, движок.

И, что бы вы тут не написали, спасибо за внимание.

#22 Re: Работа с памятью, EXE » Camera rotation matrix » 19-09-2010 20:05

Оу. А если делать в виде asi, то можно будет вызывать функцию процесса игры?

#23 Re: Работа с памятью, EXE » Camera rotation matrix » 18-09-2010 20:07

Да, найти получается.
Теперь тогда ещё вопрос. В саннике используются хэндлы, т.е. переменные, могут хранить в себе игрока/машину/объект/любое значение. Подобный хэндл - просто число?
А то нужно передать теперь параметры в дельфях. Мне следует найти адрес начала струкруты этого игрока/машины/объекта?

var
  StoreActorPos: Procedure (player: dword; var x,y,z:single; _x,_y,_z: single);cdecl;
...
 var
  x,y,z : single;
  PLAYER_ACTOR: dword;
begin
  GetWindowThreadProcessId(Wnd,@PId); //внедрение в процесс игры
  PHandle:=OpenProcess(PROCESS_ALL_ACCESS,false,PId); // <- ALL_ACCESS
  @StoreActorPos:=Ptr($0048BA97); //адрес процедуры
  ReadProcessMemory(PHandle,Ptr(CPed),@PLAYER_ACTOR,4,rw); //считываем указатель на адрес структуры игрока
  ReadProcessMemory(PHandle,Ptr(PLAYER_ACTOR),@PLAYER_ACTOR,4,rw); //читаем этот адрес
  If PLAYER_ACTOR<>0 Then
   Begin
     StoreActorPos(PLAYER_ACTOR,x,y,z,0.0,0.0,0.0); // <- здесь вылет
     Edit4.Text:=Format('%8.4f %8.4f %8.4f',[x,y,z]);
   End;
  Closehandle(PHandle);
end;

AcessViolation при вызове процедуры. Разве что-то не так?

#24 Re: Работа с памятью, EXE » Camera rotation matrix » 18-09-2010 10:19

Где можно надыбать точные адреса памяти, используемые в опкодах санни билдера? Такая информация где-то вообще есть?
Хочется перенести пару скриптов на удобный мне Delphi.
Собственно, интересующие опкоды:
04C4:
86BD:

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

Board footer

Powered by FluxBB