Перейти к содержанию

[Ошибки][c++][Hook MessageBox]


Рекомендуемые сообщения

Делаю хук меседжбокса и что то у меня по ходу не то

вот кодинг


#include <Windows.h>

DWORD address_hook = 0;
void SetHook();
void MEMwrite(void *adr, void *ptr, int size)
{
DWORD OldProtection;
VirtualProtect(adr,size,PAGE_EXECUTE_READWRITE, &OldProtection);
memcpy(adr,ptr,size);
VirtualProtect(adr,size,OldProtection, &OldProtection);
}
int hookedFunc(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType)
{
DWORD prot =0;
DWORD addres =(DWORD)MessageBoxA;
VirtualProtect((void*)addres,sizeof((PBYTE)SetHook),PAGE_EXECUTE_READWRITE,&prot);
address_hook = (DWORD)hookedFunc;
MEMwrite((void*)addres,(void*)"\x8B\xFF\x55\x8B\xEC",5);
MessageBoxA(hWnd,lpText,"Hook me",uType);
memcpy((void*)addres,(PBYTE)SetHook,sizeof((PBYTE)SetHook));
VirtualProtect((void*)addres,sizeof((PBYTE)SetHook),prot,&prot);
return 1;
}

void SetHook()
{
_asm jmp hookedFunc
}


HRESULT HOOK()
{
MessageBox(0,"Хук установлен",0,0);
address_hook =(DWORD)hookedFunc;
DWORD addres =(DWORD)MessageBoxA;
DWORD prot =0;
VirtualProtect((void*)addres,sizeof((PBYTE)SetHook),PAGE_EXECUTE_READWRITE,&prot);
memcpy((void*)addres,(PBYTE)SetHook,sizeof((PBYTE)SetHook));
VirtualProtect((void*)addres,sizeof((PBYTE)SetHook),prot,&prot);
::ExitThread(1337);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
CreateThread(0,0,(LPTHREAD_START_ROUTINE)HOOK,0,0,0);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

Рисует джамп но при попытке вызова функции краш... %)

Ссылка на комментарий
Поделиться на другие сайты

  • 5 лет спустя...

