Autor Beitrag
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Do 26.08.10 15:49 
Ich will einen Pointer auf eine Klassen-Methode erhalten um DirectX-Funktionen zu hooken.
Bei directX kriege ich ja beim init nur ein Interface mit MethodenZeigern gefüllt. Darum das ganze dynamisch.

Mein Ansatz:
ausblenden Delphi-Quelltext
1:
  HookCode(@(Keyboard.FDeviceObj.GetDeviceState),@HookedGDS,@realGDS);					

Mit: Keyboard.FDeviceObj:IDirectInputDevice8;

Der Meckert mir aber über "Nicht genügend wirkliche Parameter", als wollte er die Funktion ausführen.

Wie schaffe ich das, zum Laufen zu bringen?
Teekeks
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 211
Erhaltene Danke: 23



BeitragVerfasst: Do 26.08.10 16:10 
Hallo!
Versuche es mal so:
ausblenden Delphi-Quelltext
1:
HookCode(@Keyboard.FDeviceObj.GetDeviceState,@HookedGDS,@realGDS);					
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 26.08.10 16:16 
Also ein "Methodenpointer" gibt's so eigentlich nicht. Ein Methodenaufruf benötigt zwei Pointers (siehe TMethod), der Pointer auf den Code und der Pointer auf die Daten (d.h. auf Self).

Mit einem kleinen Trick kannst du jedoch einen "Methodenpointer" erhalten, wenn du nämlich ein Interface hast. Die Methodentabelle von Interfaces beinhalten nämlich nur Funktionspointer. Dort drin wird dann das Self noch dazugerechnet und dann die Methode aufgerufen. Blöderweise musst du aber das Interface selbst als Parameter übergeben, was ActiveX wohl kaum machen wird.

Weitere Möglichkeit ist, wenn du sowas wie MakeObjectInstance machst. Der generiert aus einer Methode einen Pointer (die Methode hat aber nicht die Signatur, die du benötigst).

Ansonsten globale Funktion, die die Methode aufruft.


Zuletzt bearbeitet von delfiphan am Do 26.08.10 17:09, insgesamt 1-mal bearbeitet
Flamefire Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 31

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Do 26.08.10 17:09 
nja sagen wir so: in assembler sieht das ganze so aus:
ausblenden Quelltext
1:
2:
3:
push eax //parameter self
mov eax,[eax] //laden der methodenpointertabelle
call [eax+1C] //aufruf der methode


Was meinst du mit der Signatur?

Die Variante von Teekeks hatte ich ja, aber ging nicht.

Meine Frage ist jetzt: Wie kriege ich den Pointer aus der Tabelle von dem Interface?
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 26.08.10 17:19 
Das Problem ist, dass dir DirectX den Interface-Pointer (<>Self!) nicht als Parameter mitgibt (Methodensignatur = Methodendeklaration; d.h. die Tatsache, dass du den Interface-Pointer übergeben musst).

Also entweder machst du eine globale Prozedur, die deine Methode aufruft oder du machst sowas wie MakeObjectInstance.

Also mit sowas wie hier kannst du ein procedure of object in ein procedure umwandeln. In dem Code unten ist die Variable Code auf dem Stack. Das müsste man ändern, sodass man zuerst Speicher mittels VirtualAlloc mit dem Flag PAGE_EXECUTE_READWRITE holt und damit arbeitet.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
type
  TObjProc = procedure of object;
  TProc = procedure;

type
  TCode = packed record
    MovEAX: Byte;
    Data: Pointer;
    MovEBX: Byte;
    Code: Pointer;
    CallEbx: Word;
    Ret: byte;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ObjProc: TObjProc;
  Proc: TProc;

  Code: TCode;
begin
  ObjProc := Test; // Note: ObjProc are two pointers

  Code.MovEAX := $B8;
  Code.MovEBX := $BB;
  Code.CallEbx := $D3FF;
  Code.Ret := $C3;
  Code.Data := TMethod(ObjProc).Data;
  Code.Code := TMethod(ObjProc).Code;

  @Proc := @Code;

  Proc; // Note: Proc is a single pointer
end;

procedure TForm1.Test;
begin
  ShowMessage('Success!');
end;