На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Подмена данных о GPU с помощью MS Detours 3.0 , Не получается перехватить и подменить IEnumWbemClassObject::CreateInstanceEnum
    Всем привет,
    Пытаюсь подменить информацию о видеокарте, но столкнулся с проблемой. Так данные о видеокарте (GPU) в большинстве случаев тянутся посредством Win32_VideoController, то выглядит это все как-то так:
    ExpandedWrap disabled
      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 следующим образом:

    Попытка получить указатель:
    ExpandedWrap disabled
      typedef HRESULT(WINAPI IWbemServices::*tm_CreateInstanceEnum) (const BSTR strClass, LONG lFlags, IWbemContext *pCtx, IEnumWbemClassObject **ppEnum);
      tm_CreateInstanceEnum True_CreateInstanceEnum = &IWbemServices::CreateInstanceEnum;


    Моя функция:
    ExpandedWrap disabled
      __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;
      }


    Впихон:
    ExpandedWrap disabled
      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. Но, увы сия чуда не происходит :oops:

    Как правильно перехватить?
      Подсказали мне значит вешать хук на метод Get. Получился такой код:
      ExpandedWrap disabled
        #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, то получаю ошибку:

      Первое окошко:
      Прикреплённая картинка
      Прикреплённая картинка


      Второе - ошибка:
      Прикреплённая картинка
      Прикреплённая картинка


      Кто знает в чем проблема? :-?
        Такое ощущение, что тут нет знатоков :blink:
        В общем имею такой код:

        Хедер и определение указателя:
        ExpandedWrap disabled
          #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;


        Моя функция:
        ExpandedWrap disabled
          __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:
        ExpandedWrap disabled
          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:
        ExpandedWrap disabled
          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 выдает ошибку.

        Прикреплённая картинка
        Прикреплённая картинка

        Прикреплённая картинка
        Прикреплённая картинка

        Прикреплённая картинка
        Прикреплённая картинка


        Выдвиньте хотя бы какую-то свою версию почему так происходит.
        Сообщение отредактировано: Mr.Newbie‎ -
          Ну вы хоть опосля SetDetour проверьте: всё ли там норм произошло; а то вдруг NULL вертухается, а вы забиваете на сие, а?.. :blush:
            Цитата Славян @
            Ну вы хоть опосля SetDetour проверьте: всё ли там норм произошло; а то вдруг NULL вертухается, а вы забиваете на сие, а?..

            Так вроде проверял, все четко. Ткните плз я не вижу этот изъян
            Сообщение отредактировано: Mr.Newbie‎ -
              Да мож и нет никакого изъяна. Просто в вашей SetDetour происходят же вызовы с проверками, так что вдруг какой и завершается ошибкой, но в DllMain на это код забивает.
                Цитата Mr.Newbie‎ @
                Выдвиньте хотя бы какую-то свою версию почему так происходит.

                Вот версия:
                Как я понял, ты пытаешься перехватить функцию класса.
                У таких функций есть дополнительный параметр - this.
                Он автоматически добавляется компилятором.
                Фактически, протопип функции не такой, как ты используешь.
                -----
                Совершенно очевидно, что надо делать.
                Надо пытаться трассировать твои опусы отладчиком уровня ядра.
                Сообщение отредактировано: ЫукпШ -
                  Цитата ЫукпШ @

                  У таких функций есть дополнительный параметр - 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:
                  ExpandedWrap disabled
                    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
                    }



                  И тут нет никакого доп.параметра.
                    Цитата Mr.Newbie‎ @
                    Почему не такой ? И откуда доп.параметр this ?

                    Каждая функция используется для всех экземпляров класса.
                    Поэтому, чтобы отличить один экземпляр класса от другого, не статической функции
                    передаётся указатель на структуру данных класса.
                    Лекция
                    Сообщение отредактировано: ЫукпШ -
                      Цитата Mr.Newbie‎ @
                      И тут нет никакого доп.параметра

                      "Ты суслика видишь? И я не вижу. А он есть" (С)
                      В любую не статическую функцию класса первым неявным аргументом передается параметр this - указатель на экземпляр\объект класса, для которого вызывается функция. Т.е. для объекта С *с запись c->f(i) это лишь синтаксическая условность ("сахар"), за которой в действительности скрывается вызов функции C::f(c,i)
                        Так, окей. Убедили что суслик есть.
                        Добавил первым параметром, но ведь...

                        ExpandedWrap disabled
                          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)
                          {
                          ....


                        всеравно не работает :-?

                        user posted image
                        Сообщение отредактировано: Mr.Newbie‎ -
                          Цитата Mr.Newbie‎ @
                          Так, окей. Убедили что суслик есть.
                          Добавил первым параметром, но ведь...

                          Доказательство как бы намекает, что суслик может быть не один.
                          Выход один - надо отлаживаться.
                          ---
                          Есть ли уверенность, что "Calling Conventions" твоих процедур и вызываемой - совпадают ?
                            Calling Conventions - совпадают. У меня такое предчувствие, что я как-то неправильно использую DetourAttachEx/DetourAttach. Перерыл буржнет и нашел посты, правда датированные лохматыми годами и используется там версия detour 1.5, так вот там почти все как у меня только вместо DetourAttachEx/DetourAttach - прописана функция DetourFunction и результат его работы присваивается (в данном случаем у меня) к p_Get :blink:
                              Цитата Mr.Newbie‎ @
                              Calling Conventions - совпадают.
                              Это не имеет значения. this может передаваться в регистре.
                                Пришел к такому решению, оно наполовину рабочее... в общем вот код:
                                ExpandedWrap disabled
                                  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 изменениями и не пахнет.
                                ExpandedWrap disabled
                                          pVal->vt = VT_BSTR;
                                          V_BSTR(pVal) = L"NO_DATA";


                                :crazy:
                                Сообщение отредактировано: Mr.Newbie‎ -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0875 ]   [ 23 queries used ]   [ Generated: 18.04.24, 19:08 GMT ]