Уроки, Туториалы, Мануалы со всего света!

На этом форуме, будет находится огромное количество уроков и мануалов, сделайте небольшой вклад, и опубликуйте хотя бы один урок.
Текущее время: 19-05, 12:24

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 3 ] 
Автор Сообщение
 Заголовок сообщения: Visual C++ - Делаем трейнер
СообщениеДобавлено: 19-12, 17:53 
Не в сети
Пока что, только учусь!
Аватара пользователя

Зарегистрирован: 19-12, 17:36
Сообщения: 8
В этой статье я покажу, как сделать трейнер, используя Visual C++. На написание этой статьи меня подтолкнул тот факт, что когда я пытался найти в инете хоть какую-нибудь информацию о том, как сделать простой трейнер в VC, все, что я находил, были статьи, показывающие примеры на С/С++, а в основном на Delphi и MASM. Казалось бы что в этой ситуации можно было использовать материал статей на С/С++ если бы не одно "но" - сильная привязанность VC++ к классам, в следствии чего некоторые API функции ведут себя не так, как надо. Позже это станет понятно.

Итак приступим

Вот что нам понадобится:

-----Сама игра. Я выбрал интересную RPG - Avernum 3 (берем отсюда)

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

----- Visual C++. У меня стоит версия 6.0, поэтому туториал будет -------- сделан на ней. Версия не особо принципиальна, как ты понимаешь :)

Разведка:

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

Цитата:
HP первого character'a 0x00C1C050 2 байта
MP первого character'a 0X00C1C054 4 байта

HP второго character'a 0x00C1C420 2 байта
MP второго character'a 0x00C1C424 4 байта

HP третьего character'a 0x00C1C7F0 2 байта
MP третьего character'a 0x00C1C7F4 4 байта

HP четвертого character'a 0x00C1CBC0 2 байта
MP четвертого character'a 0x00C1CBC4 4 байта


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

Кодинг:

Приступим к самому главному и творческому процессу - написанию нашего трейнера. Делать будем, конечно, используя API функции, поскольку так будет проще, да и прога будет работать намного быстрее. Вот необходимые нам функции (посмотри их описания в Win32 API reference):

Код:
SetTimer
FindWindow
GetThreadProcessId
OpenProcess
WriteProcessMemory
GetAsyncKeyState
KillTimer
CloseHandle


Тепeрь создадим новый проект для будующего трейнера. Запусти Visual С и дави File->New. В появившемся окне выбирай тип MFC AppWizard (exe), набери имя проекта - Avernum3tr. Дави Next. Выбирай Dialog based. Next. Тут убери галочки с Active X и About box - они нам нафиг не нужны. Все, дави Finish и получай каркас. Как видишь AppWizard уже сгенерировал диалоговоё окно для нас, как и много кода, инициализирующего много всякой ерунды. Можешь сразу удалить static text и две кнопки с окна - они тоже лишние.

Разберемся с таймером и его функцией-обработчиком. Чтобы создать таймер, нажми Ctrl+W. Откроется окно MFC ClassWizard - эдакий редактор классов. Выбери следующее на вкладке Message Maps:

Код:
Class name - CAvernum3trDlg
Object ID's - CAvernum3trDlg
Member functions - OnIntiDialog


и нажми Edit code. Поскольку эта функция уже создана, попадем на кусок кода этой функции, которая вызывается когда создается наше окно. Там мы и инициализируем наш таймер. Добавляй перед строчкой return TRUE строку:

Код:
SetTimer(1, 100, NULL);


Тем самым, при запуске нашего трейнера, будет создаваться таймер , который будет посылать нашему окну сообщение WM_TIMER примерно 4 раза в секунду (второй параметр). Но раз мы создали таймер при запуске, надо его уничтожить при выходе из трейнера. Дави опять Ctrl+W и добавляй функцию WM_DESTROY (думаю понятно как) и жми Edit code. Пиши там:

Код:
KillTimer(1);


OK, перейдем к обработчику таймера. Ctrl+W и добавляй функцию WM_TIMER и перейди на её код. Вот. Эта функция будет вызываться каждый раз, когда сработает таймер. Как ты уже понял, тут мы будем писать код, который будет отвечать за отлов нажатия нужных нам клавиш и делать то, для чего, собственно, создается трейнер :)

Лови приколы:

