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.
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?
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:
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..
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.
[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);
}