AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Verwenden von GetClass und RegisterClass
Thema durchsuchen
Ansicht
Themen-Optionen

Verwenden von GetClass und RegisterClass

Ein Thema von striker · begonnen am 18. Sep 2004 · letzter Beitrag vom 21. Apr 2005
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von maximov
maximov

Registriert seit: 2. Okt 2003
Ort: Hamburg
548 Beiträge
 
Delphi 2005 Professional
 
#11

Re: Verwenden von GetClass und RegisterClass

  Alt 22. Sep 2004, 10:10
Hat es denn funktioniert, sprich kannst jetzt beliebige formulare laden, ohne den code zu instanzieren?
mâxîmôv.

{KDT}
  Mit Zitat antworten Zitat
striker

Registriert seit: 18. Sep 2004
6 Beiträge
 
Delphi 6 Enterprise
 
#12

Re: Verwenden von GetClass und RegisterClass

  Alt 23. Sep 2004, 19:13
ja geht wunderbar jetzt danke nochmal...
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#13

Re: Verwenden von GetClass und RegisterClass

  Alt 24. Sep 2004, 13:42
Aber Vorsicht!
der von mir benutzte Trick geht offiziell überhaupt nicht nach Borlands Aussagen. Soll heisen offiziell kann man nicht über alle RTTI's eines Programmes iterieren. Bisher habe ich auch noch keine einzigste andere Implementation meines Tricks gefunden. D.h. wenn du diese Funktionen benutzt dann kannst du dich nur alleine auf mein Wissen stützen. Der obige Source funktioniert auch nur bis Delphi 6. Für Delphi 7 muß eine kleine Änderung durchgeführt werden. Allerdings, während der Entwicklung dieses Tricks habe ich alle Delphi Versionen bis Delphi 6 ausgiebigst getestet. Wenn man weiß wie der Source vorgeht besteht also die Möglichkeit speziellen Code zu programmieren der den Trick "austrickst", er produziert also dann Fehler. Dies könnte man für "Anti-Reverse-Engineering" Fallen benutzen, allerdings muß man dann schon ganz genau wissen was man programmieren muß. Rein zufällig kann ein solcher "Stolper-code" aber nicht entstehen, d.h. mit normalen Packages/Modulen funktioniert obige Funktion absolut sauber.

Konzeptonell stellt sich aber die Frage ob die Anwendung der obigen Funktion ansich sauber ist. Soll heissen, das man eigentlich sein eigenes Konzept überdenken sollte bevor man obigen Trick benutzt.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von maximov
maximov

Registriert seit: 2. Okt 2003
Ort: Hamburg
548 Beiträge
 
Delphi 2005 Professional
 
#14

Re: Verwenden von GetClass und RegisterClass

  Alt 24. Sep 2004, 14:12
Ja, das dies nicht grade sauber ist, ist mir bewusst. Deshalb auch mein hinweis:

Zitat von maximov:
...
So jetzt gibt es da aber einen illegalen trick, der aber relativ effektiv sein könnt.
...
Denke aber nicht das Strike das hoch professionell einsetzen will. Für seine anwendung sehe ich aber keine bessere lösung und als workaround passt dein trick halt wie faust auf auge ...denn anscheinend registrieren sich komponenten ja nicht standardmässig und alle von hand zu registrieren wäre noch unschöner.
mâxîmôv.

{KDT}
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#15

Re: Verwenden von GetClass und RegisterClass

  Alt 24. Sep 2004, 14:51
Naja, das eigentliche Problem entsteht woanders. Jede eigene TForm Klasse enthält in deren PUBLISHED Sektion Felder auf deren Komponenten und Controls. Der Compiler legt also in der RTTI im Codesegment zu dieser TForm Klasse auch die Informationen auf diese Felder ab. Diese Informationen enthalten den Namen der Komponente/Controls und auch den Klassentyp. Dieser Klassentyp ist aber nichts anderes als ein Zeiger in ds Codesegment wo dann wiederum die RTTI dieser Klassen zu finden ist.

