PDA

Просмотр полной версии : [Скрипт] "Патчер памяти 2" или "Пишем Джампхак"


Dinmaite
09.09.2010, 13:28
Продолжу цикл статей о принципах патчинга памяти в Делфи в общем, и написании хаков в частности.

Почему я разделил статьи о флай и джамп хаке?
Дело в том что их реализация имеет некоторые отличия.
В флайхаке мы патчили флаг полета в памяти, в джампхаке же будем менять код клиента игры. Сразу замечу в моей реализации и реализации от Sauron'а есть некоторое отличие, а именно: патчер Sauron'a (PWmp1 - PWmp5) изменяет код проверки счетчика прыжков, я же пошел по иному пути - меняю код записи в счетчик прыжков.

Итак начнем.

Работу разделим на три этапа.


1. Открываем Perfect World и Cheat Engine (в данном случае работать будет удобне в нем), и подключаемся к процессу PW.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

Важно! Если у Вас медленная машина поставьте галочку "Pause the game while scanning" (на вопрос о подключении дебаггера отвечаем Yes).
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

2. Теперь вводим в поле Value число прыжков, лучше начинать с 2. Подпрыгиваем в игре двойным прыжком и быстренько нажимаем на First Scan (Если вы повторяете этот пункт после следующего то нажимаем на Next Scan), отсеивание должно закончится раньше, чем персонаж опустится на землю (если это не так установите галочку "Pause the game while scanning" и повторите данный пункт)
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

3. Мы нашли множество адресов, но нам нужен только один. Потому когда персонаж опустится на землю отсеим значение 0.
(вводим в поле Value 0 и надимаем на Next Scan)
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

4. Повторяем пункты 2 и 3 до тех пор, пока в таблице не останется 1 адреc. Затем, двойным щелчком, добавляем полученный адрес в поле работы с адресами.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]



1. Итак у нас есть добавленный адрес. Щелкаем по нему правой кнопкой мыши, и выбираем пункт "Find out what writes to this address"
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
2. После выполнения пункта 1, откроется новое окно, что бы в нем появился нужный нам адрес подпрыгнем в игре 1 раз.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
3. Мы подпрыгнули, но в окошко добавилось 2 строки, нам нужна первая, так как именно эта команда увеличивает счетчик прыжков (вторая строка показывает команду обнуляющую счетчик).
Выбираем первую строку и жмем на Show disassembler.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
4. Открывается окно отладчика, и мы видем в нем нужную нам команду.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

Что значит mov [esi+00000bf4],ecx ?
Это значит что в ячейку (ячейка счетчика прыжков), которая указана как [esi+00000bf4], заносится значение регистра ecx.
Данный код в памяти занимает 6 байт:
89 8E F4 0B 00 00
Если мы захотим править именно эту команду, то исправленный код должен выглядеть как mov [esi+00000bf4],00000001. Но данный код занимает 10 байт памяти:
C7 86 F4 0B 00 00 01 00 00 00,
а что бы не нарушить код мы можем использовать лишь 6 байт.
Поэтому мы прокрутим код немного вверх, и найдем запись в регистр ecx.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

Зеленым я выделил адрес, который мы нашли.
Красным адрес, который будем править.
Оранжевым "важный момент".

Итак мы видем что команда mov ecx,[esi+00000bf4] занимает 6 байт в памяти:
8B 8E F4 0B 00 00.
Если мы попытаемся заменить код на mov ecx,00000000 то увидим что он занимает 5 байт в памяти:
B9 00 00 00 00.
Но так как свободной памяти у нас 6 байт, то в 6 байт запишем команду nop (NoOPeration, эта команда ничего не делает, но занимает процессорное время, байткод команды - 90).
Тоесть байткод, который мы должны использовать при патчинге:
B9 00 00 00 00 90.

Теперь немного о "важном моменте", команда inc ecx увеличивает значение в регистре ecx на единицу, именно поэтому мы изменяем команду mov ecx,[esi+00000bf4] на mov ecx,00000000, а не на mov ecx,00000001.



