|
You last visited: Today at 20:48
Advertisement
Problem mit IDirect3DDevice9 VTable Hooking
Discussion on Problem mit IDirect3DDevice9 VTable Hooking within the C/C++ forum part of the Coders Den category.
03/23/2014, 17:57
|
#1
|
elite*gold: 724
Join Date: Mar 2011
Posts: 10,479
Received Thanks: 3,318
|
Problem mit IDirect3DDevice9 VTable Hooking
Hallo,
ich habe hier ein Problem mit der VTable, bei dem ich mir nicht ganz sicher bin, ob ich nicht einfach etwas übersehe.
Ich erstelle mit IDirect3D9::CreateDevice() ein IDirect3DDevice9 und initialisiere damit meinen Pointer auf die VTable:
Code:
m_device = CreateDevice();
m_vtable = *reinterpret_cast<SD3DDeviceVTable **>(m_device);
SD3DDeviceVTable ist ein einfaches Struct, in dem die ganzen Memberfunktionen sind:
Code:
struct SD3DDeviceVTable
{
CD3DDeviceFunction& operator[](DWORD index)
{
return reinterpret_cast<CD3DDeviceFunction *>(this)[index];
}
#pragma pack(push, 1)
union
{
CD3DDeviceFunction *QueryInterface_Raw; // 0
HRESULT(__stdcall *QueryInterface)(LPDIRECT3DDEVICE9, REFIID, void**);
};
//usw...
};
Wenn ich jetzt mit DetourFunction eine Funktion hooke, funktioniert alles ohne Probleme:
Code:
nd::CD3DDevice d3d;
auto &present = d3d[PRESENT_INDEX];
present_orig = reinterpret_cast<Present_t>(DetourFunction(present, reinterpret_cast<PBYTE>(&present_hk)));
Wenn ich jetzt allerdings die Adresse direkt in der VTable verändern möchte, klappt das zwar auch, allerdings ruft das Zielprogramm meinen Hook nie auf. Wenn ich mit dem Debugger den Aufruf einer Funktion abfange & die VTable des Device Pointers anschaue, hat die eine ganz andere Adresse als die meines Device Pointers - somit schreibe ich zwar in gültigen Speicher, allerdings halt in welchen, der von keinem anderen Device verwendet wird.
Die VTable im Konstruktor von CD3DBase wird zwar gesetzt, allerdings später scheinbar nochmals ersetzt, somit hat es keinen Nutzen, einfach die VTable, die das Pattern zurückgibt, zu verwenden (bereits getestet).
Hat jemand eine Idee, weshalb es für das Interface mehrere VTables gibt, obwohl die Aufrufe von CreateDevice fast identisch sind?
Das Zielprogramm ist übrigens momentan ein von mir selbst geschriebenes, soll später natürlich aber auch bei anderen Programmen funktionieren.
|
|
|
03/23/2014, 19:00
|
#2
|
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
|
Quote:
Originally Posted by snow911
Die VTable im Konstruktor von CD3DBase wird zwar gesetzt, allerdings später scheinbar nochmals ersetzt, somit hat es keinen Nutzen, einfach die VTable, die das Pattern zurückgibt, zu verwenden (bereits getestet).
|
Speziell zu deinem Problem kann ich leider nichts sagen, aber normalerweise wird Vererbung mit virtuellen Funktionen von C++ - Compilern so realisiert:
1. In der Basisklasse wird der Zeiger auf die Tabelle virtueller Funktionen der Basisklasse gesetzt. Ich könnte ja im Konstruktor der Basisklasse eine solche virtuelle Funktion aufrufen.
2. In der abgeleiteten Klasse wird dieser Zeiger überschrieben. Es soll schließlich später die richtige virtuelle Funktion aufgerufen werden.
Der Destruktor arbeitet ähnlich, nur umgekehrt.
Ist CD3DBase eine Basisklasse?
|
|
|
03/23/2014, 19:24
|
#3
|
elite*gold: 724
Join Date: Mar 2011
Posts: 10,479
Received Thanks: 3,318
|
Quote:
Originally Posted by Tasiro
Speziell zu deinem Problem kann ich leider nichts sagen, aber normalerweise wird Vererbung mit virtuellen Funktionen von C++ - Compilern so realisiert:
1. In der Basisklasse wird der Zeiger auf die Tabelle virtueller Funktionen der Basisklasse gesetzt. Ich könnte ja im Konstruktor der Basisklasse eine solche virtuelle Funktion aufrufen.
2. In der abgeleiteten Klasse wird dieser Zeiger überschrieben. Es soll schließlich später die richtige virtuelle Funktion aufgerufen werden.
Der Destruktor arbeitet ähnlich, nur umgekehrt.
Ist CD3DBase eine Basisklasse?
|
Dass der Zeiger auf die Tabelle überschrieben wird, ist mir bewusst (und auch sinnvoll), mich wundert nur, dass das jetzt auf einmal der Fall ist, vor allem weil der "neue" Zeiger immer dynamisch allokiert wird & dann mit dem Inhalt der bestehenden Tabelle gefüllt wird:
Code:
67463FF8 . 8B0B MOV ECX,DWORD PTR DS:[EBX]
67463FFA . 898B 982D0000 MOV DWORD PTR DS:[EBX+0x2D98],ECX
67464000 . 8BB3 982D0000 MOV ESI,DWORD PTR DS:[EBX+0x2D98]
67464006 . 8DBB 9C2D0000 LEA EDI,DWORD PTR DS:[EBX+0x2D9C]
6746400C . 893B MOV DWORD PTR DS:[EBX],EDI
6746400E . B9 AF000000 MOV ECX,0xAF
67464013 . F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
Das kann ja soweit durchaus Sinn machen, wenn die beiden Zeiger verschiedene Klassen hinter der Schnittstelle haben, aber dann frage ich mich, warum das so ist? Selbst wenn ich den Code zur Erzeugung eines Fensters für beide Devices verwende, erhalte ich verschiedene Adressen..
EDIT:
Okay, habe noch ein paar Dinge herausgefunden:
- die VTable wird in IDirect3DDevice9::BeginStateBlock zurückgesetzt, das liegt daran, dass ich innerhalb meines Hooks GetFVF / SetFVF verwende
- beide Devices (sowohl vom Zielprogramm als auch von der DLL) werden mit dem VTable-Zeiger in der Funktion CD3DHal::CD3DHal gesetzt
- die Zeiger werden in der Funktion CD3DBase::InitDevice überschrieben
Ich verstehe ehrlich gesagt immer noch nicht, warum das nicht funktioniert..
|
|
|
03/25/2014, 17:19
|
#4
|
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
|
BeginStateBlock funktioniert so als Hook, schiebt sich zwischen alle Set* Methoden um einen StateBlock zu generieren mit den Werten die du setzen willst und lässt den Aufruf "nichts" tun. In EndStateBlock sollten die Hooks wieder entfernt werden.
DirectX einfach nicht über die VTable hooken und gut.
|
|
|
 |