So, lädt sich nun ein TForm selber aus deiner DFM so ist dieser TForm-Klasse sehr wohl bekannt welche Komponenten/Controls es selber enthält und welchen Klassentyp diese besitzen. Dazu muß die virtuelle DFM-Laderoutine -> eg. das Delphi VCL Streaming System, nur ausgehend von der aktuellen TForm Klasse in deren RTTI nachschlagen.

Lädt man aber eine x'beliebige DFM, ohne das die dazugehörige TForm-Klasse erzeugt wurde so funktioniert dieses nicht mehr. Da nun eben kein Zugriff mehr auf die korrekte RTTI und deren published Komponentenfelder mehr vorhanden ist. Somit entsteht ein Fehler das eine bestimmte Klasse nicht registriert sei. Denn, eine Klasse ist nichts anderes wie ein Zeiger in das Codesegment. Solche Zeiger kann man aber in DFM's nicht direkt speichern. Um das denoch hinzubekommen benutzt das Delphi Streaming System den Feld-Namen und Klassentyp und speichert diese Informationen in der DFM. Sprich in der DFM steht "Object" -> "Button1" : "TButton" als Strings. Object bezeichnet ein Token so das das Streamingsystem weis das jetzt ein TObject == Klasse gemeint ist. "Button1" wiederum ist der Name des Feldes das in der TForm Klasse definiert wurde -> also der Name der Komponenten. Und "TButton" ist die eigentliche Klasse der Komponente. Delphis Streamingsystem lädt diese Strings aus der DFM und versucht nun diese Namenstrings in Klassen-Zeiger umzuwandeln. Natürlich muß es dazu eben den String "TButton" irgendwo nachschlagen. Da Delphi selber NICHT so einen Trick wie den obigen benutzt (geht ja offiziell auch nicht laut Borland), benutzt die RTL zwei Wege. Zuerstmal schaut es in der aktuellen Instance==Object in deren RTTI nach ob es ein Feld mit Namen "Button1" gibt. Wenn ja vergleicht es über die RTTI dessen Klassennamen "TButton" mit dem der aus der DFM geladen wurde. Wenn diese übereinstimmen hat das Streamingsystem schon die richtige und eindeutige Zuordnung gefunden. Wenn nein, geht es iterariv über die weiteren Felder der Instance und deren RTTI drüber und sucht.

Wenn all dies fehlschlägt greift nun das dynamsiche Klassen-Registratuons-Konzept. Mit RegisterClass() wird eine Klasse in einer globalen TList gespeichert und registeriert. Delphi geht nun diese Liste iterativ durch und vergleich von den darin gespeicherten Klassen == RTTI's die Klassennamen mit "TButton". Sollte ein übereinstimmerneder Eintrag gefunden worden sein so hat man zum String "TButton" die Klasse == Zeiger in das Codesegment zur RTTI dieser TButton Klasse gefunden.

Statt nun, wie du oben gezeigt hast, mit RegisterClass() alle im Code enthaltenen Klassen zu registrieren wäre es konzeptionell am saubersten die DFM nur durch die richtige TForm Klasse laden zu lassen. Sollte dies aber nicht möglich sein so stellt Delphis Komponmenten-Streaming-Sytsem eine Callback zur Verfügung. Diese Callback wird immer dann aufgerufen wenn Delphi einem Klassennamens-String NICHT die Klasse zuordnen kann. D.h. wenn alle Stricke reisen und selbst mit Registerclass() kein Erfolg beschieden ist. Nun, ich würde diese Callback überschreiben (sie ist zur Laufzeit immer NIL) und darin mit dem obigen Trick nach einer Klassen-RTTI im Codesegment aller geladenen Module nach dem Klassennamen suchen. Somit überfrachtet man nicht die interne Liste der RegisterClass() Funktion.