Описание используемых API функций можно посмотреть в теме "Патчер памяти" или "Пишем флайхак" [Delphi] ([Ссылки могут видеть только зарегистрированные и активированные пользователи])

Начнем с того что бросим на форму 2 кнопки "ВКЛ" и "ВЫКЛ".
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

Продолжим процедурой записи в память. Эта процедура автоматизирует запись в память байткодов, длина которых превышает 4 байта.
Параметры:
hProcess - Идентификатор объекта
Addres - Адрес в памяти, по которому мы будем вести патчинг.
bytecode - Набор байт для патчинга (байткод).
procedure MemoryPatch(hProcess, Addres:DWord; bytecode:string);
var
i, bytecount:dword;
buf:byte;
begin
i:=(length(bytecode) div 2)-1;
for i:=0 to i do
begin
buf:=strtoint('$'+bytecode[i*2+1]+bytecode[i*2+2]);
writeprocessmemory(hProcess,ptr(Addres+i),@buf,1,b ytecount);
end;
end;


Основная процедура, в ней дается команда на патчинг и определяется соответствие версии клиента
Суть метода в том что в PW есть 2 статических адреса базовый адрес (ba) и базовый указатель (bp), причем базовый указатель лежит по смещению $1C относительно значения базового адреса. Тоесть [ba]+$1C=bp, именно это взаимоотношение я использую для проверки версии.

В качестве параметра передается логическое значение:
true - для включения джампхака;
false - для выключения джампхака.

procedure JumpHack(state:boolean);
const
base_addr=$009C0E6C; //Базовый Адрес PW
base_ptr=$009C1514; //Базовый указатель PW
jump_addr=$00455EB3; //Адрес команды, которую мы правим
bytecode_jump_standart='8B8EF40B0000'; //Байткод стандартной команды
bytecode_jump_modified='b90000000090'; //Байткод модифицированной команды
var
WndHndl:THandle;
ipbuf,PID,hProcess,BytesCount,buf:dword;
begin
WndHndl:=FindWindow('ElementClient Window',nil);
GetWindowThreadProcessId(WndHndl, @PID);
hProcess:=OpenProcess(PROCESS_ALL_ACCESS, False, PID);
if hProcess <> 0 then // проверяем получилось ли открыть процесс для записи и чтения
try
//Првоеряем верная ли версия клиента
ReadProcessMemory(hProcess,ptr(base_addr),@buf,4,B ytesCount);
if (buf+$1C<>base_ptr) then
messagebox(0,'Неверная версия клиента','Пишем Джампхак',16)
else
if state then
begin
MemoryPatch(hProcess, jump_addr, bytecode_jump_modified);
MessageBox(0,'Клиент пропатчен','Пишем Джампхак',64);
end
else
begin
MemoryPatch(hProcess, jump_addr, bytecode_jump_standart);
MessageBox(0,'Восстановлены стандартные значения','Пишем Джампхак',64);
end
finally
CloseHandle(hProcess);
end;
end;

В обработчики событий OnClick наших кнопок запишем:
для "ВКЛ" - JumpHack(true);
для "Выкл" - JumpHack(false);

Вуаля, джампхак готов.

В аттаче исходник проекта.

Sirioga
11.09.2010, 22:47
Чё-то я когда прыгал, до паузы не додумался)))
Зажимал пробел пока скан шел))))

GrieVeR-13
12.09.2010, 20:22
И на оффе естественно не работает, Да? ;)
Как не крути, откидывать всё равно будет.

Dinmaite
12.09.2010, 20:29
GrieVeR-13, естественно.
По сути цель темы побудить Жуковских кодеров поработать с памятью PW.
Может даже начнут ботов писать ;)

AEBus
12.09.2010, 20:51
Вообще цель такова чтобы превратить читерский портал в действительно читерский а не портал брутеров, разводил и прочих
Самые популярые темы на жуке это
Брут
Разводы
Дюп

