L2 PTS - Страница 3 - Форум администраторов игровых серверов
Форум администраторов игровых серверов StormWall - Защита от DDos атак
Регистрация Мнения Справка Пользователи Календарь Все разделы прочитаны
Вернуться   Форум администраторов игровых серверов > MMO > Другие игры / Other games

Другие игры / Other games
Прочие онлайн игры и эмуляторы их серверов. Other online games and emulators.

Ответ
Опции темы
Непрочитано 22.08.2016, 10:09   #21
Пользователь

По умолчанию Re: L2 PTS

Удивительно как можно совершить столько ошибок в паре строчек кода
tramp = new unsigned char[6];
Code: C++
Memory leak без delete[] в конце. Лучше сразу на стеке объявить char tramp[6];
tramp[1] = (char)pNewFunc;
Code: C++
Это копирует только один младший байт адреса.
WriteMemory(pAddress, &tramp, sizeof(tramp));
Code: C++
Cразу две ошибки. У тебя tramp - это указатель, следовательно &tramp - адрес этой переременной, а не самого буфера с кодом; по той же причине sizeof(tramp) будет == 4, а не 6.

 
char trampoline[6];
trampoline[0] = 0x68; // push imm32
memcpy(&trampoline[1], pNewFunc, 4); // тут я не понял. pNewFunc у тебя это уже адрес новой функции или это указатель на переменную с адресом новой функции?
trampoline[5] = 0xС3; // ret
WriteMemory(pAddress, trampoline, sizeof(trampoline));
 
Code: C++
Ugly вне форума Ответить с цитированием
Сказали спасибо:
Непрочитано 22.08.2016, 11:09   #22
Пользователь

По умолчанию Re: L2 PTS

Да уж, как можно так издеваться над c++
f1redark вне форума Ответить с цитированием
Непрочитано 22.08.2016, 14:03   #23
Аватар для Sojang
Пользователь

Автор темы (Топик Стартер) Re: L2 PTS

Цитата:
Сообщение от Ugly Посмотреть сообщение
Удивительно как можно совершить столько ошибок в паре строчек кода
tramp = new unsigned char[6];
Code: C++
Memory leak без delete[] в конце. Лучше сразу на стеке объявить char tramp[6];
tramp[1] = (char)pNewFunc;
Code: C++
Это копирует только один младший байт адреса.
WriteMemory(pAddress, &tramp, sizeof(tramp));
Code: C++
Cразу две ошибки. У тебя tramp - это указатель, следовательно &tramp - адрес этой переременной, а не самого буфера с кодом; по той же причине sizeof(tramp) будет == 4, а не 6.

 
char trampoline[6];
trampoline[0] = 0x68; // push imm32
memcpy(&trampoline[1], pNewFunc, 4); // тут я не понял. pNewFunc у тебя это уже адрес новой функции или это указатель на переменную с адресом новой функции?
trampoline[5] = 0xС3; // ret
WriteMemory(pAddress, trampoline, sizeof(trampoline));
 
Code: C++
спасибо)
только теперь адрес то верно пишет, но когда выполняется патченый код то приложение крашится тупо..в чем может быть проблема?
UDP: Посмотрел дебагером, а там по адресу pNewFunc расположено что то очень странное..
Sojang вне форума Ответить с цитированием
Непрочитано 22.08.2016, 15:01   #24
Аватар для Zubastic
ZG troll squad

По умолчанию Re: L2 PTS

Просто длл не загружена, если не ошибаюсь.
А вообще критует из-за ошибки записи скорее всего. Писать через виртуалпротект же надо

Добавлено через 1 минуту
void HookFunction(void* dest, void* src, int countBytes)
{
	DWORD dwProtect = PAGE_READWRITE;
	VirtualProtect(dest, countBytes, dwProtect, &dwProtect);
	*(int*)dest = (int)src;
	VirtualProtect(dest, countBytes, dwProtect, &dwProtect);
}
Code: C++
Для моих нужд этого хватает.
__________________

Последний раз редактировалось Zubastic; 22.08.2016 в 15:03. Причина: Добавлено сообщение
Zubastic вне форума Ответить с цитированием
Непрочитано 22.08.2016, 15:06   #25
Аватар для Sojang
Пользователь

Автор темы (Топик Стартер) Re: L2 PTS

Цитата:
Сообщение от Zubastic Посмотреть сообщение
Просто длл не загружена, если не ошибаюсь.
А вообще критует из-за ошибки записи скорее всего. Писать через виртуалпротект же надо

Добавлено через 1 минуту
void HookFunction(void* dest, void* src, int countBytes)
{
	DWORD dwProtect = PAGE_READWRITE;
	VirtualProtect(dest, countBytes, dwProtect, &dwProtect);
	*(int*)dest = (int)src;
	VirtualProtect(dest, countBytes, dwProtect, &dwProtect);
}
Code: C++
Для моих нужд этого хватает.
так длл то вроде как загружается и код патчится вот только как то криво у меня все работает

Добавлено через 19 минут
Я тут подумал, а у меня вообще адрес функции правильно определятся?
CPatchEngine::Instance()->WriteCall((BYTE *)0x14010DF47, (DWORD *)PatchInit);
Code: C++
 
void CPatchEngine::WriteCall(BYTE *pAddress, DWORD *pNewFunc)
{
	char trampoline[6];
	trampoline[0] = 0x68; // push imm32
	memcpy(&trampoline[1], &pNewFunc, 4); 
	trampoline[5] = 0xC3; // ret
	WriteMemory(pAddress, trampoline, sizeof(trampoline));
}
 
Code: C++

