Сообщений: 21
Тем: 2
Зарегистрирован: Feb 2014
Репутация:
57
Удивительно как можно совершить столько ошибок в паре строчек кода 
[SRC="c++"]tramp = new unsigned char[6];[/SRC]
Memory leak без delete[] в конце. Лучше сразу на стеке объявить char tramp[6];
[SRC="c++"]tramp[1] = (char)pNewFunc;[/SRC]
Это копирует только один младший байт адреса.
[SRC="c++"]WriteMemory(pAddress, &tramp, sizeof(tramp));[/SRC]
Cразу две ошибки. У тебя tramp - это указатель, следовательно &tramp - адрес этой переременной, а не самого буфера с кодом; по той же причине sizeof(tramp) будет == 4, а не 6.
[SRC="c++"]
char trampoline[6];
trampoline[0] = 0x68; // push imm32
memcpy(&trampoline[1], pNewFunc, 4); // тут я не понял. pNewFunc у тебя это уже адрес новой функции или это указатель на переменную с адресом новой функции?
trampoline[5] = 0xС3; // ret
WriteMemory(pAddress, trampoline, sizeof(trampoline));
[/SRC]
Сообщений: 78
Тем: 0
Зарегистрирован: May 2015
Репутация:
577
Да уж, как можно так издеваться над c++
Сообщений: 357
Тем: 58
Зарегистрирован: Jan 2016
Репутация:
116
Ugly Написал:Удивительно как можно совершить столько ошибок в паре строчек кода 
[SRC="c++"]tramp = new unsigned char[6];[/SRC]
Memory leak без delete[] в конце. Лучше сразу на стеке объявить char tramp[6];
[SRC="c++"]tramp[1] = (char)pNewFunc;[/SRC]
Это копирует только один младший байт адреса.
[SRC="c++"]WriteMemory(pAddress, &tramp, sizeof(tramp));[/SRC]
Cразу две ошибки. У тебя tramp - это указатель, следовательно &tramp - адрес этой переременной, а не самого буфера с кодом; по той же причине sizeof(tramp) будет == 4, а не 6.
[SRC="c++"]
char trampoline[6];
trampoline[0] = 0x68; // push imm32
memcpy(&trampoline[1], pNewFunc, 4); // тут я не понял. pNewFunc у тебя это уже адрес новой функции или это указатель на переменную с адресом новой функции?
trampoline[5] = 0xС3; // ret
WriteMemory(pAddress, trampoline, sizeof(trampoline));
[/SRC]
спасибо)
только теперь адрес то верно пишет, но когда выполняется патченый код то приложение крашится тупо..в чем может быть проблема?
UDP: Посмотрел дебагером, а там по адресу pNewFunc расположено что то очень странное..
Сообщений: 5,862
Тем: 105
Зарегистрирован: Sep 2010
Репутация:
13,014
08-22-2016, 03:01 PM
(Сообщение последний раз редактировалось: 08-22-2016, 03:03 PM Zubastic.)
Просто длл не загружена, если не ошибаюсь.
А вообще критует из-за ошибки записи скорее всего. Писать через виртуалпротект же надо
Добавлено через 1 минуту
[SRC="c++"]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);
}[/SRC]
Для моих нужд этого хватает.
Сообщений: 357
Тем: 58
Зарегистрирован: Jan 2016
Репутация:
116
08-22-2016, 03:06 PM
(Сообщение последний раз редактировалось: 08-22-2016, 03:25 PM Sojang.)
Zubastic Написал:Просто длл не загружена, если не ошибаюсь.
А вообще критует из-за ошибки записи скорее всего. Писать через виртуалпротект же надо 
Добавлено через 1 минуту
[SRC="c++"]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);
}[/SRC]
Для моих нужд этого хватает.
так длл то вроде как загружается  и код патчится вот только как то криво у меня все работает
Добавлено через 19 минут
Я тут подумал, а у меня вообще адрес функции правильно определятся? 
[SRC="c++"]CPatchEngine::Instance()->WriteCall((BYTE *)0x14010DF47, (DWORD *)PatchInit);[/SRC]
[SRC="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));
}
[/SRC]
Сообщений: 21
Тем: 2
Зарегистрирован: Feb 2014
Репутация:
57
Функция называется WriteCall, но вообще-то равносильна jmp, а не call. Предварительно на стек следует положить адрес, куда вернётся управление после возврата из функции.
Сообщений: 357
Тем: 58
Зарегистрирован: Jan 2016
Репутация:
116
Ugly Написал:Функция называется WriteCall, но вообще-то равносильна jmp, а не call. Предварительно на стек следует положить адрес, куда вернётся управление после возврата из функции.
Я что то вообще запутался:redlol:
мне в начале темы говорили про:
push Adr
ret
я как понял в данном случае это не верно будет для call?
Сообщений: 357
Тем: 58
Зарегистрирован: Jan 2016
Репутация:
116
Сообщений: 2,454
Тем: 53
Зарегистрирован: Apr 2010
Репутация:
19,728
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.
Гадаю по капче.
Сообщений: 357
Тем: 58
Зарегистрирован: Jan 2016
Репутация:
116
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 это оказывается не правильно? 
Я вообще туплю что то и нихуа не понимаю :redlol::redlol:
|