|
Трейнер на Delphi 7 - Школа Читера - Основы основ - начинаем писать статьи для начинающих с целью создания полноценного раздела |
06.02.2011, 02:25
|
#1
|
|
|
|
Разведчик
|
Регистрация: 20.01.2011
Сообщений: 3
Популярность: 26
Сказал(а) спасибо: 2
Поблагодарили 8 раз(а) в 3 сообщениях
|
Трейнер на Delphi 7
Туториал по написанию трейнеров для DMA и не-DMA игр
Содержание:
1. Немного теории
2. Не-DMA игры
3. DMA игры - поиск поинтера
4. Пишем трейнер для:
4.1 Трейнер для не-DMA игры
4.2 Трейнер для DMA игры
4.3 Общие замечания
5. Заключение
6. Некоторые оговорки
В этой статье я рассмотрю написание трейнера (trainer'а) для игры. В рунете совсем мало информации на эту тему, а про написание DMA-трейнеров я вообще ничего не нашёл (может быть, конечно, плохо искал), но в процессе написания мною была дана торжественная клятва, что когда закончу - обязательно напишу нормальный туториал на эту тему. Хотелось написать туториал, в котором бы затрагивалось в равной степени как теория, так и поиск поинтера и написание собственно трейнера.
Основную часть я намерен посвятить именно DMA играм.
Итак, что потребуется:
- - Язык программирования. Я буду использовать Delphi для примеров. В принципе, подойдёт любой - для работы с памятью процесса нам потребуются только WinAPI функции.
- - Программа типа ArtMoney (чтобы искать значения в памяти). Настоятельным образом рекомендую TSearch (несмотря даже на то, что весит он полтора метра), буду использовать его в примерах.
- - Отладчик. Опять же рекомендую TSearch - он содержит в себе простой и удобный отладчик, которого вполне хватит. Если у вас есть SoftICE, и вы умеете им пользоваться - то флаг в руки.
- - Минимальные знания ассемблера, общее (хотя бы теоретическое) представление об отладке программ, устройстве памяти.
приступим...
1. Немного теории:
Прежде всего, что такое DMA? DMA - dynamic memory allocation, т.е. динамическое распределение памяти. Проще говоря, DMA игры, в отличие от не-DMA игр, хранят используемые ими величины (нас будут интересовать деньги, жизни и т.п.) по адресам в памяти, которые меняются после каждого запуска/перезапуска/загрузки игры.
Все программы DOS не используют DMA, тогда как большинство игр под Win32 его использует (не используют только игры времён Win95-Win98). С не-DMA играми всё предельно просто - нужно просто найти адрес в памяти, где игра хранит интересующее нас значение, и изменить его. А вот с DMA могут сложнее - что делать, если адреса постоянно изменяются? Для того, чтобы ответить на этот вопрос, нужно понять, как сама игра находит нужный адрес. Для этого используются поинтеры (pointer - указатель, я буду их называть и так, и так). Адреса поинтеров, в отличие ото всех остальных, не изменяются. Поинтер содержит значение, которое соответствует адресу какой-то величины, используемой игрой. Не важно какой, важно, что смещение других адресов относительно адреса, на который указывает поинтер, также не меняется (*). (Если не очень понятно - уверен, что станет понятнее в практической части) Итак, трейнер для DMA игры будет сначала считывать из указателя адрес интересующего значения, а затем уже его изменять. Осталось только его найти и написать соответствующую программу. (Всего-то делов, да? )
Про регистры процессора, про то, как устроен стек и т.д. я рассказывать не намерен. Для этого есть учебники по ассемблеру (вообще говоря, эти темы так или иначе затрагиваются в любом учебнике программирования на любом языке).
Теперь к практике...
2. Не-DMA игры.
Как я уже говорил, тут всё предельно просто. Запускаем ArtMoney/TSearch/GameHack и т.п., ищем, затем отсеиваем, определяем адрес интересующего значения. Пишем трейнер в пункте 4.1.
3. DMA игры - поиск поинтера.
Итак, сначала нужно найти адрес интересующей величины. Теперь нужно поставить брейкпоинт на этот адрес (TSearch - в меню: AutoHack -> Enable Debugger, Enable AutoHack window, там нажимаем на кнопку добавления брейкпоинта и вводим адрес нашей величины). Мы ставим брейкпоинт на чтение/запись этого адреса, т.е. при чтении или записи этого адреса нам будет показано, какие инструкции в программе и в каком месте читали/писали из/в него (в более профессиональных отладчиках, например, SoftICE, выполнение всех программ приостановится, и вылезет окно отладчика). Далее нужно переключиться в игру и изменить величину. После того, как он изменится, в окне отладчика TSearch появится строка, например, mov [ebx+A], eax (A - некоторое смещение, может быть любым целым числом, например 4). Эта ассемблерная инструкция устанавливает значение по адресу ebx+A равным eax. Что такое ebx+A? Это и есть наш адрес, +A - смещение относительно ближайшего указателя. То есть, поинтер указывает на какой-то адрес, а через A от него находится интересующее нас значение, и это значение всегда будет смещено на A относительно адреса, на который указывает поинтер. Но мы ещё не знаем адрес поинтера (адрес у нас был в регистре ebx, но он должен быть где-то в памяти). Искать его придётся как и любое другое числовое значение. Вычтем из адреса интересующего нас значения, который мы нашли в самом начале, A, затем переведём его в десятеричную систему счисления, а затем будем искать. Возможно, мы найдём несколько адресов, содержащий такое число, но совсем не факт, что все эти адреса - адреса указателей. Для этого придётся перезагрузить игру, затем вновь найти интересующее значение, из его адреса вычесть A, перевести в десятеричную систему счисления, и отсеивать.
Слова, конечно, хорошо, но на примерах любое изучение идёт лучше.
Пример: Red Alert 2. Для наглядности буду использовать TSearch. Запускаем. Open Process - выбираем нужный процесс (game.exe), приступаем к поиску: деньги - Exact Value, 4 bytes. Меняем количество денег. Отсеиваем. В результате останется 3 значения, но только одно из них - значение собственно денег, остальные два - значения счётчика и ещё что-то. (Я знаю, что значение с самым большим адресом - то, которое нужно) У меня этот адрес получился равным 72C6DAC. Далее устанавливаем на этот адрес брейкпоинт. Изменяем значение. В окошке отладчика видим: 4E48FF:
mov [ebx+0x24C], eax. Ассемблерная инструкция mov [ebx+0x24C], eax устанавливает значение, равное eax по адресу ebx+024C (ebx - регистр процессора, содержащий адрес, квадратные скобки указывают на то, что число, содержащееся в них, - адрес, и нужно изменять значение по этому адресу), но нас интересует только ebx+0x24C. Отнимаем от 72C6DAC (адреса, по которому хранится значение денег) 24Ch - получаем 72C6B60, переводим в десятеричную систему счисления - 120351584. Теперь ищем это число в памяти. В начале я получил 37 адресов. Теперь по новой ищем адрес, по которому находятся деньги, не забыв предварительно добавить в таблицу уже найденные адреса потенциальных указателей. На этот раз это 73B29FC. Вновь отнимаем 24С, переводим, ищем. В результате у меня осталось несколько адресов. Пожалуй, можно выбрать любой. Один из них - A1E0C4, сгодится. Перезапускаем. Итак, прибавим к значению, хранящемуся по адресу A1E0C4, 24С. Теперь переводим результат сложения в шестнадцатеричную систему счисления и смотрим на значение по этому адресу. Если мы видим там количество наших денег - значит всё удалось, поздравляю (Если нет - придётся повторить всё с начала)
Итак, поинтер мы нашли. Пожалуй, это был самый сложный этап.
4. Пишем трейнер.
Для записи и чтения в памяти мы будем использовать две WinAPI функции - ReadProcessMemory и WriteProcessMemory. (Всё предельно просто)
4.1. Трейнер для не-DMA игры.
К примеру, возьмём старую DOS-овскую игрушку Raptor: Call of The Shadows.
Код:
var
Form1: TForm1;
WindowName: integer;// Для удобства объявим как глобальные переменные.
ProcessId: integer; // Все эти переменные нужны для того, чтобы найти
ThreadId: integer; // процесс с игрой.
HandleWindow: Integer; //
write: cardinal; // В эту переменную попадёт количество записанных байтов.
buf: dword; // Тут будет содержаться значение, на которое будем изменять.
const
WindowTitle = 'RAP'; // Заголовок окна с игрой
Address = $83C4BF64; // Адрес, по которому будем изменять значение.
NumberOfBytes = 4; // Количество байт, которые будем заменять.
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
WindowName := FindWindow(nil,WindowTitle);
If WindowName = 0 then begin // Если окошка у нас нет, то и изменять нечего.
MessageDlg('Игра должна быть запущена до трейнера. Запустите ее, потом трейнер', mtwarning,[mbOK],0);
end;
ThreadId := GetWindowThreadProcessId(WindowName,@ProcessId); // Ищем хэндл процесса
HandleWindow := OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId); // с нашей игрой.
buf:=$DEAD; // DEADh = 57005d
WriteProcessMemory(HandleWindow, ptr(address), @buf, 4, write); // Изменяем значение по этому адресу на наше.
end;
4.2. Пишем трейнер для DMA-игры.
Тут уже будем читать из поинтера адрес, по которому будем далее менять значение. Возьмём в качестве примера, скажем, SimCity 4.
var
Код:
Form1: TForm1;
WindowName : integer;
ProcessId : integer;
ThreadId : integer;
HandleWindow : Integer;
bword; // Всё по-прежнему, кроме этой переменной - сюда прочитаем адрес из поинтера.
readwrite:cardinal;
buf : dword;
Const WindowTitle = 'SimCity 4';
Address = $B321E4; // Это адрес поинтера.
NumberOfBytes = 4;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
WindowName := FindWindow(nil,WindowTitle);
If WindowName = 0 then
begin
MessageDlg('Игра должна быть запущена до трейнера. Запустите ее, потом трейнер', mtwarning,[mbOK],0);
end;
ThreadId := GetWindowThreadProcessId(WindowName,@ProcessId);
HandleWindow := OpenProcess(PROCESS_ALL_ACCESS,False,ProcessId);
ReadProcessMemory(HandleWindow,ptr(address),@b,4,readwrite); // Прочитали в b значение из адреса поинтера.
b:=b+40; // Смещение адреса денег относительно адреса, на который указывает поинтер равно 40. Прибавляем.
buf:=$FFFFFFFF; // Денег должно быть много :) (**)
WriteProcessMemory(HandleWindow, ptr(b), @buf, 4, readwrite); // Наконец, запишем по адресу,
// содержащемуся в b, новое значение денег.
end;
Для того, чтобы значение "заморозить" нужно выложить на форму таймер или использовать бесконечный цикл (думаю, это итак понятно ), но в этом случае будет очень полезно проверять значение по адресу в b, т.к. всё в том же SimCity 4 если выйти со включённым таймером на экран выбора города - игра вывалится.
Также хорошей идеей является использование горячих клавиш. В тему борьбы с DMA это не входит, так что всё это на вкус читателя.
4.3. Общие замечания
Хочется ещё обратить внимание на то, сколько мы байт читаем и записываем (константа NumberOfBytes). Есличитаем из поинтера - то читать нужно 4 байта (т.е. dword - переменная, в которую читаем, должна уместить в себя это значение; все адреса - 32-разрядные). Если пишем значение, размер которого 1 байт - то соответственно и писать надо 1 байт Иначе, опять же, чревато аварийным завершением игры.
Напоминаю, что:
byte это 1 байт (это 8 бит ) - число от 0 до 255.
word это 2 байта - число от 0 до 65535.
dword это 4 байта - число от 0 до 4294967295.
Приводить описание всех использованных WinAPI функций я счёл ненужным, так что если интересно - смотри MSDN сам.
5. Заключение.
Ну вот и всё. Трейнер написан и работает (по крайней мере, надеюсь на это), остаётся лишь пожелать всем удачи в этом непростом деле
Удачи, xxVENIKxx. 6. Некоторые оговорки
* - я пишу, что смещение адресов относительно поинтера не меняется. Это так. Но иногда его сложнее найти - встречаются конструкции типа mov [ebx+ecx], eax (правда, встречается значительно реже - это всякие полоски с жизнью и другие неявные величины). Тут хорошо бы вооружиться отладчиком посерьёзнее (SoftICE) и либо смотреть, что откуда попадает в регистры (быть указаны явно), либо ставить брейкпоинт на адрес, когда брейкпоинт сработает - смотреть содержимое регистров и искать их в памяти по-отдельности, точно так же, как мы это делали в случае с одним регистром. Но так или иначе, раз игра находит адрес - то можем найти и мы. (Это здесь написано для того, чтобы не возникало сомнений относительно неизменности адреса поинтера 8) )
** - я смело заменяю значение на FFFFFFFFh. Это прокатит для SimCity 4, но в общем случае также чревато последствиями. (Значение может быть и 4 байта, но такая цифра может не влезть в строку, вылезти за пределы экрана или ещё как-нибудь заглючить , в общем, лучше не жадничать)
С сайта CheMax
С уважением xxVENIKxx
________________
Последний раз редактировалось xxVENIKxx; 06.02.2011 в 02:45.
|
|
|
5 пользователя(ей) сказали cпасибо:
|
|
06.02.2011, 16:46
|
#2
|
|
|
|
Разведчик
|
Регистрация: 11.05.2010
Сообщений: 10
Популярность: 22
Сказал(а) спасибо: 5
Поблагодарили 6 раз(а) в 6 сообщениях
|
Re: Трейнер на Delphi 7
ИМХО хорошая тема, у самого была мысль написать подобную статью (только с примерами на с++ или c#), но во первых лень, во вторых знаний маловато... и собственно из vc++ 2008 и 2010 у меня ни одна нужная winApi функция не работает... GetWindowThreadProcessId не возвращает PID, OpenProcess не находит дескриптор, и тд... Самое обидное - я не уверен в чем проблемма, в компиляторе, или в моей тупости
________________
небойся делать то чего неумеешь- ковчег построил любитель... профи сотворили титаник
|
|
|
Пользователь сказал cпасибо:
|
|
06.02.2011, 23:28
|
#3
|
|
|
|
Разведчик
|
Регистрация: 20.01.2011
Сообщений: 3
Популярность: 26
Сказал(а) спасибо: 2
Поблагодарили 8 раз(а) в 3 сообщениях
|
Re: Трейнер на Delphi 7
я в vc++ ненаю как форму сделать и потому не пользуючь но так он у меня есть писал Hello World
________________
|
|
|
20.02.2011, 20:41
|
#4
|
|
|
|
Разведчик
|
Регистрация: 20.02.2011
Сообщений: 5
Популярность: 22
Сказал(а) спасибо: 9
Поблагодарили 6 раз(а) в 4 сообщениях
|
Re: Трейнер на Delphi 7
Обьсни по лучше плизззз, а ещё лучше в скайп jakush5 плизз очень прошу
|
|
|
20.02.2011, 22:12
|
#5
|
|
|
|
Сержант
|
Регистрация: 04.09.2009
Сообщений: 130
Популярность: 1758
Сказал(а) спасибо: 652
Поблагодарили 324 раз(а) в 128 сообщениях
|
Re: Трейнер на Delphi 7
Сделай видео урок , многим понадобится.
________________
Палки палки палочки
|
|
|
21.02.2011, 00:01
|
#6
|
|
|
|
Разведчик
|
Регистрация: 20.01.2011
Сообщений: 3
Популярность: 26
Сказал(а) спасибо: 2
Поблагодарили 8 раз(а) в 3 сообщениях
|
Re: Трейнер на Delphi 7
Лень
________________
|
|
|
21.02.2011, 16:23
|
#7
|
|
|
|
Сержант
|
Регистрация: 20.02.2010
Сообщений: 118
Популярность: 499
Сказал(а) спасибо: 167
Поблагодарили 189 раз(а) в 129 сообщениях
|
Re: Трейнер на Delphi 7
Потому что это не его статься...он просот скопипастил...по этому и видео не может сделать
|
|
|
10.03.2011, 07:26
|
#8
|
|
|
|
Разведчик
|
Регистрация: 05.03.2011
Сообщений: 0
Популярность: 20
Сказал(а) спасибо: 2
Поблагодарили 5 раз(а) в 4 сообщениях
|
Re: Трейнер на Delphi 7
|
|
|
02.04.2011, 22:19
|
#9
|
|
|
|
Разведчик
|
Регистрация: 23.03.2011
Сообщений: 0
Популярность: 10
Сказал(а) спасибо: 5
Поблагодарили 0 раз(а) в 0 сообщениях
|
Re: Трейнер на Delphi 7
|
|
|
02.04.2011, 22:24
|
#10
|
|
|
|
Фельдмаршал
|
Регистрация: 13.08.2009
Сообщений: 1,004
Популярность: 25098
Золото Zhyk.Ru: 350
Сказал(а) спасибо: 110
Поблагодарили 830 раз(а) в 395 сообщениях
|
Re: Трейнер на Delphi 7
NumberOfBytes = "количество байт, которые необходимо перезаписать"
________________
Ни одно доброе дело не остается безнаказанным.
Программы:
PW: Флудобот, Девизхак, OutFocusBot, OutFocusBot ver 3 (freepvp), PWMultiHack ver 3, AutoRespawn.
JD: JDMultiHack, JDFlooder, JDBot.
Статьи: Отключаем UAC, Ищем базовый адрес Perfect World, "Патчер памяти" или "Пишем флайхак", "Патчер памяти 2" или "Пишем Джампхак", "Поиск инжектов" или "Наш код в чужом процессе"
|
|
|
Пользователь сказал cпасибо:
|
|
02.04.2011, 22:35
|
#11
|
|
|
|
Разведчик
|
Регистрация: 23.03.2011
Сообщений: 0
Популярность: 10
Сказал(а) спасибо: 5
Поблагодарили 0 раз(а) в 0 сообщениях
|
Re: Трейнер на Delphi 7
Да всё *) Не для DMA игр зделал а для DMA что то не получаеться *(
Добавлено через 3 минуты
Может кто нидь кинуть сыль на тему как найти смещение адресса ???? За спасибку естественно *)
Последний раз редактировалось ***RAKIM***; 02.04.2011 в 22:38.
Причина: Добавлено сообщение
|
|
|
02.04.2011, 22:38
|
#12
|
|
|
|
Фельдмаршал
|
Регистрация: 13.08.2009
Сообщений: 1,004
Популярность: 25098
Золото Zhyk.Ru: 350
Сказал(а) спасибо: 110
Поблагодарили 830 раз(а) в 395 сообщениях
|
Re: Трейнер на Delphi 7
А для DMA нужно "дорожу к адресу" находить (в случае если правишь область динамически выделяемой памяти). Тоесть от статичного адреса по дорожке смещений до нужного.
Добавлено через 3 минуты
Вот примерно так
http://zhyk.ru/forum/showthread.php?t=116666
________________
Ни одно доброе дело не остается безнаказанным.
Программы:
PW: Флудобот, Девизхак, OutFocusBot, OutFocusBot ver 3 (freepvp), PWMultiHack ver 3, AutoRespawn.
JD: JDMultiHack, JDFlooder, JDBot.
Статьи: Отключаем UAC, Ищем базовый адрес Perfect World, "Патчер памяти" или "Пишем флайхак", "Патчер памяти 2" или "Пишем Джампхак", "Поиск инжектов" или "Наш код в чужом процессе"
Последний раз редактировалось Dinmaite; 02.04.2011 в 22:41.
Причина: Добавлено сообщение
|
|
|
Пользователь сказал cпасибо:
|
|
02.04.2011, 22:54
|
#13
|
|
|
|
Разведчик
|
Регистрация: 23.03.2011
Сообщений: 0
Популярность: 10
Сказал(а) спасибо: 5
Поблагодарили 0 раз(а) в 0 сообщениях
|
Re: Трейнер на Delphi 7
Так не получаеться так как после выполнения этого пункта 8. Щелкаем правой кнопкой мыши по адресу в поле работы с адресами, и в контекстном меню выбираем "Find out what writes to this addres".
процесс игры закрываеться и всё *((((
А как ещё моно найти ????
|
|
|
02.04.2011, 22:57
|
#14
|
|
|
|
Фельдмаршал
|
Регистрация: 13.08.2009
Сообщений: 1,004
Популярность: 25098
Золото Zhyk.Ru: 350
Сказал(а) спасибо: 110
Поблагодарили 830 раз(а) в 395 сообщениях
|
Re: Трейнер на Delphi 7
Логика поиска по сути одна и та же, а вот другим инструментом можно попробовать - OllyDbg к примеру, но там уже сложнее.
________________
Ни одно доброе дело не остается безнаказанным.
Программы:
PW: Флудобот, Девизхак, OutFocusBot, OutFocusBot ver 3 (freepvp), PWMultiHack ver 3, AutoRespawn.
JD: JDMultiHack, JDFlooder, JDBot.
Статьи: Отключаем UAC, Ищем базовый адрес Perfect World, "Патчер памяти" или "Пишем флайхак", "Патчер памяти 2" или "Пишем Джампхак", "Поиск инжектов" или "Наш код в чужом процессе"
|
|
|
02.04.2011, 23:51
|
#15
|
|
|
|
Разведчик
|
Регистрация: 23.03.2011
Сообщений: 0
Популярность: 10
Сказал(а) спасибо: 5
Поблагодарили 0 раз(а) в 0 сообщениях
|
Re: Трейнер на Delphi 7
Почему у меня на эту строчку
Выдаёт ошибку ???
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Похожие темы
|
Тема |
Автор |
Раздел |
Ответов |
Последнее сообщение |
[Помогите!] Трейнер
|
anime-kawai |
Школа Читера |
2 |
03.02.2011 19:44 |
[Помогите!] Трейнер на C#
|
anime-kawai |
Школа Читера |
1 |
18.01.2011 16:04 |
[Помогите!] трейнер
|
cherif |
Общение и обсуждение S4 League |
5 |
22.11.2010 13:06 |
Заявление об ответственности / Список мошенников
Часовой пояс GMT +4, время: 17:12.
|
|