Аналогичная проблема, только код немного другой (взял из этого видеурока https://youtu.be/RwH0ThOrodg). Вместо относительного адреса выдает абсолютный, который ведет совсем в другое место.

Ссылка на комментарий
Поделиться на другие сайты

Решил проблему. Дело вот в чем: в видео автор заменяет команды шаблона call dword ptr [указатель]. Эти команды составляют по размеру 6 байтов. А в моем случае нужно было заменить команды шаблона call offset, которые имеют размер 5 байт.

Для примера я скопировал код из видео:
 

Спойлер

void CallHook()
{
  _asm call dword ptr hooked_messagebox
}

DWORD WINAPI Hook_thread (LPVOID)
{
  hooked_messagebox = (DWORD)HookedMessageBox;
  DWORD call_adress = 0x0120116A;
  DWORD old_prot = 0;

  VirtualProtect((void*)call_adress, 5, PAGE_EXECUTE_READWRITE, &old_prot);
  memcpy((void*)call_adress, (PBYTE)CallHook, 5);
  VirtualProtect((void*)call_adress, 5, old_prot, &old_prot);
  
  ::ExitThread(1337);
}

 

Теперь же он должен выглядеть вот так (часть кода взята с гитхаба https://github.com/khycan/API-Hooking/blob/master/API Hooking %2B DLL Injection/dll/DllMain.cpp):
 

Спойлер

DWORD WINAPI Hook_thread (LPVOID)
{
  BYTE NewBytes[5]={0xE8,0,};
  DWORD call_adress = 0x0120116A;
  DWORD hooked_messagebox = ((DWORD)HookedMessageBox) - 0x0120116A - 5;
  memcpy(&NewBytes[1], &hooked_messagebox, 4);
  DWORD old_prot = 0;

  VirtualProtect((void*)call_adress, 5, PAGE_EXECUTE_READWRITE, &old_prot);
  memcpy((void*)call_adress, (PBYTE)NewBytes, 5);
  VirtualProtect((void*)call_adress, 5, old_prot, &old_prot);
  
  ::ExitThread(1337);
}

 

Как можно видеть, код с ассемблером я удалил за ненадобностью. Теперь же нам нужно найти смещение, которое находится по формуле:

offset = HookFunc - DestFunc - 5, где HookFunc - это адрес нашей функции из dll, которую мы инжектим, DestFunc - адрес, по которому производится изменение кода (в случае с кодом из видео, 0x0120116A). Число 5 - это размер нашей команды, которую мы хотим заменить. Также создается массив байтов, в первый байт которого уже записан первый байт, кодирующий команду call. Мы заменяем все байты в этом массиве, кроме первого. После этого весь массив копируем по адресу, где мы хотим вызвать нашу функцию из либы. Можно часть кода вынести в отдельную функцию для удобства замены нескольких адресов.

Надеюсь доступно объяснил.

Изменено пользователем faik003
Вставка ссылки
Ссылка на комментарий
Поделиться на другие сайты

46 минут назад, faik003 сказал:

void CallHook()

Тут не правильно объявлена функция с асм вставкой, нужно использовать голую декларацию

__declspec(naked) void CallHook()

Чтобы для твоей функции компилятор не генерировал пролог и эпилог, а использовать массив байт это изврат, когда есть асм вставки, таким только на C# занимаются?

 

46 минут назад, faik003 сказал:

BYTE NewBytes[5]={0xE8,0,};

 

И кстати, используя опкод E8 хук не крашит приложение?

Ссылка на комментарий
Поделиться на другие сайты

22 минуты назад, partoftheworlD сказал:

Тут не правильно объявлена функция с асм вставкой, нужно использовать голую декларацию

У автора видео каким-то образом получилось нормально заменить команду или это просто единичный случай и надеяться не стоит на будущее?

 

22 минуты назад, partoftheworlD сказал:

а использовать массив байт это изврат, когда есть асм вставки

Ладно, допустим, что я в правду извращаюсь. Тогда можно хоть пример того, как должен выглядеть asm код?
 

22 минуты назад, partoftheworlD сказал:

И кстати, используя опкод E8 хук не крашит приложение?

Нет, не крашит. А с чего бы ему это делать?

Изменено пользователем faik003
Ссылка на комментарий
Поделиться на другие сайты

44 минуты назад, faik003 сказал:

А с чего бы ему это делать?

Ну хук вешают обычно опкодом E9(jmp), ведь E8 это call, который сохраняет в стек позицию для возврата, разница у них не большая, но именно она может стать причиной краша, а чтобы такое заметить под отладкой нужно быть сверхвнимательным.

 

44 минуты назад, faik003 сказал:

Тогда можно хоть пример того, как должен выглядеть asm код?

 

__declspec(naked) void Ammo()
{
	__asm 
	{

	mov AmmoBase , esi
	MOV [ESI + 0x1414], 0x63
	jmp [OrigAmmo]

	}

}

если единичная инструкция, то 

 

__declspec(naked) void Ammo()
{
	_asm mov AmmoBase , esi
}

 

44 минуты назад, faik003 сказал:

У автора видео каким-то образом получилось нормально заменить команду

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

Ссылка на комментарий
Поделиться на другие сайты

30 минут назад, partoftheworlD сказал:

Ну хук вешают обычно опкодом E9(jmp), ведь E8 это call, который сохраняет в стек позицию для возврата

Наверное стоило упомянуть, что мне не нужен был хук в привычном понимании этого слова. Я делаю реверсинг на С++ нужной мне функции, сравниваю его дизассемблерный листинг с листингом из дизассемблера, затем просто перенаправляю цикл игры на свою функцию.

38 минут назад, partoftheworlD сказал:

 


__declspec(naked) void Ammo()
{
	__asm 
	{

	mov AmmoBase , esi
	MOV [ESI + 0x1414], 0x63
	jmp [OrigAmmo]

	}

}

если единичная инструкция, то 

 


__declspec(naked) void Ammo()
{
	_asm mov AmmoBase , esi
}

Либо лыжи не едут, либо на ночь глядя не понимаю, как использовать ваши примеры в моей ситуации

Ссылка на комментарий
Поделиться на другие сайты

13 часов назад, faik003 сказал:

перенаправляю цикл игры на свою функцию

А в чем собственно разница?) Вы можете сохранить перезаписаные 5 байт(если 32х) перед выходом из Вашей функции просто востановить их и вызвать оригинал :)

 

Ссылка на комментарий
Поделиться на другие сайты

34 минуты назад, temtriss сказал:

А в чем собственно разница?) Вы можете сохранить перезаписаные 5 байт(если 32х) перед выходом из Вашей функции просто востановить их и вызвать оригинал

Может я чего-то не понимаю, но зачем это?

Изменено пользователем faik003
Ссылка на комментарий
Поделиться на другие сайты

1 час назад, faik003 сказал:

но зачем это?

Может быть и не зачем, но просто я впервые вижу что бы хукали функцию не джампом, а коллом, Но как было сказано выше, разницы почти нету, кроме того, что call оставляет в стеке адрес для возврата, но я использую обычно другую конструкцию

		push param0
        push param1
        ....
            mov eax, _retnAddr
			push eax
            .....
_retnAddr :
		mov Result, eax
		retn 8

 

Ссылка на комментарий
Поделиться на другие сайты

42 минуты назад, temtriss сказал:

я впервые вижу что бы хукали функцию не джампом, а коллом

Я уже выше писал, что это не совсем хук. Представим такую ситуацию: есть функция в игре, пусть будет называться tempFunc. Я провожу ее реверсинг на С++ и выношу код в функцию HookFunc, которая будет находиться в dll. Затем я нахожу место, где вызывается tempFunc и просто заменяю адрес (точнее смещение) так, чтобы произошел вызов HookFunc через dll, которую мы инжектим к игре. Мне не нужно, чтобы игра повторно вызывала оригинальную функцию, то есть tempFunc, поэтому в данной ситуации использование jump для меня избыточно. В каком-то смысле я заменяю ф-ции игры своими из dll и таким образом потихоньку "декомпилирую" игру.

Ссылка на комментарий
Поделиться на другие сайты

11 часов назад, faik003 сказал:

Я уже выше писал, что это не совсем хук. Представим такую ситуацию: есть функция в игре, пусть будет называться tempFunc. Я провожу ее реверсинг на С++ и выношу код в функцию HookFunc, которая будет находиться в dll. Затем я нахожу место, где вызывается tempFunc и просто заменяю адрес (точнее смещение) так, чтобы произошел вызов HookFunc через dll, которую мы инжектим к игре. Мне не нужно, чтобы игра повторно вызывала оригинальную функцию, то есть tempFunc, поэтому в данной ситуации использование jump для меня избыточно. В каком-то смысле я заменяю ф-ции игры своими из dll и таким образом потихоньку "декомпилирую" игру.

Что тогда мешает использовать точный адрес вызова? 

Путем подмены обычного call на свой? Из длл через naked метод который как было сказано не комеилирует доп код

  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

11 часов назад, roma91212 сказал:

Что тогда мешает использовать точный адрес вызова? 

Путем подмены обычного call на свой? Из длл через naked метод который как было сказано не комеилирует доп код

Что ещё за точный адрес вызова?

Пример можете показать, как должен выглядеть naked метод? 

Ссылка на комментарий
Поделиться на другие сайты

Блин, у меня складывается впечатление, что либо не читают мои посты перед тем, как ответить, либо я чего-то не понимаю. Я уже сказал, что в моей ситуации нужен именно call, а не jump. И пример кода на asm мне не о чем не говорит, кроме как ещё больше запутывает. Возможно я прошу слишком много, но можно ли привести пример asm в согласии с моим постом, где я описывал свою ситуацию? 

Ссылка на комментарий
Поделиться на другие сайты

1 минуту назад, Xipho сказал:

Ты попросил пример naked кода. В ссылке на сообщение partoftheworlD есть как раз naked функция с asm кодом. Разве это не то, что ты просил?

Да, но я не понимаю как применить данный пример к моей ситуации.

Или это из разряда: кидаем тебе пример без контекста, а там уже сам додумывай.

Ссылка на комментарий
Поделиться на другие сайты

Хм. Ну давай рассуждать. Тебе нужно сделать CodeCave, и на него прыгнуть из какого-то оригинального кода, так?

Если так, то вот эта вот naked функция и станет тем самым код кейвом, на который нужно будет прыгать. И писать в ней нужно ровно то, что обычно

пишется в кодкейве (как в автоассемблере СЕ). Далее из основного кода ты прыгаешь на эту свою функцию и получаешь то, что нужно.

Ссылка на комментарий
Поделиться на другие сайты

14 часов назад, faik003 сказал:

Блин, у меня складывается впечатление, что либо не читают мои посты перед тем, как ответить, либо я чего-то не понимаю.

ну Lol

 

int test1(){
__rdtsc();
__rdtsc();
__rdtsc();
return 1;
}

void test2(){
__rdtsc();
}

DWORD_PTR Hook = (DWORD_PTR)test1;
DWORD_PTR Func = (DWORD_PTR)test2;
DWORD_PTR temp;
static BYTE Call[] = {0xE8,0x00,0x00,0x00,0x00,0x90};
*(DWORD*)(Call+1) = (Func-5)-Hook;
VirtualProtect((LPVOID)Hook,sizeof Call,PAGE_EXECUTE_READWRITE,&temp);
memcpy((LPVOID)Hook,Call,sizeof Call);
VirtualProtect((LPVOID)Hook,sizeof Call,temp,&temp);

 

  • Понравилось 1
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

7 часов назад, Xipho сказал:

Тебе нужно сделать CodeCave, и на него прыгнуть из какого-то оригинального кода, так?

Вы про эти CodeCave'ы? Если да, то зачем все так усложнять? Мне нужно просто перебросить вызов оригинальной функции на мою функцию из dll. И даже если каким-то образом ваш метод является более эффективным, то как я буду создавать CodeCave в Visual Studio?

Ссылка на комментарий
Поделиться на другие сайты

8 часов назад, gmz сказал:

ну Lol

Да, ваш способ замены смещения более изящный, чем мой. Только вод одно не понимаю - зачем было вставлять 6 байтом в массиве опкод 0x90 (NOP)? Он же перезапишет следующую инструкцию, которая следует за инструкцией call.

Изменено пользователем Xipho
Не нужно цитировать сообщения целиком. Никому не хочется одно и то же сообщение два раза прочитывать - в оригинале и в процитированном виде.
Ссылка на комментарий
Поделиться на другие сайты

7 минут назад, gmz сказал:

в примере хук ставится на х3 rdtsc = 6 байт

 

Я так и подумал, что ты опирался на видео Dmitry K. - Не мог @gmz ошибиться.?

 

Но у @faik003 5 байт:

В 15.06.2018 в 22:46, faik003 сказал:

А в моем случае нужно было заменить команды шаблона call offset, которые имеют размер 5 байт.

 

 

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.