Similar Threads
|
[Tutorial] Hooking, Detours, VTable etc.
08/21/2018 - Coding Tutorials - 5 Replies
Da man öfters hier im Forum die Frage aufkommen sieht "Wie male ich etwas auf ein Spiel" und "Wie sende ich Tastendrücke an mein spiel?!?111"
Präsentiere ich hiermit stolz pünktlich zu Neujahr mein Tutorial rund ums Hooking, Detours, Searchpattern, VTables etc.
27 Seiten geballte Informationen mit 2 Beispielen für einen DirectInput und einen D3DHook.
Download: HookingTutorial.rar | xup.in
GL & HF
|
VTable hooking Problem
07/03/2012 - C/C++ - 9 Replies
Hey, ich habe jetzt mal mit der Funktion von Heavyhacker versucht eine Funktion zu hooken.
PBYTE HookVTable(DWORD** VTablePtr, int VTableIndex, PBYTE HookPtr)
{
DWORD oldProtect;
VirtualProtect((void*)((*VTablePtr)+(VTableIndex *sizeof(DWORD))),sizeof(DWORD),PAGE_EXECUTE_READWR ITE,&oldProtect);
PBYTE original=((BYTE*)(*VTablePtr));
(*VTablePtr)=(DWORD)HookPtr;
VirtualProtect((void*)((*VTablePtr)+(VTableIndex *sizeof(DWORD))),sizeof(DWORD),oldProtect,&old Protect);
return original;
}
|
[C++] Hooking IDirect3DDevice9::Present
09/05/2009 - C/C++ - 0 Replies
Hi
I am trying to hook this function.
HRESULT (WINAPI IDirect3DDevice9::*pOrigPresent)(CONST RECT * pSourceRect,CONST RECT * pDestRect,HWND hDestWindowOverride,CONST RGNDATA * pDirtyRegion) = &IDirect3DDevice9::Present;
HRESULT WINAPI m_Present(CONST RECT * pSourceRect,CONST RECT * pDestRect,HWND hDestWindowOverride,CONST RGNDATA * pDirtyRegion)
{
printf("Hooked\n");
return pOrigPresent(pSourceRect,pDestRect,hDestWindowOver ride,pDirtyRegion);
}
|
All times are GMT +1. The time now is 20:50.
|
|