XP SP3 32bit трабла с перехватом.

Тема в разделе "WASM.WIN32", создана пользователем Booster, 19 окт 2008.

  1. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Всем привет.
    Есть dll, в которой хукаются интерфейсы DirectX, и она у многих работает нормально.
    Не уверен на сто процентов, но видимо проблемы у тех у кого XP SP3. У них вызов функций видимо зацикливается, то есть в месте где должна вызываться оригинальная функция, вызывается хуканная. Может кто подскажет по этой проблеме?
     
  2. 2FED

    2FED New Member

    Публикаций:
    0
    Регистрация:
    20 фев 2008
    Сообщения:
    1.002
    Сплайсинг?
     
  3. Twister

    Twister New Member

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    720
    Адрес:
    Алматы
    Booster
    Код библиотеки можно лицезреть? Или всем форумом будем гадать на кофейной гуще?
     
  4. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    Twister
    Это когда программеры гадали на кофейной гуще ? программер всегда юзал бубен!
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Показываю то что заслуживает показа, так как в других частях вода, не имеющая отношения к сабжу. Так С++.

    Это функция ставит хук на CreateDevice.
    Код (Text):
    1. void HookeCreateDevice(IDirect3D9 *pD3D9)
    2. {
    3.     DWORD oldProtect;
    4.     DWORD vtbl;
    5.     _asm
    6.     {
    7.         mov eax, pD3D9
    8.         mov eax, [eax]
    9.         mov vtbl, eax
    10.         lea edx, CreateDeviceOrg  //Записываем оригинальный адрес метода
    11.         mov ecx, [eax + 64]
    12.         mov [edx], ecx
    13.     }
    14.    
    15.     VirtualProtect((LPVOID)vtbl, 72, PAGE_READWRITE, &oldProtect);
    16.  
    17.     _asm
    18.     {
    19.         lea edx, CreateDeviceNew //Новый адрес
    20.         mov eax, vtbl
    21.         mov [eax + 64], edx
    22.     }
    23.  
    24.     VirtualProtect((LPVOID)vtbl, 72, oldProtect, &oldProtect);
    25. }
    Это экспортируемая функция Direct3DCreate9, делает предварительную инициализацию и вызывает HookeCreateDevice. Сделана проверка от повторного вызова и хука.

    Код (Text):
    1. IDirect3D9 *WINAPI Direct3DCreate9(UINT SDKVersion)
    2. {
    3.     if (!Direct3DCreate9Org)
    4.         Direct3DCreate9Org = GetDirect3DCreate9();
    5.     static bool bHook = false;
    6.     if (Direct3DCreate9Org)
    7.     {
    8.         IDirect3D9* pD3D9 = Direct3DCreate9Org(SDKVersion);
    9.         if (!bHook)
    10.         {
    11.             HookCreateDevice(pD3D9);
    12.             bHook = true;
    13.         }
    14.         return pD3D9;
    15.     }
    16.     return NULL;
    17. }
    А это собственно сама CreateDevice, привожу участок заслуживающий хоть какого-то внимания.
    Код (Text):
    1. HRESULT WINAPI CreateDeviceNew(IDirect3D9* pD3D9, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface)
    2. {
    3.     IDirect3DDevice9* pDevice;
    4.     HRESULT hr = CreateDeviceOrg(pD3D9, Adapter, DeviceType, hFocusWindow
    5.                             BehaviorFlags, pPresentationParameters, &pDevice);
    6.         //Тут ещё кое-что есть,  но это не интересно.
    7. }
    У меня и у тех, у кого sp2 работает как и надо. Вызывается два раза (так делается в той проге для которой это писано) Direct3DCreate9, в первый раз вызывается HookeCreateDevice, потом нет. Затем из проги приходит один вызов CreateDeviceNew и в нём благополучно вызывается оригинальный метод - CreateDeviceOrg.

    Так вот нашлось два человека с sp3 (может совпадение, а может и нет), у которых это работает более чем загадочно. По логу видно, что адреса CreateDeviceOrg и CreateDeviceNew перед вызовом CreateDeviceOrg отличны и корректны (они такими были когда хукались). Но и так же видно, что после вызова CreateDeviceOrg на самом деле управление снова приходит в CreateDeviceNew, и второй раз в ней вызывается CreateDeviceOrg, и управление передаётся оригинальной, директовой функции. После того как она отработала, соответственно два раза выходим из CreateDeviceNew. Это показывают логи, и не верить им не приходится. Не понятно. Дальше ещё веселее, есть другие версии той проги для которой это писалось, так вот по логу, управление в Direct3DCreate9 не передаётся вообще, а только в саму DllMain. Хотя как уже писал, и у меня и многих всё работает как надо.

    Если с первой траблой ещё можно справится, контролируя повторный вход в CreateDeviceNew(хотя такое поведение более чем загадочно). То что делать когда не вызывается Direct3DCreate9, вообще не понятно. Многопоточность по логам не юзается.
    Может на sp3 какая хитрож.... защита есть? Советуйте, если что спрошу у тех у кого это проявляется, и проверю что необходимо.
     
  6. keYMax

    keYMax New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2003
    Сообщения:
    276
    Адрес:
    Новоуральск
    Правка vtbl глупо, сплайсить нужно прямо direct3d*.dll
    У DX есть такой трабл как обнуление всего vtbl до оригинального прямо во время работы программы (влияют вызовы каких то пары-тройки методов, не помню уже каких)
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    keYMax
    Может и так, но тут обратная картина, вызов оригинального метода, не через vtbl, приводит к вызову похученой функции. То есть как бы vtbl сама сплайсит. -) Да и не хочется сплайсить, траблы с многопоточностью, хотя в данном случае этого и нет.
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Посетила бредовая мысль, что CreateDevice может вызывать себя же, но только с другими параметрами. То есть я вызываю оригинальную функцию, а она вызывает себя же через vtbl со спец параметрами, и следовательно опять получает управление мой хук. Бред конечно, но другое на ум не приходит. Сегодня сделаю логирование параметров CreateDevice, и отправлю для теста людям.
     
  9. keYMax

    keYMax New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2003
    Сообщения:
    276
    Адрес:
    Новоуральск
    Booster

    Может проще на sp3 в отладчике посмотреть?
     
  10. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    keYMax
    Возможно да, проще. Но ставить его только ради этого, как-то в лом.
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Похоже мои предположения оправдались, происходит повторный вызов CreateDevice из самой себя. Вставил проверку на повторный хук vtbl и всё благополучно разрулилось. Странно в этой заплатке директ работает.

    keYMax
    Я так и не понял, откуда может взяться восстановление vtbl? Звучит странно, кто его будет восстанавливать?
     
  12. keYMax

    keYMax New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2003
    Сообщения:
    276
    Адрес:
    Новоуральск
    Когда я писал аналог Fraps я его мучал в ольке, решил сделать не как он, а правкой vtbl. Так вот, периодически мои функции назначеные в vtbl просто переставали вызваться. Просмотр в отладчике показал что память по которой лежит вся vtbl, например, на Direct3DDevice после вызова некоторых методов просто обновляется до первоначального значения. Методом опытного тыка я попытался как-то обойти это дело, но в конечном итоге получил только гемор. поэтому проще сплайсить прямо в dll первые 5 байт нужного метода и все. Такие вот дела.