Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.17.184.90] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Всем привет,
Пытаюсь подменить информацию о видеокарте, но столкнулся с проблемой. Так данные о видеокарте (GPU) в большинстве случаев тянутся посредством Win32_VideoController, то выглядит это все как-то так: IWbemServices* services = NULL; ... IEnumWbemClassObject* instanceEnum = NULL; services->CreateInstanceEnum( _bstr_t("Win32_VideoController"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &instanceEnum); Т.е. создается объект класса IWbemServices (допустим *services), а далее вызывается метод services->CreateInstanceEnum("Win32_VideoController"..., &instanceEnum); и данные записываются в заранее созданный объект IEnumWbemClassObject (в данном случаем это instanceEnum). Используя MS Detours 3.0 пробовал перехватить IEnumWbemClassObject::CreateInstanceEnum следующим образом: Попытка получить указатель: typedef HRESULT(WINAPI IWbemServices::*tm_CreateInstanceEnum) (const BSTR strClass, LONG lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum); tm_CreateInstanceEnum True_CreateInstanceEnum = &IWbemServices::CreateInstanceEnum; Моя функция: __declspec(dllexport) HRESULT WINAPI Hooked_CreateInstanceEnum(const BSTR strClass, LONG lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum) { MessageBox(0, L" Hooked!!!", L"Oh yeah, you did it !", MB_OK); //return True_CreateInstanceEnum(strClass, lFlags, pCtx, ppEnum); // я честно хз почему так, но это не верно return 0; } Впихон: BOOL APIENTRY DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) { if (dwReason == DLL_PROCESS_ATTACH) { DetourRestoreAfterWith(); DetourTransactionBegin(); DetourAttach((PVOID*)&True_CreateInstanceEnum, Hooked_CreateInstanceEnum); DetourTransactionCommit(); } else if (dwReason == DLL_PROCESS_DETACH) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach((PVOID*)&True_CreateInstanceEnum, Hooked_CreateInstanceEnum); DetourTransactionCommit(); } { Все это прекрасно компилируется в DLL, но ничего не перехватывается. Хотя по идее это все должно было работать так, что при хуке CreateInstanceEnum у меня бы появлялся MessageBox. Но, увы сия чуда не происходит Как правильно перехватить? |
Сообщ.
#2
,
|
|
|
Подсказали мне значит вешать хук на метод Get. Получился такой код:
#include "stdafx.h" #pragma comment (lib, "detours.lib") typedef HRESULT (WINAPI * True_GetFn)(LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pvtType, LONG *plFlavor); True_GetFn p_Get = nullptr; __declspec(dllexport) HRESULT WINAPI Hooked_Get(LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pvtType, LONG *plFlavor) { if (wcsstr(wszName, L"VideoProcessor") != NULL || wcsstr(wszName, L"Name") != NULL || wcsstr(wszName, L"AdapterCompatibility") != NULL || wcsstr(wszName, L"SystemName") != NULL) { pVal->vt = VT_BSTR; V_BSTR(pVal) = L"NO_DATA"; } else if (wcsstr(wszName, L"AdapterRAM") != NULL) { pVal->vt = VT_UI4; V_BSTR(pVal) = L"0"; } return p_Get(wszName, lFlags, pVal, pvtType, plFlavor); } PVOID SetDetour(PVOID* ppTarget, PVOID pHandler) { if (DetourTransactionBegin() != NO_ERROR) return FALSE; if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) { DetourTransactionCommit(); return NULL; } PDETOUR_TRAMPOLINE pTrampoline = NULL; if (DetourAttachEx(ppTarget, pHandler, &pTrampoline, NULL, NULL) != NO_ERROR) { DetourTransactionCommit(); return NULL; } if (DetourTransactionCommit() != NO_ERROR) { DetourTransactionAbort(); return NULL; } return pTrampoline; } BOOL APIENTRY DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) { HMODULE hLib = LoadLibraryA("fastprox.dll"); if (hLib) { p_Get = (True_GetFn)GetProcAddress(hLib, "?Get@CWbemObject@@UAGJPBGJPAUtagVARIANT@@PAJ2@Z"); if (p_Get) { if (dwReason == DLL_PROCESS_ATTACH) { SetDetour((PVOID*)&p_Get, Hooked_Get); } else if (dwReason == DLL_PROCESS_DETACH) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach((PVOID*)&p_Get, Hooked_Get); DetourTransactionCommit(); } } } return TRUE; } Однако, когда с помощью withdll.exe запускаю dxdiag.exe совместно с моей DLL, то получаю ошибку: Первое окошко: Прикреплённая картинка
Второе - ошибка: Прикреплённая картинка
Кто знает в чем проблема? |
Сообщ.
#3
,
|
|
|
Такое ощущение, что тут нет знатоков
В общем имею такой код: Хедер и определение указателя: #include "stdafx.h" #pragma comment (lib, "detours.lib") typedef HRESULT (WINAPI * True_GetFn)(LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pvtType, LONG *plFlavor); True_GetFn p_Get = nullptr; Моя функция: __declspec(dllexport) HRESULT WINAPI Hooked_Get(LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pvtType, LONG *plFlavor) { if (wcsstr(wszName, L"VideoProcessor") != NULL || wcsstr(wszName, L"Name") != NULL || wcsstr(wszName, L"AdapterCompatibility") != NULL || wcsstr(wszName, L"SystemName") != NULL) { pVal->vt = VT_BSTR; V_BSTR(pVal) = L"NO_DATA"; } else if (wcsstr(wszName, L"AdapterRAM") != NULL) { pVal->vt = VT_UI4; V_BSTR(pVal) = L"0"; } return p_Get(wszName, lFlags, pVal, pvtType, plFlavor); } Функция SetDetour: PVOID SetDetour(PVOID* ppTarget, PVOID pHandler) // Thank you, IChooseYou. { if (DetourTransactionBegin() != NO_ERROR) return FALSE; if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) { DetourTransactionCommit(); return NULL; } PDETOUR_TRAMPOLINE pTrampoline = NULL; if (DetourAttachEx(ppTarget, pHandler, &pTrampoline, NULL, NULL) != NO_ERROR) { DetourTransactionCommit(); return NULL; } if (DetourTransactionCommit() != NO_ERROR) { DetourTransactionAbort(); return NULL; } return pTrampoline; } DllMain: BOOL APIENTRY DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) { HMODULE hLib = GetModuleHandle(L"fastprox.dll"); if (hLib) { p_Get = (True_GetFn)GetProcAddress(hLib, "?Get@CWbemObject@@UAGJPBGJPAUtagVARIANT@@PAJ2@Z"); if (p_Get) { SetDetour(&(PVOID&)p_Get, Hooked_Get); } } return TRUE; } Но он все равно не работает. Запускаемое приложение dxdiag.exe выдает ошибку. Прикреплённая картинка
Прикреплённая картинка
Прикреплённая картинка
Выдвиньте хотя бы какую-то свою версию почему так происходит. |
Сообщ.
#4
,
|
|
|
Ну вы хоть опосля SetDetour проверьте: всё ли там норм произошло; а то вдруг NULL вертухается, а вы забиваете на сие, а?..
|
Сообщ.
#5
,
|
|
|
Цитата Славян @ Ну вы хоть опосля SetDetour проверьте: всё ли там норм произошло; а то вдруг NULL вертухается, а вы забиваете на сие, а?.. Так вроде проверял, все четко. Ткните плз я не вижу этот изъян |
Сообщ.
#6
,
|
|
|
Да мож и нет никакого изъяна. Просто в вашей SetDetour происходят же вызовы с проверками, так что вдруг какой и завершается ошибкой, но в DllMain на это код забивает.
|
Сообщ.
#7
,
|
|
|
Цитата Mr.Newbie @ Выдвиньте хотя бы какую-то свою версию почему так происходит. Вот версия: Как я понял, ты пытаешься перехватить функцию класса. У таких функций есть дополнительный параметр - this. Он автоматически добавляется компилятором. Фактически, протопип функции не такой, как ты используешь. ----- Совершенно очевидно, что надо делать. Надо пытаться трассировать твои опусы отладчиком уровня ядра. |
Сообщ.
#8
,
|
|
|
Цитата ЫукпШ @ У таких функций есть дополнительный параметр - this. Он автоматически добавляется компилятором. Фактически, протопип функции не такой, как ты используешь. Почему не такой ? И откуда доп.параметр this ? Вот что написано на cppreference.com: Цитата Pointers to member functions A pointer to non-static member function f which is a member of class C can be initialized with the expression &C::f exactly. Expressions such as &(C::f) or &f inside C's member function do not form pointers to member functions. Such pointer may be used as the right-hand operand of the pointer-to-member access operators operator.* and operator->*. The resulting expression can be used only as the left-hand operand of a function-call operator: struct C { void f(int n) { std::cout << n << '\n'; } }; int main() { void (C::* p)(int) = &C::f; // pointer to member function f of class C C c; (c.*p)(1); // prints 1 C* cp = &c; (cp->*p)(2); // prints 2 } И тут нет никакого доп.параметра. |
Сообщ.
#9
,
|
|
|
Цитата Mr.Newbie @ Почему не такой ? И откуда доп.параметр this ? Каждая функция используется для всех экземпляров класса. Поэтому, чтобы отличить один экземпляр класса от другого, не статической функции передаётся указатель на структуру данных класса. Лекция |
Сообщ.
#10
,
|
|
|
Цитата Mr.Newbie @ И тут нет никакого доп.параметра "Ты суслика видишь? И я не вижу. А он есть" (С) В любую не статическую функцию класса первым неявным аргументом передается параметр this - указатель на экземпляр\объект класса, для которого вызывается функция. Т.е. для объекта С *с запись c->f(i) это лишь синтаксическая условность ("сахар"), за которой в действительности скрывается вызов функции C::f(c,i) |
Сообщ.
#11
,
|
|
|
Так, окей. Убедили что суслик есть.
Добавил первым параметром, но ведь... typedef HRESULT (WINAPI * True_GetFn)(void*, LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pvtType, LONG *plFlavor); .... __declspec(dllexport) HRESULT WINAPI Hooked_Get(void* suslik,LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pvtType, LONG *plFlavor) { .... всеравно не работает |
Сообщ.
#12
,
|
|
|
Цитата Mr.Newbie @ Так, окей. Убедили что суслик есть. Добавил первым параметром, но ведь... Доказательство как бы намекает, что суслик может быть не один. Выход один - надо отлаживаться. --- Есть ли уверенность, что "Calling Conventions" твоих процедур и вызываемой - совпадают ? |
Сообщ.
#13
,
|
|
|
Calling Conventions - совпадают. У меня такое предчувствие, что я как-то неправильно использую DetourAttachEx/DetourAttach. Перерыл буржнет и нашел посты, правда датированные лохматыми годами и используется там версия detour 1.5, так вот там почти все как у меня только вместо DetourAttachEx/DetourAttach - прописана функция DetourFunction и результат его работы присваивается (в данном случаем у меня) к p_Get
|
Сообщ.
#14
,
|
|
|
Цитата Mr.Newbie @ Это не имеет значения. this может передаваться в регистре. Calling Conventions - совпадают. |
Сообщ.
#15
,
|
|
|
Пришел к такому решению, оно наполовину рабочее... в общем вот код:
typedef HRESULT(__stdcall *IWbemClassObject_Get)(void *__this, LPCWSTR, LONG, VARIANT*, CIMTYPE*, LONG*); IWbemClassObject_Get True_Get; __declspec(dllexport) HRESULT __stdcall Hooked_Get(void *__this, LPCWSTR wszName, LONG lFlags, VARIANT *pVal, CIMTYPE *pvtType, LONG *plFlavor) { printf("wszName: %S\n", wszName); std::cout << "lFlags:" << lFlags << std::endl; std::cout << "pVal:" << pVal << std::endl; std::cout << "pvtType:" << pvtType << std::endl; std::cout << "plFlavor:" << plFlavor << std::endl; return True_Get(__this, wszName, lFlags, pVal, pvtType, plFlavor); } template<typename T> void HookFunction(const char *module, char *signature, T &fn_real, PVOID fn_mine) { HookFunction<T>(DetourFindFunction(module, signature), fn_real, fn_mine); } template<typename T> void HookFunction(DWORD address, T &fn_real, PVOID fn_mine) { HookFunction<T>(reinterpret_cast<PVOID>(address), fn_real, fn_mine); } template<typename T> void HookFunction(PVOID target, T &fn_real, PVOID fn_mine) { fn_real = reinterpret_cast<T>(target); HookFunction<T>(fn_real, fn_mine); } template<typename T> void HookFunction(T &fn_real, PVOID fn_mine) { DetourAttach(&(PVOID&)fn_real, fn_mine); } void ApplyHooks(LPVOID address) //Function address 0x6FD9B723 { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); HookFunction<IWbemClassObject_Get>((FARPROC)address, True_Get, Hooked_Get); DetourTransactionCommit(); } BOOL APIENTRY DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) { AllocConsole(); freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); HMODULE hLib = GetModuleHandle(L"fastprox.dll"); if (hLib) { FARPROC hAdd = GetProcAddress(hLib, "?Get@CWbemObject@@UAGJPBGJPAUtagVARIANT@@PAJ2@Z"); if (hAdd) { if (dwReason == DLL_THREAD_ATTACH) { std::cout << "DLL_THREAD_ATTACH" << std::endl; DisableThreadLibraryCalls(hinst); // Почему-то если его убрать, то через какой-то время dxdiag.exe выбрасывает ошибку CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ApplyHooks, hAdd, 0, 0); } } } return TRUE; } И он мне выдает вот такой списочек в консоли: Прикреплённая картинка
Но есть два непонятных для меня момент - 1). Без DisableThreadLibraryCalls(hinst) в DllMain(...) через какое-то время dxdiag.exe выбивает ошибку, хотя какие-то данные в консоли отобразились. 2). Потерпел фиаско при попытке изменить какие-либо значения, в dxdiag.exe они не поменялись. Предполагаю, что это как-то связано с DisableThreadLibraryCalls... но см.п.1 Пример кода того как пытался поменять значения у строковых переменных. Причем если после изменения вывести в консоль pVal, то оно будет изменено на "NO_DATA", а в dxdiag.exe изменениями и не пахнет. pVal->vt = VT_BSTR; V_BSTR(pVal) = L"NO_DATA"; |