Брут - нубизм
Разводы - тоже нубизм
Дюп - мистика
(с) TBX1n

Раньше он был действительно читерским, а сейчас...

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

GrieVeR-13
я иногда читаю вашу тему на elitepvpers.de и убеждаюсь что в России есть такие люди, но они не сидят на жуке...

~ГайвеР~
13.09.2010, 13:17
ПРочитал название темы и автоматом поставил СПС, не думал вникать в суть, потом прочитал коменты, теперь залезу), а то както обидно быть не Читером на читерском портале)

Богомол
16.11.2010, 14:08
Отличная статья. Я как раз увлекаюсь программированием. Мне, как новичку в Delphi, она показала основы работы с памятью)
Как только что-нибудь полезное напишу, то выложу)))

mires51
11.04.2011, 15:41
Dinmaite, Спасибо
p.s жаль на руофе не робит

Jok3r666
20.08.2011, 11:15
writeprocessmemory(hProcess,ptr(Addres+i),@buf,1,b ytecount);

jump_addr=$00455EB3;

Можно поинтересоваться?
откуда взялся джамп адр (это офсет?)
почему к нему прибавляется i?

VeTaL_UA
20.08.2011, 11:25
откуда взялся джамп адр (это офсет?)
Второй пункт прочти...
почему к нему прибавляется i?
Ты статью то читал?)

Jok3r666
20.08.2011, 11:28
Второй пункт прочти...

Ты статью то читал?)

Читал на 2 раза и так и не понял. Тыкни носом.

Добавлено через 2 минуты
for i:=0 to i do
begin
buf:=strtoint('$'+bytecode[i*2+1]+bytecode[i*2+2]);
writeprocessmemory(hProcess,ptr(Addres+i),@buf,1,b ytecount);
end;
почему i прибавляется к адресу не догоняю

Добавлено через 4 минуты
Ааааа все родил откуда берется адрес, а про i так и не понял

VeTaL_UA
20.08.2011, 11:33
Читал на 2 раза и так и не понял. Тыкни носом.
Второй и третий пункты... Во втором описано, как найти jump address, а в 3 - есть код, в котором ясно видно что такое i...

Jok3r666
20.08.2011, 12:28
в котором ясно видно что такое i
i используется в цикле, но для чего он добавляется к адресу я понять не могу. походу я ощще баран
writeprocessmemory(hProcess,ptr(Addres+i),@buf,1,b ytecount);

Dinmaite
20.08.2011, 12:49
Потому как в процедуру передается строка байт (именно в строковом формате).
А каждый байт нужно записать за идущим перед ним.
Отсюда Adress+i

JohnSilver
18.01.2012, 15:08
Объясните на пальцаx как найти базовый указатель.Не понимаю,что значит "смещение $1C".Базовый адрес(если я правильно его нашел) $00924E0C.

Dinmaite
18.01.2012, 19:49
Ищем базовый адрес Perfect World ([Ссылки могут видеть только зарегистрированные и активированные пользователи])

skew222
11.04.2012, 15:53
всем привет, извиняюсь за нубизм, но я в этом деле еще новичок, можете сказать откуда были взяты данные адреса
base_ptr=$009C1514; //Базовый указатель PW
jump_addr=$00455EB3; //Адрес команды, которую мы правим

BritishColonist
11.04.2012, 15:57
skew222, смотрите предыдущий пост, там описан поиск base_ptr.
Второй же адрес вычислен логически (мы просматриваем код функции прыжка и выделяем ключевые моменты. читайте шапку темы, пункт 2).

skew222
11.04.2012, 18:29
так вроде там описывается base_addres, а не base_ptr

skew222
14.04.2012, 17:47
так мне могут ответить?

DeLeTeSHift
09.06.2013, 21:11
А если это приложение на Unity, какой процесс открывать?

mafiosi
22.08.2014, 15:31
так вроде там описывается base_addres, а не base_ptr

скорее всего это одно и тоже