AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi schreibender Zugriff auf private Variablen ?
Thema durchsuchen
Ansicht
Themen-Optionen

schreibender Zugriff auf private Variablen ?

Ein Thema von MaBuSE · begonnen am 6. Nov 2007 · letzter Beitrag vom 7. Nov 2007
Antwort Antwort
Seite 1 von 2  1 2      
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
 
#1

schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 16:50
Hallo,

ich habe ein kleines Problem. Ich müsste eine private Variable ändern (von außen) Das ist normalerweise nicht möglich und auch nicht gewollt. Kennt jemand einen dirty hack um das trotzdem zu machen?

Beisp:
Delphi-Quellcode:
unit Unit1;

interface

uses
  SysUtils;

type
  TmyTest = class(TObject)
  private
    sTest: string;
  public
    constructor Create;
    function getTest: string;
  end;

implementation

{$R *.dfm}

{ TmyTest }

constructor TmyTest.Create;
begin
  sTest := IntToStr(Random(100));
end;

function TmyTest.getTest: string;
begin
  Result := sTest;
end;

end.
Ich möchte nun in der Unit2 schreibend auf sTest zugreifen.

Aber ich kann Unit1 nicht ändern !!!

Wäre sTest protected, wäre es kein Problem.
Innerhalb der selben Unit kann ich auf sTest zugreifen, aber das bringt mir nix.
Class Helper bringt mich auch nicht weiter, da er ja auch von "außen" zugreift.

Delphi-Quellcode:
unit Unit2;

interface

uses
  SysUtils, Unit1;

type

type
  TmyTestHelper = class helper for TmyTest
    procedure setTest(s: string);
  end;

implementation

{$R *.dfm}

{ TmyTestHelper }

procedure TmyTestHelper.setTest(s: string);
begin
  // hier gibt es leider keinen schreibenden Zugriff auf sTest
end;

end.
Hat jemand eine Idee?
(vieleicht mit Code Beisp. , evtl mit RTTI?)
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
Benutzerbild von Flocke
Flocke

Registriert seit: 9. Jun 2005
Ort: Unna
1.172 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

Re: schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 16:59
Vielleicht geht's so: Einander zugewiesene Strings zeigen ja normalerweise solange auf denselben Speicherbereich, bis man sie ändert. Irgendwo in der Struktur TmyTest muss es einen Zeiger auf denselben String geben, wie getTest ihn zurückliefert.

(ungetestet)
Delphi-Quellcode:
type
  PString = ^string;

function FindStringReference(Obj: Pointer; Size: Integer; const TheString: string): PString;
begin
  while Size >= 8 do
  begin
    Obj := Pointer(Integer(Obj) + 4);
    dec(Size, 4);
    if PInteger(Obj)^ = Integer(@TheString) then
    begin
      Result := PString(Obj);
      Exit;
    end;
  end;
  Result := nil;
end;

// Aufrufen mit:
FindStringReference(myObj, SizeOf(myObj), myObj.getTest)^ := 'Neuer Text';
Volker
Besucht meine Garage
Aktuell: RtfLabel 1.3d, PrintToFile 1.4
  Mit Zitat antworten Zitat
Benutzerbild von Phoenix
Phoenix
(Moderator)

Registriert seit: 25. Jun 2002
Ort: Hausach
7.641 Beiträge
 
#3

Re: schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 17:05
Okay, jetzt wird's dirty:

Caste eine Methode von dem Objekt, auf dem Du die Variable ändern willst, nach TMethod. TMethod hat ein Property Data und ein Property Code. Das Data Property ist ein Zeiger auf den Datenbereich des Objektes.

In dem solltest Du nach dem aktuellen Wert Suchen und so die Speicherstelle herausfinden können. Es sollte gehen, das dann nach String zu casten und zu verändern.

Allerdings gebe ich da keine Gewähr
Sebastian Gingter
Phoenix - 不死鳥, Microsoft MVP, Rettungshundeführer
Über mich: Sebastian Gingter @ Thinktecture Mein Blog: https://gingter.org
  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
 
#4

Re: schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 17:06
Zitat von Flocke:
Vielleicht geht's so: Einander zugewiesene Strings zeigen ja normalerweise solange auf denselben Speicherbereich, bis man sie ändert. Irgendwo in der Struktur TmyTest muss es einen Zeiger auf denselben String geben, wie getTest ihn zurückliefert.

(ungetestet)
...
Danke, das teste ich mogen mal aus...
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 17:17
@Flocke: Gute Idee, aber ich glaube, dass da noch ein paar kleine Fehler drin sind...
Delphi-Quellcode:
function FindStringReference(Obj: Pointer; Size: Integer; const TheString: string): PString;
begin
  while Size >= 8 do
  begin
    Obj := Pointer(Integer(Obj) + 4);
    dec(Size, 4);
    if PInteger(Obj)^ = Integer(TheString) then //Der String selbst ist der Zeiger - wir brauchen nicht seine Adresse!
    begin
      Result := PString(Obj);
      Exit;
    end;
  end;
  Result := nil;
end;

FindStringReference(myObj, MyObj.InstanceSize, myObj.getTest)^ := 'Neuer Text';//SizeOf liefert für alle Klassen 4 zurück, da es Zeiger sind
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 17:52
@Phoenix: Da steht aber nur der Zeiger. Das wird recht kompliziert.

