int __cdecl ShowMessageInChatLog(int ChatFlag, int a2, char *Caption, char *Message, int a5)
{...}
Есть ли какие-то отличия в установке хуков на внутренние функции и API функции?
Если декомпилировать эту функцию, то получаю следующую картину:
Код:
Я загружаю в процесс свою длл, где пытаюсь установить хук на эту функцию. Все заканчивается тем, что моя функция перехватчик не выполняется, но и не выполняется оригинальная функция. И краша нет.
При том, что если из моей длл вызвать ShowMessageInChatLog следующим образом:
Код:
int* ShowMessageInChatLog = (int*)0x00480D20;
((int (__cdecl*)(int, int, char*, char*, int))ShowMessageInChatLog)(0, 0, "test", " asd", 0);
((int (__cdecl*)(int, int, char*, char*, int))ShowMessageInChatLog)(0, 0, "test", " asd", 0);
эта функция нормально отрабатывает и выводит что надо и где надо.
Теперь о процессе хукинга:
Код:
struct jmp_far
{
BYTE instr_push; //здесь будет код инструкции push
DWORD arg; //аргумент push
BYTE instr_ret; //здесь будет код инструкции ret
};
static DWORD written; //вспомогательная переменная
static jmp_far jump; //здесь будет машинный код инструкции перехода
void WriteToLog(char* str)
{
FILE* f = fopen("hook_log.txt", "a+");
fprintf(f, "%s\n", str);
fclose(f);
}
int __cdecl Hooked_ShowMessageInChatLog(int chat_flag, int unkn_0, char* caption, char* message, int unkn_1)
{
WriteToLog("Entered to message hook");
//Вызываем оригинальную функцию через указатель
int* ShowMessageInChatLog = (int*)0x00480D20;
int ret_val = ((int (__cdecl*)(int, int, char*, char*, int))ShowMessageInChatLog)(0, 0, "test", " asd", 0);
//int ret_val = ((DWORD (__stdcall*)(int, int, char*, char*, int))ShowMessageInChatLog)(chat_flag, unkn_0, caption, message, unkn_1);
WriteToLog("message hook executed");
return ret_val;
}
void InterceptFunctions(void)
{
// Зададим машинный код инструкции перехода, который затем впишем
// в начало полученного адреса:
jump.instr_push = 0x68;
jump.arg = (DWORD)&Hooked_ShowMessageInChatLog;
jump.instr_ret = 0xC3;
//Запишем команду перехода на нашу функцию поверх этих 6-ти байт
WriteProcessMemory(GetCurrentProcess(), (void*)0x00480D20, &jump, sizeof(jmp_far), &written);
}
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
InterceptFunctions();
}
{
BYTE instr_push; //здесь будет код инструкции push
DWORD arg; //аргумент push
BYTE instr_ret; //здесь будет код инструкции ret
};
static DWORD written; //вспомогательная переменная
static jmp_far jump; //здесь будет машинный код инструкции перехода
void WriteToLog(char* str)
{
FILE* f = fopen("hook_log.txt", "a+");
fprintf(f, "%s\n", str);
fclose(f);
}
int __cdecl Hooked_ShowMessageInChatLog(int chat_flag, int unkn_0, char* caption, char* message, int unkn_1)
{
WriteToLog("Entered to message hook");
//Вызываем оригинальную функцию через указатель
int* ShowMessageInChatLog = (int*)0x00480D20;
int ret_val = ((int (__cdecl*)(int, int, char*, char*, int))ShowMessageInChatLog)(0, 0, "test", " asd", 0);
//int ret_val = ((DWORD (__stdcall*)(int, int, char*, char*, int))ShowMessageInChatLog)(chat_flag, unkn_0, caption, message, unkn_1);
WriteToLog("message hook executed");
return ret_val;
}
void InterceptFunctions(void)
{
// Зададим машинный код инструкции перехода, который затем впишем
// в начало полученного адреса:
jump.instr_push = 0x68;
jump.arg = (DWORD)&Hooked_ShowMessageInChatLog;
jump.instr_ret = 0xC3;
//Запишем команду перехода на нашу функцию поверх этих 6-ти байт
WriteProcessMemory(GetCurrentProcess(), (void*)0x00480D20, &jump, sizeof(jmp_far), &written);
}
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
InterceptFunctions();
}
пробовал по разному объявлять int __cdecl Hooked_ShowMessageInChatLog(int chat_flag, int unkn_0, char* caption, char* message, int unkn_1). вместо __cdecl, __stdcall и т.д. не катит... Файл с надписью "Entered to message hook" не создается
тут jump.arg = (DWORD)&Hooked_ShowMessageInChatLog; пробовал так тоже jump.arg = (DWORD)Hooked_ShowMessageInChatLog; не катит...
Куда пишем адрес функции-перехватчика?
здесь 0x00480D20 это адрес начала функции (которую я зову ShowMessageInChatLog), который я определил в ИДА.
Ваш вопрос заставил меня задуматься, а туда ли я пишу... И как тогда определить куда писать?
В случае хука на API функцию я как-то не задумывался что за адрес дает GetProcAddress, главное что все работает :)
Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL)
адрес, просто адрес...
я бы глянул в дебаггере все же