Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.11.2017, 18:10   #1
SuprSonic
Пользователь
 
Регистрация: 07.08.2016
Сообщений: 16
Вопрос [Help] Подмена данных о GPU с помощью MS Detours 3.0

Привет всем,
Пытаюсь подменить информацию о видеокарте (производитель, имя и т.д.), но столкнулся с проблемой. Данные о видеокарте (GPU) в большинстве случаев тянутся посредством Win32_VideoController. Вот как то так:
Код:
IEnumWbemClassObject::CreateInstanceEnum(_bstr_t("Win32_VideoController"),WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &instanceEnum);
Т.е. вначале создается объект класса IWbemServices (допустим *services), а далее вызывается метод services->CreateInstanceEnum("Win32_VideoCon troller"..., &instanceEnum); и данные записываются в заранее созданный объект IEnumWbemClassObject (в данном случаем это instanceEnum).

Используя MS Detours 3.0 пробовал перехватить IEnumWbemClassObject::CreateInstanc eEnum следующим образом:

Попытка получить указатель:
Код:
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;
}
Inject:
Код:
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.

Возможно есть другие варианты решения подмены информаци о GPU, но я их не знаю, поэтому пытаюсь сделать так. В общем помогите чем могёте

Как это дело перехватить?
SuprSonic вне форума Ответить с цитированием
Старый 15.11.2017, 20:30   #2
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Хы, пркольно, а что пончик уже и перехватывать умеет? Последний раз перехватыл я сам, а пончиком ток дизассемблировал.

Ну так на вскидку, а ДЛЛ в процесс встроена? Нужно убедится что

1. Она загрузилась в процесс.
2. Она сделала перехват ДО вызова CreateInstanceEnum оригинальной прогой.

Насчет пункта (2) я не уверен, т.к., скорее всего, программа считывает видюху прежде вообще всего и вы просто не успеваете встроить перехват. В этом случае, вам нужно делать замену всей системной ДЛЛ, переименовать ее, написать свою, со старым именем, которая будет перенаправлять все вызовы в оригинал, кроме вот того 1. Т.к. это COM объект ... м.б. можно подпатчить реестр, т.е. сделать переименование в нем, а не файлов на диске.

Последний раз редактировалось alexzk; 15.11.2017 в 20:33.
alexzk вне форума Ответить с цитированием
Старый 15.11.2017, 22:40   #3
SuprSonic
Пользователь
 
Регистрация: 07.08.2016
Сообщений: 16
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Хы, пркольно, а что пончик уже и перехватывать умеет? Последний раз перехватыл я сам, а пончиком ток дизассемблировал.

Ну так на вскидку, а ДЛЛ в процесс встроена? Нужно убедится что

1. Она загрузилась в процесс.
2. Она сделала перехват ДО вызова CreateInstanceEnum оригинальной прогой.
Естественно я ее встраиваю в процесс с помощью withdll.exe, которая идет в комплекте с MS Detours 3.0.

Так она перехватывает остальные данные, но вот с этим случаем у меня траблы. Не хватает знаний и опыта, вроде делаю как пишут мелгомягкие в прилагаемых примерах, но что-то не работает.

Насчет замены всей DLL не вариант т.к. чревато нестабильностью в работе.
SuprSonic вне форума Ответить с цитированием
Старый 15.11.2017, 23:05   #4
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Так стоп...я уже подзабыл эти интерфейсы, но это же объект некого класса по идее? А в классах 1й параметр это не явный this.

Попробуйте так

Код:
typedef HRESULT(WINAPI IWbemServices::*tm_CreateInstanceEnum) (void*, const BSTR strClass, LONG lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum);
tm_CreateInstanceEnum True_CreateInstanceEnum = &IWbemServices::CreateInstanceEnum;


__declspec(dllexport) HRESULT WINAPI Hooked_CreateInstanceEnum(void*, const BSTR strClass, LONG lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum)
...хотя, если метод static, то его не будет ....вопщем просто попробуйте. Вдруг все же объект.

Если сработает - то его же и в оригинал передавать не забывайте.
Вообще, стоит взять IDA и ей посмотреть бинарную функция в длл, она на основе ассемблера даст прототип, и сравнить его с тем что вы делаете.

Вот еще идея проверить, по умолчанию компилер делает __cdecl, а все системные ф. винды __stdcall (хотя, кажется, это уже включено в макросе WINAPI).

Последний раз редактировалось alexzk; 15.11.2017 в 23:15.
alexzk вне форума Ответить с цитированием
Старый 15.11.2017, 23:37   #5
SuprSonic
Пользователь
 
Регистрация: 07.08.2016
Сообщений: 16
По умолчанию

Стоит добавить void* и на строке ниже VS мне подсвечивает & и пишет вот это.
error.jpg
SuprSonic вне форума Ответить с цитированием
Старый 16.11.2017, 03:47   #6
SuprSonic
Пользователь
 
Регистрация: 07.08.2016
Сообщений: 16
По умолчанию

Подсказали использовать хук на метод 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 и вижу такое:
#1
jwy8Ffr.png

#2
3N2qSQA.png

Вроде прикрепляется, но программа выплевывает ошибку и не запускается. Почему?
SuprSonic вне форума Ответить с цитированием
Старый 16.11.2017, 09:12   #7
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

По моему вы там чета с указателями перемудрили. По идее

Код:
p_Get = (True_GetFn)GetProcAddress
это уже указатель,а вы из него еще раз берете адрес позже. Т.о. у вас указатель на указатель. Перепроверьте все. И кстати, в прошлой версии м.б. такой же косяк был.

Код:
PVOID*
Собственно вот, вы хотите указатель на указатель. Но смысла в этом мало. Т.к. вы берете указатель на локальную переменную, которая перестает существовать после вызова.

Последний раз редактировалось alexzk; 16.11.2017 в 09:17.
alexzk вне форума Ответить с цитированием
Старый 16.11.2017, 12:21   #8
SuprSonic
Пользователь
 
Регистрация: 07.08.2016
Сообщений: 16
По умолчанию

Цитата:
True_GetFn p_Get = nullptr;
Я же задаю этот указатель заранее, но он не на что не указывает, он пустой.
А далее когда я уже подключаю DLL к EXE и запускаю все совместно, то в DllMain перехватывается указатель из библиотеки fastprox.dll на оригинальный метод Get.
Т.е. я его таким образом присваиваю:
Код:
p_Get = (True_GetFn)GetProcAddress(hLib, "?Get@CWbemObject@@UAGJPBGJPAUtagVARIANT@@PAJ2@Z");
Цитата:
Собственно вот, вы хотите указатель на указатель. Но смысла в этом мало. Т.к. вы берете указатель на локальную переменную, которая перестает существовать после вызова.
Функция SetDetour(PVOID* ppTarget... принимает PVOID*. Как мне ей правильно передать параметр тогда?
SuprSonic вне форума Ответить с цитированием
Старый 16.11.2017, 12:27   #9
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Ага, значит все правильно (не заметил, что глобалка), но не правильно...

(PVOID* ppTarget..

это будет РЕЗУЛЬТАТ, а не источник. А вы передаете источник.

Т.е.

Код:
PVOID res = nullptr;
SetDetour(&res, ...)
и вот так в res будет какойто указатель на чтото в результате. Читайте доку по ф. (и сюда скопируйте).

Кстати PVOID означает, что подойдет любой указатель. Скорее всего, туда нада ваш тип передавать, т.е.

Код:
True_GetFn res;

Последний раз редактировалось alexzk; 16.11.2017 в 12:29.
alexzk вне форума Ответить с цитированием
Старый 16.11.2017, 14:29   #10
SuprSonic
Пользователь
 
Регистрация: 07.08.2016
Сообщений: 16
По умолчанию

SetDetour - эту моя функция, но первый ее параметр передается в DetourAttachEx и к сожалению документации к ней найти не смог. Ориентируюсь я только по примерам, а в них в 98% случаев первый параметр передается так - &(PVOID&)parameter и очень редко (PVOID*)&parameter.

Т.е. DetourAttachEx и/или DetourAttach принимают только PVOID тип и поэтому приходится делать преобразование.

Однако в моем случае что бы я не написал - (PVOID*)&p_Get / &(PVOID&)p_Get / (PVOID*)p_Get - любая запись выбрасывает ошибку, только в последнем случае выбрасывает еще и ошибку 0xc0000005 при запуске dxdiag.exe

------------------------------------------

Хм. Сменил LoadLibraryA("fastprox.dll") на GetModuleHandle(L"fastprox.dll") прога стала запускаться, но значения не меняются.
Как так то?!?!

Последний раз редактировалось SuprSonic; 16.11.2017 в 15:04.
SuprSonic вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Подмена url с помощью .htaccess Gorychev Общие вопросы Web 1 19.02.2014 01:39
в чем отличие gpu core clock и gpu clock почему значания разные? gpu0 Компьютерное железо 0 10.06.2012 05:17
DETOURS, Перехват API средствами Detours Micki1 Visual C++ 1 05.04.2012 04:45
подмена данных в программе linkod Фриланс 9 12.03.2009 11:12
Подмена данных Smip Microsoft Office Excel 2 13.01.2009 08:51