Как в чужой запущенной программе получить указатель на IDirect3DDevice

Тема в разделе "WASM.DirectX", создана пользователем Холод, 22 ноя 2007.

  1. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    то есть я внедрил длл в уже запущенную программу использующую Direct3D
    но поскольку создание интерфейса устройства происходит в начале подопытной программы... то мы не можем ставить хук на него потому как это произошло уже.

    вопрос вот в чём: можно ли получить указатель на IDirect3DDevice в уже запущенной программе?
     
  2. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    А зачем тебе указатель на IDirect3DDevice? Достаточно перехватить его методы. И там уже делать все, что нужно. Тот же указатель можно получить сразу - он передается при вызове метода.

    Смотри сюда: http://www.wasm.ru/forum/viewtopic.php?id=10740
     
  3. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    я просто не допонимаю как перехватить метод не зная указатель на интерфейс IDirect3DDevice.

    Игра к примеру уже запущена и в неё играют... функции Direct3DCreate9 и CreateDevice уже отработали, и тут встаёт вопрос как перехватить метод не зная указатель на интерфейс IDirect3DDevice. Надо ведь от чего то отталкиваться... объясните
     
  4. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Холод
    Интерфейс это vtbl. Когда ты получаешь указатель на него, то это указатель на vtbl, то есть таблицу методов этого интерфейса. Всё что тебе надо это изменить атрибут памяти vtbl (VirtualProtect) на write и поменять адреса в vtbl, на адреса своих функций, и все вызовы теперь будут перенаправляться тебе.

    З.Ы Да первый указатель в vtbl, это указатель this кома, то бишь его данные.
     
  5. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    а оригинальную vtbl искать в памяти чтоли надо, создав клон интерфейса и сравнивая их. или что? мне бы пример какой или что-то похожее на пример... буду признателен за помощ
     
  6. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    вкратце....

    - вот запущенная игра, ребёнок играет 3 часа в неё.
    - по нажатии на горячую клавишу происходит внедрение длл в запущенную игру(это сделано).
    - теперь надо получить контекст запущенной игры(это надо сделать).

    собственно если запускать игру с лоадера проблем нет, просто перехватываются функции создания контекста и дальше по плану...
     
  7. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Холод
    vtbl искать не надо, получаешь интерфейс IDirect3DDevice, и патчишь его vtbl. vtbl всегда одна, так как это код. Только данные у всех разные. Патчишь vtbl, и перехват будет у всех экземпляров интерфейса данного процесса.
     
  8. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    что значит патчиш?
     
  9. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Холод
    vtbl это таблица адресов на методы. Меняешь эти адреса на адреса своих функций.
    А vtbl получаешь через указатель на интерфейс. Этот указатель и есть указатель на vtbl.
    Я этим делом занимался когда писал редиректор с джойстика на клаву и мышь, типо когда в игре нету джойстика, а нужно.
     
  10. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    угу посмотрю... позже напишу результат
     
  11. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    Вот меня интересует момнтент "...получаешь интерфейс IDirect3DDevice..." как его получать?

    В DLL делаю так:
    Код (Text):
    1. var direct3d_DEVICE: IDIRECT3DDEVICE9;
    2.  
    3. D3D := Direct3DCreate9(D3D_SDK_VERSION);
    4. D3D.QueryInterface(IID_DIRECT3DDEVICE9, direct3d_DEVICE)
    direct3d_DEVICE - не возвращается...

    тоесть вы хотите сказать, что нужно создавать direct3d_DEVICE вручную незапраштвая его?
    делаю так(код внедряемой DLL в запущенное тестовое приложение. l_D3DPresentParameters у DLL и тестового приложения одинаковые):
    Код (Text):
    1. library game;
    2.  
    3. uses SysUtils, Classes, Windows, Direct3D9, D3DX9, advApiHook;
    4.  
    5. var
    6.   D3DObj: IDirect3D9;
    7.   direct3d_DEVICE: IDirect3DDevice9;
    8.   l_D3DPresentParameters: TD3DPresentParameters;
    9.   g_Font: ID3DXFont;
    10.  
    11. var EndScene9Next: function(self: pointer): HResult stdcall = nil;
    12.  
    13. function GetInterfaceMethod(const intf; methodIndex: DWORD): POINTER;
    14. begin
    15.   RESULT := POINTER(POINTER(DWORD(POINTER(intf)^) + methodIndex * 4)^);
    16. end;
    17.  
    18. function EndScene9Callback(self: pointer): HResult; stdcall;
    19. var TextRect: TRect;
    20. begin
    21.   TextRect := RECT(0, 0, 100, 100);
    22.   g_Font.DrawTextA(nil, PChar('test... ok installation...'), -1, @TextRect, DT_LEFT or DT_NOCLIP, D3DCOLOR_RGBA($FF, $FF, $FF, $FF));
    23.  
    24.   Result := EndScene9Next(self);
    25. end;
    26.  
    27. begin
    28.   D3DObj := Direct3DCreate9(D3D_SDK_VERSION);
    29.   FillChar(l_D3DPresentParameters, SizeOf(l_D3DPresentParameters), 0);
    30.   l_D3DPresentParameters.Windowed := true;
    31.   l_D3DPresentParameters.PresentationInterval := D3DPRESENT_INTERVAL_IMMEDIATE;
    32.   l_D3DPresentParameters.MultiSampleType := D3DMULTISAMPLE_NONE;
    33.   l_D3DPresentParameters.EnableAutoDepthStencil := true;
    34.   l_D3DPresentParameters.BackBufferCount := 1;
    35.   l_D3DPresentParameters.AutoDepthStencilFormat := D3DFMT_D16;
    36.   l_D3DPresentParameters.SwapEffect := D3DSWAPEFFECT_DISCARD;
    37.   l_D3DPresentParameters.Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    38.   l_D3DPresentParameters.BackBufferWidth := 800;
    39.   l_D3DPresentParameters.BackBufferHeight := 600;
    40.   l_D3DPresentParameters.BackBufferFormat := D3DFMT_UNKNOWN;
    41.   D3DObj.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetForegroundWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, @l_D3DPresentParameters, direct3d_DEVICE);
    42.   if direct3d_DEVICE <> nil then SetWindowText(getforegroundwindow, 'ok') else SetWindowText(getforegroundwindow, 'off');
    43.  
    44.   D3DXCreateFont(direct3d_DEVICE, 30, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH or FF_DONTCARE, PChar('Lucida console'), g_Font);
    45.  
    46.   HookCode(GetInterfaceMethod(direct3d_DEVICE, 42), @EndScene9Callback, @EndScene9Next);
    47. end.
    результат нулевой...

    что посоветуете?

    P.S. Уважаемый Booster был бы рад увидеть ваш код редиректора, в виде выложенного архива.
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Холод
    Понял в чём трабла. Я конечно делал перехват в самом начале, хукая Direct3DCreate9 и его метод CreateDevice. И уже когда программа их вызывала, хукал другие их методы.
    Скорее всего нету в нём этого интерфейса. А метод Direct3DCreate9.CreateDevice это фабрика интерфейса. Тут можно посоветовать всё же делать перехват в самом начале, например с помощью инфектора. Или попробовать получить ещё одно устройство, и патчить его методы. Методы ведь одни и теже для всех интерфейсов (vtbl всегда одна), а значит патчинг распространяется на все интерфейсы. Но не знаю, никогда не создавал несколько устройств в одном приложении.
     
  13. anticyclope

    anticyclope New Member

    Публикаций:
    0
    Регистрация:
    11 дек 2007
    Сообщения:
    2
    кстати, хотелось бы узнать ответ на вопрос
    тот же самый fraps в состоянии впечатывать свои циферки в D3D приложение, даже если будет запущен после запуска приложения...
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    anticyclope
    По идее проблемы быть не должно.
    Вызываешь Direct3DCreate9.CreateDevice, получаешь интерфейс. И патчишь его. При вызове метода, первый параметр будет this того объекта для которого это вызывалось. Вообщем как со всеми другими комами. Единственно я не пробовал дважды вызывать CreateDevice в одном приложении, и незнаю можно ли дважды получить этот интерфейс. Раз fraps это умеет, значит возможно.
     
  15. anticyclope

    anticyclope New Member

    Публикаций:
    0
    Регистрация:
    11 дек 2007
    Сообщения:
    2
    Кажется нашел, но не до конца понял
    http://forum.gamedeception.net/archive/index.php/t-10421.html

    upd: понял и реализовал. работает, будучи внедренным после создания D3D-устройства.
     
  16. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    Booster, а ты матрицы не фанат? ;)
     
  17. Холод

    Холод New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2006
    Сообщения:
    42
    anticyclope, выложи архив с тестовой прогой