Последний раз редактировалось Sojang; 22.08.2016 в 15:25. Причина: Добавлено сообщение
Sojang вне форума Ответить с цитированием
Непрочитано 22.08.2016, 15:49   #26
Пользователь

По умолчанию Re: L2 PTS

Функция называется WriteCall, но вообще-то равносильна jmp, а не call. Предварительно на стек следует положить адрес, куда вернётся управление после возврата из функции.
Ugly вне форума Ответить с цитированием
Непрочитано 22.08.2016, 21:23   #27
Аватар для Sojang
Пользователь

Автор темы (Топик Стартер) Re: L2 PTS

Цитата:
Сообщение от Ugly Посмотреть сообщение
Функция называется WriteCall, но вообще-то равносильна jmp, а не call. Предварительно на стек следует положить адрес, куда вернётся управление после возврата из функции.
Я что то вообще запутался
мне в начале темы говорили про:
push Adr
ret
я как понял в данном случае это не верно будет для call?
Sojang вне форума Ответить с цитированием
Непрочитано 23.08.2016, 00:58   #28
Аватар для Sojang
Пользователь

Автор темы (Топик Стартер) Re: L2 PTS

Такс ладно собравшись с мыслями я что то вообще в тупик попал.
Размер
push Adr 
ret
Code: ASM
6 байт, а размер
call Adr
Code: ASM
5 байт и вот тут и получается бред какой то...
Далее нужно же после вызова моей функции вернуться к оригинальной и тут я вообще в тупик попал что то
Тогда нужно писать что то вроде
mov rax, Adr // моя функция
call rax
mov rax, Adr // оригинал
call rax
Code: ASM
и опять же размер больше 5 байт и все пойдет через попу..

:):
Свернуть ↑Развернуть ↓
Sojang вне форума Ответить с цитированием
Непрочитано 23.08.2016, 10:01   #29
Аватар для n3k0nation
Antihero

По умолчанию Re: L2 PTS

Sojang, для начала определитесь вообще, что Вы хотите, а не бездумно копируйте код)
jmp - безусловный переход и не более того.
push/ret - аналог jmp.
call - кидает на стек текущий адрес и прыгает на указанный адрес; если функция ret-ается, то у нас происходит возврат туда откуда был call (адрес caller'a на стеке же есть).

Для вызова оригинальной функции нужно выполнить, то что было затерто переходом (jmp/push-ret/call), обычно это пролог функции по какому-нибудь calling conventions, а-ля, stdcall для win32. При вызове оригинальной функции, мы смещаемся на то количество байтов, которое мы перетерли.
Пример: адрес функции 0x1000, мы переписали первые 5 байт на jmp, значит мы реализуем перетертые 5 байт и делаем переход на 0x1005, грубо говоря.

Если затерто было БОЛЬШЕ пролога, да и вообще чето как-то получилось, то что размер перетертых команд не совпадает с размером команд, которыми мы заменили, то пишем дизассемблер длин, нопим кривые куски команд и делаем все то же самое, но реализовывать обратный переход надо уже с учетом того, что мы нопнули.

Можно конечно оботись костылем такого вида: если у нас перехваченная функция гарантированно дергается в один поток, то можно просто снимать хук, когда мы хотим перейти назад и ставить его опять, после того, как мы получим результат работы функции. Главное не забыть сбросить instruction cache, иначе ничего не поменяется
__________________
m0nster.art - clear client patches, linkz to utils & code.
Гадаю по капче.
n3k0nation вне форума Ответить с цитированием
Непрочитано 23.08.2016, 14:10   #30
Аватар для Sojang
Пользователь

Автор темы (Топик Стартер) Re: L2 PTS

Цитата:
Сообщение от n3k0nation Посмотреть сообщение
Sojang, для начала определитесь вообще, что Вы хотите, а не бездумно копируйте код)
jmp - безусловный переход и не более того.
push/ret - аналог jmp.
call - кидает на стек текущий адрес и прыгает на указанный адрес; если функция ret-ается, то у нас происходит возврат туда откуда был call (адрес caller'a на стеке же есть).

Для вызова оригинальной функции нужно выполнить, то что было затерто переходом (jmp/push-ret/call), обычно это пролог функции по какому-нибудь calling conventions, а-ля, stdcall для win32. При вызове оригинальной функции, мы смещаемся на то количество байтов, которое мы перетерли.
Пример: адрес функции 0x1000, мы переписали первые 5 байт на jmp, значит мы реализуем перетертые 5 байт и делаем переход на 0x1005, грубо говоря.

Если затерто было БОЛЬШЕ пролога, да и вообще чето как-то получилось, то что размер перетертых команд не совпадает с размером команд, которыми мы заменили, то пишем дизассемблер длин, нопим кривые куски команд и делаем все то же самое, но реализовывать обратный переход надо уже с учетом того, что мы нопнули.

Можно конечно оботись костылем такого вида: если у нас перехваченная функция гарантированно дергается в один поток, то можно просто снимать хук, когда мы хотим перейти назад и ставить его опять, после того, как мы получим результат работы функции. Главное не забыть сбросить instruction cache, иначе ничего не поменяется
Такс я чет не понял про пролог..я вообще патчил в приложении вызовы например call это оказывается не правильно?
Я вообще туплю что то и нихуа не понимаю
Sojang вне форума Ответить с цитированием
Ответ


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


© 2007–2024 «Форум администраторов игровых серверов»
Защита сайта от DDoS атак — StormWall
Работает на Булке неизвестной версии с переводом от zCarot
Текущее время: 21:15. Часовой пояс GMT +3.

Вверх