Вот мы и подобрались к тому моменту, почему , собственно, многие статьи по написанию трейнера на С/С++ не срабатывали в VC. Попробуй в теле функции ON_WM_TIMER написать функцию FindWindow( и увидишь всплывшую подсказку о параметрах функции:

Код:
CWnd *FindWindow(LPCTSTR lpszClassName, LPCTSTR plszWindowName);


и сравни ее с тем, что нам нужно:

Код:
HWND FindWindow(LPCTSTR lpszClassName, LPCTSTR plszWindowName);


Дело в том, что первый вариант является функцией-членом класса нашего окна (я знаю, чтo это звучит запутанно, но тем не менее) и поэтому возвращает несколько другой тип. Что же делать??? А сделаем мы вот что - создадим свой собственный независимый универсальный класс, который мы будем использовать не только в этой проге. Если у нас будет такой класс, то в следующий раз, когда Ты будешь писать свой следующий трейнер, ты просто добавишь этот класс к проекту, впишешь в тело функции таймера всего пару строчек (позже поймешь почему) и все - готово. Это, друг мой, классы - просто супер возможность ООП. Да, конечно, это займет некоторое время сейчас, но здорово сэкономит его позже. Не веришь - смотри.

Пальцы веером - лепим класс:

Справа, в окне выбери вкладку ClassView и кликни на Avernum3tr classes правой кнопкой. Выбери New Class. В появившемся окне выбирай:

Код:
Class type Generic Class
Name CProcess


и дави ОК и увидишь, что он появился в списке классов нашего проекта. Если Ты нажмешь на значок "+" рядом с названием нашего нового класса, то увидишь там две функции-члена - конструктор и деструктор класса.
Теперь я покажу как добавить одну функцию, а остальные Ты уже добавишь сам. Жми правой кнопкой на нашем классе и выбирай Add member function. В появившемся окне пиши следующее:

Код:
Function Type HANDLE
Function Declarations cOpenProcess(char *p_ClassName, char *p_WindowName)
Access Public


а в тело вбей:

Код:
HWND hWindow;
DWORD pid;

hWindow = FindWindow(p_ClassName, p_WindowName);
if(hWindow)
{
GetWindowThreadProcessId(hWindow, &pid);
return ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
}
return NULL;


У тебя должно получится следующее:

Код:
HANDLE CProcess::cOpenProcess(char *p_ClassName, char *p_WindowName)
{
HWND hWindow;
DWORD pid;

hWindow = FindWindow(p_ClassName, p_WindowName);
if(hWindow)
{
GetWindowThreadProcessId(hWindow, &pid);
return ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
}
return NULL;
}


Таким же макаром пиши следующие функции:

Код:
bool CProcess::FindProcess(char *p_WindowTitle)
{
if(process==NULL)
{
process=this->cOpenProcess(NULL, p_WindowTitle);
}
if(process)
{
isrunning = TRUE;
return isrunning;
}
else
return FALSE;

}

bool CProcess::IsRunning()
{
return isrunning;
}

bool CProcess::IsKeyPressed(int key)
{
if (IsRunning()) return ((GetAsyncKeyState(key) & 1) == 1);
return FALSE;
}

bool CProcess::WriteByteToProcess(DWORD p_Adress, BYTE p_Value)
{
DWORD bytes;

if(isrunning)
{
return (WriteProcessMemory
(process, (void*)(p_Adress), (void*)(&p_Value), 1, &bytes) != 0);
}
return FALSE;
}


Ах да, чуть не забыл - добавь в класс две private переменных (правый click->Add member variable):

HANDLE pocess
bool isrunning



Почти финиш:

Открой во вкладке (справа) FileView файл Avernum3trDlg.cpp и в самом верху (после всех #include'ов напиши:

Код:
СProcess game;


Это создаст глобальную переменную типа CProcess с названием game. Так мы будем общаться с нашим классом и с игрой (через него)

Теперь вернемся с нашей функции ON_WM_TIMER. Впиши туда вот этот фрагмент - я думаю с его пониманием проблем возникнуть не должно:

Код:
bool check;

check = game.IsRunning();

if(!check)
{
game.FindProcess("Avernum 3");
}
else
{
if(game.IsKeyPressed(VK_F4))
{
game.WriteByteToProcess(0x00c1c050, 0xFF);
game.WriteByteToProcess(0x00c1c051, 0x10);
}

}

if( (!check && GetAsyncKeyState(VK_F4)) )
{
MessageBox("Zapusti igru snachala!!!", "lameru", MB_OK);
}


CDialog::OnTimer(nIDEvent)


Теперь откомпилируй проект и запусти его. Вроде проблем быть не должно - переписывал, вроде, как и у себя. Не запуская игру, нажми F4 - лови ругательства. Теперь запусти игру, создай персонажей... и в игре нажми F4 - получай бонусы здоровья. Остальные опции допиши сам - это тебе как домашнее задание.
© mamont tеаm-x.ru

_________________
ДружоК :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Visual C++ - Делаем трейнер
СообщениеДобавлено: 19-12, 18:03 
Не в сети
Пока что, только учусь!
Аватара пользователя

Зарегистрирован: 19-12, 18:00
Сообщения: 2
Откуда: С планеты критиков
Border =) писал(а):
Код:
bool check;

check = game.IsRunning();

if(!check)
{
game.FindProcess("Avernum 3");
}
else
{
if(game.IsKeyPressed(VK_F4))
{
game.WriteByteToProcess(0x00c1c050, 0xFF);
game.WriteByteToProcess(0x00c1c051, 0x10);
}

}

if( (!check && GetAsyncKeyState(VK_F4)) )
{
MessageBox("Zapusti igru snachala!!!", "lameru", MB_OK);
}


CDialog::OnTimer(nIDEvent)


Ээмм, а не развели в конце скрипта, должен быть знак ; ? :) Пропустил :)

_________________
http://Я хороший.НЕТ


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Visual C++ - Делаем трейнер
СообщениеДобавлено: 19-12, 18:08 
Не в сети
Пока что, только учусь!
Аватара пользователя

Зарегистрирован: 19-12, 17:36
Сообщения: 8
Imperator писал(а):
Border =) писал(а):
Код:
bool check;

check = game.IsRunning();

if(!check)
{
game.FindProcess("Avernum 3");
}
else
{
if(game.IsKeyPressed(VK_F4))
{
game.WriteByteToProcess(0x00c1c050, 0xFF);
game.WriteByteToProcess(0x00c1c051, 0x10);
}

}

if( (!check && GetAsyncKeyState(VK_F4)) )
{
MessageBox("Zapusti igru snachala!!!", "lameru", MB_OK);
}


CDialog::OnTimer(nIDEvent)


Ээмм, а не развели в конце скрипта, должен быть знак ; ? :) Пропустил :)

Ну... урок писал не я :) Так что все вопросы к создателям :)

_________________
ДружоК :)


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 3 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения

Найти:
Перейти:  
cron
Powered by Forumenko © 2006–2014
Русская поддержка phpBB