Erweiterte Möglichkeit zu Phoenix:
Variable ist "String", also dynamisch. Damit muss sie definitv in der RTTI auftauchen.

Die RTTI zum Datenrecord einer Klasse findest du so
Delphi-Quellcode:
var inittable:^pointer;
begin
  inittable:=pointer(integer(self.classparent)+vmtinittable); //oder noch mehr classparent's; je nachdem wo man hinwill
  //oder nicht im Parent, dann pointer(integer(ppointer(self)^)+vmtinittable);
                          //bzw. pointer(integer(mytest.classInfo)+vmtinittable);

  if inittable<> nil then
    inittable:=inittable^
  else
    //diese Klasse hat (in der Generation) keine dynamischen Komponenten
Dort (bei inittable) dürftest du erstmal ein $0E für Record finden, dann einen Shortstring der nur aus dem Längenbyte besteht (indem 0 drinn steht), und dann kommt folgender Datenkonstrukt
Delphi-Quellcode:
//RTTI eines Records
type PPropContent=^TPropContent;
     TPropContent=record
       RecordData:pointer; //RTTI einer dynamischen Variablen innerhalb des Records
       Position:LongInt; //Position der Variablen im Record
     end;
type PRecordData=^TRecordData;
     TRecordData=record
       ParamCount:cardinal; //Größe des Records insgesamt
       PropCount:cardinal; //Anzahl der dynamischen Komponenten
       Content:array[0..16737] of TPropContent;
end;
Dich interessiert davon das Array Content[0..Propcount-1]. Und in jedem Element des Arrays hlst du dir RecordData. Das ist ein Zeiger auf einen Zeiger auf die RTTI der dynamischen Komponente aus deiner Klasse. Und wenn dort das erste Byte $0A ist, dann ist die dynamische Komponente ein String (Du kannst auch mit den Konstanten aus der TypeInfo arbeiten tkString=10).
Jetzt weist du dass diese dynamische Komponente ein String ist und du nimmst dir Position, addierst den Wert zu self und hast deinen String.
Und jetzt musst du den Inhalt überprüfen, wie Phoenix sagte.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#7

Re: schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 19:00
Eine Instanz ist eigentlich ein Pointer auf den Bereich wo die Daten für die Klasse liegen.
Wenn du also weißt an welchem Offset der String liegt brauchst du einfach nur auf die Instanzvariable den Offset addieren, die erhaltene Adresse auf einen PString casten und dann zu ändern.

bei
Delphi-Quellcode:
type
  TmyTest = class(TObject)
  private
    sTest: string;
  public
    constructor Create;
    function getTest: string;
  end;
kommst du so an "sTest":
Delphi-Quellcode:
var
  lMyTest : TmyTest;
begin
  lMyTest := TmyTest.Create();
  PString(Cardinal(lMyTest) + Cardinal(TmyTest.InstanceSize) - sizeof(string))^ := 'neuer Wert';
[Edit]
TmyTest.InstanceSize auf Cardinal gecastet um Warnung weg zu bekommen
[/Edit]
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Hawkeye219

Registriert seit: 18. Feb 2006
Ort: Stolberg
2.227 Beiträge
 
Delphi 2010 Professional
 
#8

Re: schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 19:06
Hallo MaBuSE,

unter gewissen Voraussetzungen kann eine shadow class den Zugriff ermöglichen.

Gruß Hawkeye
  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
 
#9

Re: schreibender Zugriff auf private Variablen ?

  Alt 6. Nov 2007, 21:16
Danke an Alle !!!

@sirius: ich muß mal schauen wie weit ich hier mit rtti komme -> morgen

Zitat von SirThornberry:
Eine Instanz ist eigentlich ein Pointer auf den Bereich wo die Daten für die Klasse liegen.
Wenn du also weißt an welchem Offset der String liegt brauchst du einfach nur auf die Instanzvariable den Offset addieren, die erhaltene Adresse auf einen PString casten und dann zu ändern.
...
Die Test Klasse ist stark vereinfacht. Ich wollte kein zu kompliziertes Beispiel.
Das Objekt, um das es geht hat ein paar hundert private Variablen, Funktionen und Proceduren. und noch ein mal ein paar hundert Dinge in protected, public und published. Das macht das ganze etwas schwerer.

@Hawkeye: Deine Lösung sieht vielversprechend aus. Ich werde das mal morgen im Büro testen

Vieleicht gibt es ja noch mehr Ideen
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: schreibender Zugriff auf private Variablen ?

  Alt 7. Nov 2007, 07:19
Hast du den Source der Klasse ? Wenn ja kopiere deren Deklaration, nenne sie um, schmeiße alle Methoden usw. raus bis nur noch die privaten Felder in deiner neuen Deklaration drinnen stehen. Beim Zugriff auf diese Felder castest du dein Object zum neuen Klassentyp. Das sähe so aus:

Delphi-Quellcode:
type
  TXYClassCracker = class(TXYClassAnchor)
  private
    FField: .....
  end;

procedure Test;
begin
  TXYClassCracker(Object).FField := ....;
end;
Du deklarierst quasi eine 1 zu 1 Kopie deiner Klasse auf die du später illegalen Zugriff erlangen möchtest. Letzendlich geht es dabei nur darum das der Compiler die richtigen Zeigeroffsets auf die Felder des Objectes errechnen kann.

Gruß Hagen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 08:01 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