Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Adresse einer privaten Methode bekommen (https://www.delphipraxis.net/153041-adresse-einer-privaten-methode-bekommen.html)

Win32.API 18. Jul 2010 21:51

Delphi-Version: 2010

Adresse einer privaten Methode bekommen
 
Hallo,

ist es möglich die Adresse einer privaten Methode zur Laufzeit zu bestimmen? Eine "Hack"/"Dummy"-Klasse kommt in diesem Fall nicht in Frage, da der Code für mehrere Versionen der Klasse arbeiten soll.

Ich habe gedacht, dass das bestimmt mit der RTTI geht, aber
Delphi-Quellcode:
TRttiType.GetMethod()
gibt leider für private Methoden immer nil zurück.

Es muss aber einen Weg geben, da Delphi in der CPU-Ansicht den Namen anzeigen kann. Es ist auch möglich per Name zu dieser Funktion zu springen.

Grüße,
Win32.API

Luckie 18. Jul 2010 21:54

AW: Adresse einer privaten Methode bekommen
 
Wozu brauchst du die Adresse einer privaten Methode?

Namenloser 18. Jul 2010 21:56

AW: Adresse einer privaten Methode bekommen
 
Funktioniert
Delphi-Quellcode:
TMyClass.MethodAddress('MyMethod')
?

mkinzler 18. Jul 2010 21:57

AW: Adresse einer privaten Methode bekommen
 
Das würde ja dem Prinzip des information hiding ( black box) widersprechen

rollstuhlfahrer 18. Jul 2010 21:57

AW: Adresse einer privaten Methode bekommen
 
Das Ganze scheitert schon am Konzept. Du kannst nicht die Adresse einer privaten Prozedur auslesen. Eine private Prozedur ist vom Konzept her (ähnlich wie protected) nur INNERHALB eines Objektes verwendbar. Du kannst sie also auch nicht von außen aufrufen, weil es so aussieht, als würde sie gar nicht existieren. Somit kann sie von RTTI nicht gefunden werden.

Bernhard

Namenloser 18. Jul 2010 22:01

AW: Adresse einer privaten Methode bekommen
 
Delphi-Quellcode:
MethodAddress
liest aber direkt die VMT aus.

Win32.API 18. Jul 2010 22:06

AW: Adresse einer privaten Methode bekommen
 
Vielen Dank für die raschen Antworten :thumb:!

Ich brauche die Adresse um einen Bug in der Komponente zu beseitigen. Mir ist auch klar, dass es gegen das Konzept von OOP geht. Aber leider lässt es sich in diesem Fall nicht verhinden.

Delphi-Quellcode:
TMyClass.MethodAddress('MyMethod')
gibt leider auch nil zurück.

Alle Methoden, egal ob privat oder public, sind nur innerhalb einer Object-Instanz verwendbar (Class Functions/Procesdures und Hacks ausgeschlossen). Ich will sie auch nicht aufrufen sondern sie Hooken.


//Win32.API

mkinzler 18. Jul 2010 22:09

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Alle Methoden, egal ob privat oder public, sind nur innerhalb einer Object-Instanz verwendbar (Class Functions/Procesdures und Hacks ausgeschlossen).
Public Methoden sind von ausserhalb aufrufbar.

Hast du den Source der Komponente?

Bernhard Geyer 18. Jul 2010 22:10

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von Win32.API (Beitrag 1036066)
Ich brauche die Adresse um einen Bug in der Komponente zu beseitigen.

Und wie wäre es den Fehler zu beheben?

Win32.API 18. Jul 2010 22:13

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von mkinzler (Beitrag 1036069)
Zitat:

Alle Methoden, egal ob privat oder public, sind nur innerhalb einer Object-Instanz verwendbar (Class Functions/Procesdures und Hacks ausgeschlossen).
Public Methoden sind von ausserhalb aufrufbar.

Hast du den Source der Komponente?

Ich wollte formulieren, dass Methoden nur aus einer Objekt-Instanz heraus aufrufbar sind. (MyObj.Test <> TMyObj.Test)

Nein, der Source liegt leider nicht vor.

Zitat:

Zitat von Bernhard Geyer (Beitrag 1036071)
Zitat:

Zitat von Win32.API (Beitrag 1036066)
Ich brauche die Adresse um einen Bug in der Komponente zu beseitigen.

Und wie wäre es den Fehler zu beheben?

Die Funktion sollte immer True zurück geben, durch einen Bug wird unter bestimmten Umständen false zurück gegeben, was die weitere Verarbeitung behindert.

Also muss an die Funktions Adresse ein:

Code:
xor eax, eax
add eax, 1
retn
gepatch werden.

daywalker9 18. Jul 2010 22:19

AW: Adresse einer privaten Methode bekommen
 
Dann frag den Rückabe wert nicht ab? Wenn der immer true sein soll ist das Result ja egal

mkinzler 18. Jul 2010 22:21

AW: Adresse einer privaten Methode bekommen
 
Eine Rückgabe die immer True ergibt? Dann könnte man ja auf die Rückgabe verzichten

BUG 18. Jul 2010 22:27

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von daywalker9 (Beitrag 1036074)
Dann frag den Rückabe wert nicht ab? Wenn der immer true sein soll ist das Result ja egal

Es ist eine private Methode, die anscheinend von der Komponente genutzt / abgefragt wird, worauf er keinen Einfluss hat.


Spannendes Problem :twisted:

Win32.API 18. Jul 2010 22:30

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von BUG (Beitrag 1036077)
Zitat:

Zitat von daywalker9 (Beitrag 1036074)
Dann frag den Rückabe wert nicht ab? Wenn der immer true sein soll ist das Result ja egal

Es ist eine private Methode, die anscheinend von der Komponente genutzt / abgefragt wird, worauf er keinen Einfluss hat.


Spannendes Problem :twisted:

Genau so sieht es aus. Ich habe keinen Einfluss ob die Methode aufgerufen wird oder nicht.

mkinzler 18. Jul 2010 22:30

AW: Adresse einer privaten Methode bekommen
 
Dann melde es dem Hersteller

Win32.API 18. Jul 2010 22:46

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von mkinzler (Beitrag 1036080)
Dann melde es dem Hersteller

Ist schon vor ca. 2 Monaten passiert, bis jetzt leider keine Besserung. Darum wollte ich es nun selber in die Hand nehmen.

Namenloser 18. Jul 2010 23:30

AW: Adresse einer privaten Methode bekommen
 
Delphi-Quellcode:
unit Unit1;

interface

uses
  classes;

type

  TMyClass = class
  strict private
    procedure BuggyMethod;
  end;

  TMyClassHack = class helper for TMyClass
  public
    function GetBuggyMethodAddress: Pointer;
  end;

  procedure Test;

implementation

uses
  SysUtils;

{ TmyClassHack }

function TMyClassHack.GetBuggyMethodAddress: Pointer;
asm
  lea eax, [0+TMyClass.BuggyMethod]
end;

{ TMyClass }

procedure TMyClass.BuggyMethod;
begin
  writeln('hello');
end;

procedure Test;
var
  Obj: TMyClass;
  Addr: Pointer;
begin
  Obj := TMyClass.Create;
  writeln(format('%p',[Obj.GetBuggyMethodAddress]));
  Addr := Obj.GetBuggyMethodAddress;
  asm
    call Addr
  end;
  Obj.Free;
end;

end.
Das funktioniert bei mir. Ich weiß allerdings nicht genau was du damit meinst:
Zitat:

Eine "Hack"/"Dummy"-Klasse kommt in diesem Fall nicht in Frage, da der Code für mehrere Versionen der Klasse arbeiten soll.

himitsu 19. Jul 2010 06:00

AW: Adresse einer privaten Methode bekommen
 
strict private sollte doch eigentlich komplett privat sein, also nichtmal in einer anderen Klasse, der selben Unit.
Und selbt normale private Methoden kann man "eigentlich" nicht von anderen Units aus aufrufen.

Wollte erst fragen, ob du das auch mal mit getrennten Units getestes hast, aber selbst da geht es.

Also dieser Hack ist dann ja richtig böse :shock:




Es gibt abner noch einen einfachen Hack, um virtuelle private Methoden zu bekommen ... ohne RTTI- oder VMT-Auslesen und so.

Einfach 'ne Dummy-Klasse, ebenfalls mit diesen virtuellen Methoden (natürlich in selber Reihenfolge) erstellen und rübercasten.

Namenloser 19. Jul 2010 06:09

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von himitsu (Beitrag 1036093)
strict private sollte doch eigentlich komplett privat sein, also nichtmal in einer anderen Klasse, der selben Unit.
Und selbt normale private Methoden kann man "eigentlich" nicht von anderen Units aus aufrufen.

Wollte erst fragen, ob du das auch mal mit getrennten Units getestes hast, aber selbst da geht es.

Nein hab ich nicht, aber ich hatte erst testweise probiert, ob man in einem Class-Helper auf unter strict private deklarierte Methoden zugreifen kann, was nicht ging. Daraufhin hab ich dann mal probiert ob es im Inline-Assembler funktioniert, und da es funktionierte, bin icheinfach mal davon ausgegangen, dass das auch in verschiedenen Units funktionieren muss. Denn bei Strict Private hat die beinhaltende Unit ja im Gegensatz zum normalen private keine Privilegien.
Zitat:

Zitat von himitsu (Beitrag 1036093)
Also dieser Hack ist dann ja richtig böse :shock:

Danke :mrgreen:

[edit]
Zitat:

Zitat von himitsu (Beitrag 1036093)
Es gibt abner noch einen einfachen Hack, um virtuelle private Methoden zu bekommen ... ohne RTTI- oder VMT-Auslesen und so.

Einfach 'ne Dummy-Klasse, ebenfalls mit diesen virtuellen Methoden (natürlich in selber Reihenfolge) erstellen und rübercasten.

Aber was für einen Sinn sollte es haben, private Methoden als virtual zu deklarieren? Mann kann sie doch eh nicht überschreiben, weil man in abgeleiteten Klassen keinen Zugriff darauf hat.
[/edit]

himitsu 19. Jul 2010 06:18

AW: Adresse einer privaten Methode bekommen
 
Hättest du das nicht mal vor 'nem knappen Jahr sagen können?

Weil irgendein "Arsch" TApplication.ProcessMessage als Privat deklariert hat, kommt man da einfach nicht ran und so hätte ich mir vel Arbeit und umständliche Alternativen ersparen können. :cry:


Hey, jetzt könnte man vermutlich auch Hagens Delay mit einer noch besseren Zeiteinhaltung versehen, selbst wenn viele Messages eintreffen :thumb:

mkinzler 19. Jul 2010 06:34

AW: Adresse einer privaten Methode bekommen
 
So weit es möglich ist sollte man eh uaf solche Hacks verzichten. Denn diese Lücke könnte irgendwann geschlossen werden

Namenloser 19. Jul 2010 06:40

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von mkinzler (Beitrag 1036099)
So weit es möglich ist sollte man eh uaf solche Hacks verzichten. Denn diese Lücke könnte irgendwann geschlossen werden

Ich bin der Meinung, man sollte lieber darauf verzichten, beliebige Sachen als privat zu deklarieren, wenn es keinen echten Grund dafür gibt.

himitsu 19. Jul 2010 06:44

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von mkinzler (Beitrag 1036099)
So weit es möglich ist sollte man eh uaf solche Hacks verzichten. Denn diese Lücke könnte irgendwann geschlossen werden

Ich hoffe die machen sowas erst dann, wenn sie mal ihre Sichbasrkeitsrichtlinien verbessert haben.

Es gibt z.B. keinen Grund, warum ProcessMessage (drum sind dieses und Delay soein schönes Beispiel) versteckt sein muß.

ProcessMessages bearbeitet immer alle Messages, bis nix mehr da ist.
ProcessMessage verarbeitet nur die nächste Message, also könnte man damit.
Somit könnte Delay hier seine Pausenzeiten besser einhalten, da man die Verarbeitung eher abbrechen könnte und nicht alles sofort verarbeitet.

Zitat:

Zitat von NamenLozer (Beitrag 1036101)
Ich bin der Meinung, man sollte lieber darauf verzichten, beliebige Sachen als privat zu deklarieren, wenn es keinen echten Grund dafür gibt.

jupp

Zitat:

Ist schon vor ca. 2 Monaten passiert, bis jetzt leider keine Besserung. Darum wollte ich es nun selber in die Hand nehmen.
Gut, ich hatte hier gerade noch 2 Jahre im Kopf und wollte grade sowas wie "sooo lange keine Antwort? ... is ja nett" sagen (aber )

Stevie 19. Jul 2010 06:48

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von rollstuhlfahrer (Beitrag 1036063)
Das Ganze scheitert schon am Konzept. Du kannst nicht die Adresse einer privaten Prozedur auslesen. Eine private Prozedur ist vom Konzept her (ähnlich wie protected) nur INNERHALB eines Objektes verwendbar. Du kannst sie also auch nicht von außen aufrufen, weil es so aussieht, als würde sie gar nicht existieren. Somit kann sie von RTTI nicht gefunden werden.

Das stimmt so nicht. Mit Delphi 2010 (welches der TE nutzt) kann man von private bis published alles von einer Klasse über RTTI abrufen, sofern dies eingestellt wurde. Dafür gibt es spezielle Compiler Direktiven. Nützt dem TE natürlich nix, da wahrscheinlich nicht mit diesen RTTI Einstellungen kompiliert wurde und er den Source nicht hat (dann könnte er ja auch gleich die Methode fixen :P)

Zitat:

Zitat von NamenLozer (Beitrag 1036101)
Zitat:

Zitat von mkinzler (Beitrag 1036099)
So weit es möglich ist sollte man eh uaf solche Hacks verzichten. Denn diese Lücke könnte irgendwann geschlossen werden

Ich bin der Meinung, man sollte lieber darauf verzichten, beliebige Sachen als privat zu deklarieren, wenn es keinen echten Grund dafür gibt.

Imo wird eher andersrum nen Schuh draus, es sollte nur public sein, was man auch von außen aufrufen soll/darf/muss. Und protected nur, was vom Design her dafür vorgesehen ist, in abgeleiteten Klassen modifiziert zu werden.

Namenloser 19. Jul 2010 06:57

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von Stevie (Beitrag 1036103)
Zitat:

Zitat von NamenLozer (Beitrag 1036101)
Zitat:

Zitat von mkinzler (Beitrag 1036099)
So weit es möglich ist sollte man eh uaf solche Hacks verzichten. Denn diese Lücke könnte irgendwann geschlossen werden

Ich bin der Meinung, man sollte lieber darauf verzichten, beliebige Sachen als privat zu deklarieren, wenn es keinen echten Grund dafür gibt.

Imo wird eher andersrum nen Schuh draus, es sollte nur public sein, was man auch von außen aufrufen soll/darf/muss.

Nein, natürlich soll man nicht alles als public deklarieren. Ich deklariere auch nur die Sachen als public, die ich in der "offiziellen Anwendungsschnittstelle" haben will. Alles andere deklariere ich aber zum Großteil als protected und nicht als private. Nur in sehr seltenen Sonderfällen, wenn es wirklich einen triftigen Grund gibt, warum Nachfahren keinen direkten Zugriff haben dürfen, deklariere ich Methoden oder Felder als privat.

Win32.API 19. Jul 2010 07:36

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von NamenLozer (Beitrag 1036086)
Delphi-Quellcode:
unit Unit1;

interface

uses
  classes;

type

  TMyClass = class
  strict private
    procedure BuggyMethod;
  end;

  TMyClassHack = class helper for TMyClass
  public
    function GetBuggyMethodAddress: Pointer;
  end;

  procedure Test;

implementation

uses
  SysUtils;

{ TmyClassHack }

function TMyClassHack.GetBuggyMethodAddress: Pointer;
asm
  lea eax, [0+TMyClass.BuggyMethod]
end;

{ TMyClass }

procedure TMyClass.BuggyMethod;
begin
  writeln('hello');
end;

procedure Test;
var
  Obj: TMyClass;
  Addr: Pointer;
begin
  Obj := TMyClass.Create;
  writeln(format('%p',[Obj.GetBuggyMethodAddress]));
  Addr := Obj.GetBuggyMethodAddress;
  asm
    call Addr
  end;
  Obj.Free;
end;

end.
Das funktioniert bei mir. Ich weiß allerdings nicht genau was du damit meinst:
Zitat:

Eine "Hack"/"Dummy"-Klasse kommt in diesem Fall nicht in Frage, da der Code für mehrere Versionen der Klasse arbeiten soll.


Jawoll :thumb:. Das Zusammenspiel aus Classhelper und Zugriff via Assembler macht es Möglich.

Mit Hack-Klasse meinte ich eine Klasse, die exakt gleich deklariert ist, aber die entsprechende Methode als public deklariert. Somit liegt im Speicher alles an der gleichen Stelle und der Zugriff ist auch Möglich.

Grüße,
Win32.API

himitsu 19. Jul 2010 08:29

AW: Adresse einer privaten Methode bekommen
 
Zitat:

Zitat von Win32.API (Beitrag 1036112)
Mit Hack-Klasse meinte ich eine Klasse, die exakt gleich deklariert ist, aber die entsprechende Methode als public deklariert. Somit liegt im Speicher alles an der gleichen Stelle und der Zugriff ist auch Möglich.

Das geht aber nur mit virtuellen oder dynamischen Methoden
und mit Feldern.
Normalte Methoden kann man so nicht zugänglich machen, da diese direkt im Quellcode, bei allen Aufrufen, und z.B. nicht über die VMT des erzeugten Objekts adressiert sind.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:39 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz