вот вся длл моя. Код (Text): #include <windows.h> #include <stdio.h> const int NumberOfOpcodes=8; BOOL Detour(void); BOOL Retour(void); void MyFunction(void); void *DetourClassFunc(BYTE *src, const BYTE *dst, const int len); void RetourClassFunc(BYTE *src, BYTE *restore, const int len); void *VTableFunction(void **VTabEntry, DWORD index); void *OldFunctionAddress; void **VTable; void *bytes; INT WINAPI DllMain ( HANDLE hinstDLL, ULONG fdwReason, LPVOID lpvReserved ) { switch (fdwReason) { case DLL_PROCESS_ATTACH: if (!Detour()) { return FALSE; } break; case DLL_PROCESS_DETACH: if(!Retour()) return FALSE; break; } return TRUE; } BOOL Detour(void) { HMODULE hModule; hModule = GetModuleHandle("Library.dll"); VTable = (VOID **)((DWORD)hModule + 0xACA08); OldFunctionAddress = VTableFunction(VTable,2); bytes = DetourClassFunc((BYTE *)OldFunctionAddress, (BYTE *)MyFunction, NumberOfOpcodes); return TRUE; } BOOL Retour(void) { RetourClassFunc((BYTE *)OldFunctionAddress, (BYTE *)bytes, NumberOfOpcodes); return TRUE; } VOID MyFunction() { MessageBox(NULL,"Hello from MyFunction!","OK!",MB_OK); } void *DetourClassFunc(BYTE *src, const BYTE *dst, const int len) { int i; BYTE *jmp = (BYTE*)malloc(len+8); DWORD dwBack; VirtualProtect(src, len, PAGE_READWRITE, &dwBack); memcpy(jmp+3, src, len); // calculate callback function call jmp[0] = 0x58; // pop eax jmp[1] = 0x59; // pop ecx jmp[2] = 0x50; // push eax jmp[len+3] = 0xE9; // jmp *(DWORD*)(jmp+len+4) = (DWORD)((src+len) - (jmp+len+3)) - 5; // detour source function call src[0] = 0x58; // pop eax; src[1] = 0x51; // push ecx src[2] = 0x50; // push eax src[3] = 0xE9; // jmp *(DWORD*)(src+4) = (DWORD)(dst - (src+3)) - 5; for( i=8; i < len; i++ ) src[i] = 0x90; VirtualProtect(src, len, dwBack, &dwBack); return jmp; } void RetourClassFunc(BYTE *src, BYTE *restore, const int len) { DWORD dwBack; VirtualProtect(src, len, PAGE_READWRITE, &dwBack); memcpy(src, restore+3, len); restore[3] = 0xE9; *(DWORD*)(restore+4) = (DWORD)(src - (restore+3)) - 5; VirtualProtect(src, len, dwBack, &dwBack); } void *VTableFunction(void **VTabEntry, DWORD index) { return *(void **)((DWORD)VTabEntry + index*4); }
Ну а почену не хочиш.. скинуть все и ту Длл которую хукаеш.. мне интересно посмотреть на такой вариант хука.. чем тебе тот не подхидит.. проверен получилса.. стати подсоединять тя может сама винда.. (я несказал што програмлю сильно, но делать неф.. вот бы посмотрел.. ) ну как хочиш.. сам пока писал хук 4 раза все сначала нада было переделывать.. http://www.ring3circus.com/source/direct3d_9_hook.cpp чем плох вариант ?
Интересно, раз идет такая жесткая привязка к адресу, почему бы просто не взять конкретный адрес интересующей ф-ии в vftable и не подменить его на свой? Т.е. просто скопировать значение по адресу 100ACA10 и записать адрес своей ф-ии в этот же адрес.
Mika0x65 я ж говорю, было принципиально использование DetourClassFunc... поменял адреса, не работает... точнее результата не вижу. наверное программа при загрузке сразу адреса функций получает, а потом использует. И инжектиться и изменять что-либо уже бестолку
InTRUEdeR Не влез так и всуть всего.. но может вылетаеш ты братела со своим перехватом.. ты хоть видиш што происходит у тебя в нутри, незнаю я к примеру Олькой смог посмотреть когда гнал с етими Инжектор... ладно надоело .. больше не буду срать своим кревым русским..
_mikityak_, вижу что внутри получаются нужные мне адреса и их замены. сейчас просто не хочет срабатывать моя функция. варианта два: или перехватываемая функция никогда не вызывается или вызывается по ранее вычисленному адресу, не обращая внимания на то, что я заменил адрес...
позно ловиш.. яш сказал тутше пущай винда ставит хук.. просто не хочет срабатывать извени в лом разбиратса когданибуть, посмотрим твой вариант хука.. мой ставим Код (Text): void __stdcall wglSwapBuffers_My(HDC hDC) { ... WriteHook(address_wglSwapBuffers, backup_wglSwapBuffers); (reinterpret_cast<type_wglSwapBuffers> (address_wglSwapBuffers))(hDC); WriteHook(address_wglSwapBuffers, patch_wglSwapBuffers); ... только што возвратил.. назад работу хукнотой функцыи.. } последний раз ломал голову тем што эта гадость которую хачу хукнуть.. выгружаетса и снова загружаетса прогой которая ее использует.. при старте
InTRUEdeR У тебя же начало vtable по смещению 0xACA04: Код (Text): 0000:100ACA04 ; Exported entry 672. ??_7CButton@@6B@ 0000:100ACA04 public ??_7CButton@@6B@ 0000:100ACA04 ; const CButton::`vftable' А ты используешь 0xACA08: Код (Text): VTable = (VOID **)((DWORD)hModule + 0xACA08); OldFunctionAddress = VTableFunction(VTable,2); Т.е. получаешь адрес четвёртой функции из vtable (адрес CControlBase::Create(long)). Неужели так и задумано? Вообще странно. Не должно быть таких адресов. Там по идее должно быть число (Базовый_Адрес_Dll + 0x28360). Конечно, ничего не мешает ей это делать, но один оценил бы это либо как бессмысленные расходы ресурсов, либо как какой-то хак. Так что маловероятно. Mika0x65 Как самый первый же!
Sol_Ksacap Если не ошибаюсь, то в общем случае указатель на vtable идет после последнего члена класса, в котором объявлен первый виртуальный метод. Самым первым он будет в том случае, когда класс является наследником некого базового класса с виртуальными методами, но без полей (членов), как например TObject в VCL. Объявляемые в потомках дополнительные члены идут после указателя на vtable, поэтому в итоге он оказывается либо в самом начале (если наследование идет от виртуального "пустого" класса) или в общем случае где-то в середине структуры класса
А-ха. Похоже, это Борланд такое генерирует, да? Просто компилятор от MS всегда стремится сделать указатель на vtable первым членом класса. Интересно, запихнёт ли VS2k8 указатель на vtable в середину объекта в следующем случае: Код (Text): class A { public: int a1, a2; A(): a1(0xAAAAaaa1) { a2 = 0xAAAAaaa2; }; }; class B: public A { public: int b1, b2; B(): b1(0xBBBBbbb1) { b2 = 0xBBBBbbb2; }; virtual int __cdecl dummy1() { return 1; }; virtual int __cdecl dummy2(int) { return 2; }; }; int main(int, int, int, int) { B b; } ...Нет, не запихнул. Вместо этого компилятор создал родительский объект внутри дочернего %)
Ну понятно, что если классы объявлены в одном модуле (h-файле), то компилятор может "запихнуть" vtable в начало. А если в разных модулях, которые могут использоваться в разных прогах или dll ? Тут уж логично или всегда резервировать место под vtable независимо от наличия виртуальных методов в классе или уж вставлять его "как придется" при первом объявлении вирт.метода.
Ммм... Ведь чтобы произошло наследование, компилятор должен видеть объявление родительского класса. Т.е. пусть класс 'A' реализован в dll, а класс 'B', наследующий класс 'A' - в exe-файле. При создании exe-файла компилятор видит, как объявлен класс 'A'; а мы видим, что единственная деталь, которая изменяется при кодогенерации - конструктор 'A', вызывающийся из dll. Понимаем хотя, что всё это ничего не значит - ибо это лишь детали реализации наследования одним конкретным компилятором... InTRUEdeR Ну как? Можешь попробовать под отладчиком вписать по адресу (Адрес_Загрузки_Dll + 0xACA10) заведомо левое значение - например, 0x0000FFFF. И если прога упадёт при вызове Create, то ты будешь знать, что перехват таким способом возможен