Aber im Grunde wäre es für Borland ein leichtes gewesen von vornherein die RTTI's aller Typdeklarationen untereinander als verlinkte Liste im Codesegment zu speichern. Dann wären solche "um die Ecke Tricks" wie mit RegisterClass() etc. pp. garnicht mehr nötig. Der Compiler würde also alle Typdeklarationen, sprich deren RTTI's, untereinander verlinken und pro Modul gäbe es nur einen globalen Zeiger auf den ersten RTTI Record.
Nun, mein obiger Trick geht genau so vor und nutzt einige Eigenheiten wie Code-Aligment dieser RTTI Records aus. Im Grunde also so als wenn diese RTTI Records als verlinkte Liste durch den Compiler gespeichert wurde (was aber nichtreal der Fall ist). Der Trick ist also deterministisch.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von maximov
maximov

Registriert seit: 2. Okt 2003
Ort: Hamburg
548 Beiträge
 
Delphi 2005 Professional
 
#16

Re: Verwenden von GetClass und RegisterClass

  Alt 29. Sep 2004, 21:26
Ja,

das ist mir im wesentlichen alles bewusst, aber ich danke dir für diese fundierte zusammenfassung. An den Callback hatte ich auch gedacht, war aber zu faul zu suchen, wo ich ihn letztendlich setzen kann. Naja, striker hat ja was er will, oder glaubt zu wollen.

Hab gestern, mit deinen Hack, mal ein bisschen in den delphi eigenen BPLs rum geschnüffelt und wahrlos komponenten und forms instanziert. Das förderte dann einige lustige delphi bruchstücke zu tage. Ich vermute, dass du ähnliches im sinn hattest, als zu von 'reverse engineering' redetest? Hätte mir aber auch eine offizielle lösung von borland gewünscht
mâxîmôv.

{KDT}
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#17

Re: Verwenden von GetClass und RegisterClass

  Alt 30. Sep 2004, 03:50
Im Grunde ja, nur bin ich noch einen Schritt weiter gegangen.
In meinem Falle konnte ich von einem laufenden Prozess ermitteln ob es sich um eine Delphi/BCB Anwendung handelte. Wenn ja bin ich mit meinem Code über alle geladenen Module dieses Prozesse durchgegangen und habe mir so die RTTI und alle Datentypen des analysierten Programmes angeschaut. Naja war aber eher eine Spielerei die nur abtesten sollte ob es geht.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.840 Beiträge
 
Delphi 10 Seattle Enterprise
 
#18

Re: Verwenden von GetClass und RegisterClass

  Alt 21. Apr 2005, 17:35
Zitat von negaH:
Der obige Source funktioniert auch nur bis Delphi 6. Für Delphi 7 muß eine kleine Änderung durchgeführt werden. Allerdings, während der Entwicklung dieses Tricks habe ich alle Delphi Versionen bis Delphi 6 ausgiebigst getestet.
Hallo Hagen,
kannst Du bitte mal den Source für Delphi 7 posten?

Danke
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.840 Beiträge
 
Delphi 10 Seattle Enterprise
 
#19

Re: Verwenden von GetClass und RegisterClass

  Alt 21. Apr 2005, 18:41
Zitat von MaBuSE:
Hallo Hagen, kannst Du bitte mal den Source für Delphi 7 posten?
@Hagen: Falls Du diese Änderung meintest, die ist in dem File schon enthalten -> Also einfach meinen letzten Beitrag ignorieren

Hagen schrieb in http://www.delphipraxis.net/internal...=128809#128809 :
Zitat von negaH:
Der obige Code ist von mir für Delphi 2 bis 6 entwickelt und getestet wurden. Er ist aber auch wie man sieht eine "Quick&Dirty" Lösung, d.h. ich habe sie nicht "schön" gemacht. Die einzigste Änderung die man für D7 machen muß ist in

  if (PDWord(P)^ = DWord(K)) and (PByte(K)^ > 0) and (PByte(K)^ < 18) then // Info.Kind in ValidRange.D6 Der Wert 18 könnte durch

 ... <= Integer(High(TTypeKind)) then ersetzt werden. Dann wäre es automatisch durch neucompilieren für alle Delphi Versionen gültig.
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:49 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz