Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   DEC 5.2 String hashen? (https://www.delphipraxis.net/192579-dec-5-2-string-hashen.html)

a.def 3. Mai 2017 00:11

AW: DEC 5.2 String hashen?
 
Zitat:

Wenn die Checksumme am Ende steht, so steht da ja noch nicht drin, über welchen Bereich der Exe sie gemacht wurde. Muss ja nicht die ganze Exe sein, könnten ja auch nur die ersten X Byte sein. Oder MD5-Checksumme einer MD5-Checksumme oder die Checksumme wird vorm Speichern noch mit irgend 'nem Wert gexodert ...
Bei mir steht aktuell nur eine Checksumme am Ende der Exe. Der Programmstart hat sich deshalb schon um ~200ms verlangsamt. Reicht mir erstmal :P
Zum Hashen benutze ich, wie man in der Unit sieht, übrigens nicht DEC sondern System.Hash.THash ....

Nochmal zu meiner Ausgangsfrage:
ist es denn überhaupt möglich mit DEC einen String zu hashen?

Michael II 3. Mai 2017 11:24

AW: DEC 5.2 String hashen?
 
Hallo a.def

ich hatte dir via PN geantwortet.

Öffne ein neues Projekt, setze einen Button aufs Form und kopiere den Text unten rein.

Starte das Programm und klick auf den Button.

Deine exe sieht momentan so aus:
¦FILE EXE TEIL 1¦In EXE nach diesem Text suchen..¦FILE EXE TEIL 2¦

Wenn du den Button drückst, dann wird der Hash Wert h von
¦FILE EXE TEIL 1¦FILE EXE TEIL 2¦
berechnet.

Anschliessend wird eine neue exe md5c.exe erzeugt mit Inhalt:
¦FILE EXE TEIL 1¦<h>¦FILE EXE TEIL 2¦
Anstelle von "In EXE nach diesem Text suchen.." steht also nun der Wert von h in md5c.exe.

Starte md5c.exe. Drücke den Button. md5c.exe berechnet den Hash Wert von
¦FILE EXE TEIL 1¦FILE EXE TEIL 2¦
und liest den Wert von h aus md5c.exe

Die beiden Werte werden in der Zeile "showmessage" miteinander verglichen.

Man kann's sicher kürzer und besser schreiben (und du musst natürlich noch "try finally/except end" einbauen) ...aber es funktioniert.


Delphi-Quellcode:

var
  a : RawByteString = 'In EXE nach diesem Text suchen..';


implementation

{$R *.dfm}


function TByteToHex( b : TBytes ): RawByteString;
var i : integer;
begin
  Result := '';
  for i := 0 to High(b) do
    Result := Result + RawByteString(inttohex( b[i] ));
end;


procedure TForm77.Button1Click(Sender: TObject);
var f2, f : TBytesStream;
    mf, mfc : string;
    hp : int64;
    hashRaw : RawByteString;

begin
  mf := extractfilepath(application.ExeName) + 'md5.exe';
  mfc := extractfilepath(application.ExeName) + 'md5c.exe';

  if copyfile( PChar(application.ExeName), PChar(mf), false ) then
  begin
     f := TBytesStream.Create;
     f.LoadFromFile( mf );
     hp := pos( RawByteString(a), RawByteString(f.Bytes) );
     f2 := TBytesStream.Create;
     f2.Write( f.Bytes[0], hp-1 );
     f2.Write( f.Bytes[hp+length(a)], f.Size - (hp+length(a)) + 1 );

     hashRaw := TByteToHex( System.hash.THashMD5.GetHashBytes( f2 ) );

     showmessage( string(hashraw) + #10 + string(a) +  #10 + (hashraw=a).ToInteger.ToString );

     if extractfilename( application.ExeName ) <> 'md5c.exe' then
     begin
        move( hashRaw[1], f.Bytes[hp-1], length(a) );
        f.SaveToFile( mfc );
     end;
     f.Free;
     close;

     DeleteFile( mf );
  end;
end;

a.def 3. Mai 2017 11:55

AW: DEC 5.2 String hashen?
 
Danke für die Erklärung! Beim ersten f2.Write ist hinten das +1 zuviel glaube ich. Ich habs weggenommen denn sonst wird ein NULL-Zeichen mit verarbeitet das es nicht gibt.

Delphi-Quellcode:
 aByteStream := TBytesStream.Create;
 try
  aByteStream.LoadFromFile(aFileName);
  iPosRawByte := Pos(RawByteString(a), RawByteString(aByteStream.Bytes));

  if iPosRawByte > 0 then
   begin
    aByteStream2 := TBytesStream.Create;
    try
     aByteStream2.Write(aByteStream.Bytes[0], iPosRawByte - 1);
     aByteStream2.Write(aByteStream.Bytes[iPosRawByte + Length(a)], aByteStream.Size - (iPosRawByte + Length(a)));
     aByteStream2.SaveToFile('_STREAM.txt'); // zum test um mir zu zeigen, was in aBytesStream2 vorhanden ist

     hashRaw := TByteToHex(System.hash.THashMD5.GetHashBytes(aByteStream2));

     ShowMessage(string(hashRaw) + #10 + string(a) + #10 + (hashRaw = a).ToInteger.ToString);
    finally
     aByteStream2.Free;
    end;
   end;
 finally
  aByteStream.Free;
 end;
Irgendwo scheint es aber noch ein Problem zu geben. hashRaw ist bei mir D41D8CD98F00B204E9800998ECF8427E, es sollte aber 2708D4849D8E94F1FB0F8145999B632A sein.
Ob da irgendwo was mit der Umwandlung von Byte to Hex schiefgeht?

Edit
mit folgender Zeile klappt es und der Hash ist korrekt. Nur ob das eine schöne Lösung ist?
Delphi-Quellcode:
hashRaw := System.hash.THashMD5.GetHashString(Trim(TEncoding.ANSI.GetString(aByteStream2.Bytes)));


Nur das erneute Auslesen des Hashes funktioniert nicht. Denn wenn ich den RawByteString ersetze, kann ich ja später nicht mehr nach ihm suchen.

Michael II 3. Mai 2017 12:31

AW: DEC 5.2 String hashen?
 
Hallo a.def

1.
wenn du das Programm startest, sind natürlich die Hash Werte voneinander verschieden, denn es wird ja

"In EXE nach diesem Text suchen.." als Hash Wert interpretiert und verglichen mit dem Hash Wert von ¦FILE EXE TEIL 1¦FILE EXE TEIL 2¦.

Wenn du aber die vom Programm erzeugte md5c.exe startest, dann steht anstelle von "In EXE nach diesem Text suchen.." nun der Hash Wert von ¦FILE EXE TEIL 1¦FILE EXE TEIL 2¦. Die Hash Werte sollten nun übereinstimmen.

2.
Zitat:

Beim ersten f2.Write ist hinten das +1 zuviel glaube ich
Nebenbei: Beim ersten f2.write steht am Ende ein -1 und nicht +1 ;-).

Rasch checken: Wie viele Bytes b werden in f2 geschrieben?

b = (hp-1) + (f.Size - (hp+length(a)) + 1) = f.Size-length(a)

Korrekte Länge.

Hast du mit meinem Codete getestet oder mit deinem?

a.def 3. Mai 2017 12:36

AW: DEC 5.2 String hashen?
 
Habe deinen Code genommen und angepasst. Das hier ist mein Code. Ehrlich gesagt verstehe ich noch nicht, wie man TEIL1 und TEIL2 wieder zusammenfügen sollen, wenn am Ende doch ein Hash dazwischen steht.

Delphi-Quellcode:
procedure TForm1.Button6Click(Sender: TObject);
var
 aByteStream, aByteStream2: TBytesStream;
 iPosRawByte: Int64;
 sHash: string;
begin
 // Save hash on the position of RawByteString "a"

 aByteStream := TBytesStream.Create;
 try
  aByteStream.LoadFromFile(aFileName);
  iPosRawByte := Pos(RawByteString(a), RawByteString(aByteStream.Bytes));

  if iPosRawByte > 0 then
   begin
    aByteStream2 := TBytesStream.Create;
    try
     aByteStream2.Write(aByteStream.Bytes[0], iPosRawByte - 1);
     aByteStream2.Write(aByteStream.Bytes[iPosRawByte + Length(a)], aByteStream.Size - (iPosRawByte + Length(a))); // +1 entfernt, da Hash sonst falsch
     // Original: f2.Write( f.Bytes[hp+length(a)], f.Size - (hp+length(a)) + 1 );

     sHash := System.hash.THashSHA2.GetHashString(Trim(TEncoding.ANSI.GetString(aByteStream2.Bytes))); // abgeändert, da Hash sonst ebenfalls falsch
     // Original: hashRaw := TByteToHex( System.hash.THashMD5.GetHashBytes( f2 ) );

     Move(AnsiString(sHash)[1], aByteStream.Bytes[iPosRawByte - 1], Length(a));
     aByteStream.SaveToFile(aFileName);
    finally
     aByteStream2.Free;
    end;
   end;
 finally
  aByteStream.Free;
 end;
end;
Das hier ist meine Prozedur die -nur- dafür da ist den Hash in die Datei zu schreiben.

Erklärung;
ich habe ein kleines Tool, welches NUR dafür da ist die Hashwerte ans Ende von jeder meiner Exe-Dateien zu schreiben.
Ich schiebe dem Tool einfach meine Exe-Dateien in ein Memo, klicke den Button und alle Exen werden angepasst.

Michael II 3. Mai 2017 13:15

AW: DEC 5.2 String hashen?
 
Du schreibst

beim ersten Mal
iPosRawByte - 1

und beim zweiten Mal
aByteStream.Size - (iPosRawByte + Length(a))

Bytes in deinen aByteStream2. Insgesamt also

iPosRawByte - 1 + aByteStream.Size - iPosRawByte - Length(a)

=
aByteStream.Size - 1 - length(a)

Ist nicht schlimm, da du die allermeisten Bytes deiner exe ja berücksichtigst - und weil du es beim Schreiben und Lesen gleich machst.

Ich würde auf TypeCasts wie AnsiString(..) String(..) wenn immer möglich verzichten.

Die Trim Funktion ist soweit ich sehe falsch. Es könnte ja sein, dass in deinem BytesStream vorne oder hinten der Code für das Leerzeichen steht. Mit Trim löschst du diese Leerzeichen Bytes. OK In diesem Anwendungsfall eher nicht [Byte 1 im exe Header ist immer gleich, am Ende der exe?]. Aber wenn du den Code anderswo so verwendest, verlierst du u.U. Infos, bevor du den Hash ermittelst. Also weg damit ;-)

Zitat:

Ehrlich gesagt verstehe ich noch nicht, wie man TEIL1 und TEIL2 wieder zusammenfügen sollen, wenn am Ende doch ein Hash dazwischen steht
Diese Teile sind in der "Quell exe" und in der "Ziel exe" identisch. Deshalb "hashen" wir über diese beiden Teile.

a.def 3. Mai 2017 13:31

AW: DEC 5.2 String hashen?
 
Ich verstehe es leider nicht. ich bleibe lieber beim alten System :pale:

Das Schreiben/modifizieren verstehe ich.

Was ich aber in keinster Weise verstehe ist, wie ich mit der modifizierten Exe (die sich ja SELBER prüft!) wieder an genau die stelle kommen soll, wo der RawByteString durch den Hash ersetzt wurde.
Denn zum Prüfen müsste ich ja von INHALT1<HASH>INHALT2 den <HASH> entfernen, damit ich INHALT1 INHALT2 hashen kann und mit <HASH> vergleichen kann.
Nur die Position ist mir ja, nachdem mit der Exe ( dem Tool die meine Exen modifiziert) die Programm-Exe ansich modifiziert wurde, nicht mehr bekannt da ich sie nicht mehr finden kann.

nahpets 3. Mai 2017 13:38

AW: DEC 5.2 String hashen?
 
Deshalb hatte ich ja in meinem Beispiel die vier @ davor und dahinter.

Das ist die Kennung der Position.

Du brauchst in der Exe eine Dir bekannte Information, die sagt: Hier hinter steht der Hash.

Oder zwischen diesen beiden steht der Hash, ja nach dem, wie Du es lieber lösen möchtest.

a.def 3. Mai 2017 13:39

AW: DEC 5.2 String hashen?
 
Zitat:

Du brauchst in der Exe eine Dir bekannte Information, die sagt: Hier hinter steht der Hash.
Das war die fehlende Information denke ich.

ich dachte das ist ein NoGo? ich teste es mal.

Michael II 3. Mai 2017 13:44

AW: DEC 5.2 String hashen?
 
Und noch etwas:

Mir fällt gerade auf, dass du nun nicht mehr MD5 sondern SHA2 verwendest.

SHA2 Hashs sind länger als MD5. Du musst dies bei deiner Wahl von "a" berücksichtigen.


Im "Fall MD5" wird

a : RawByteString = 'In EXE nach diesem Text suchen..';

in der Ziel exe ersetzt durch sowas wie das hier:

a : RawByteString = 'a8910908bcd9012ba29208210120cd9e';

Wenn du SHA2 verwendest, dann muss dein a doppelt so lang definiert sein.

Wenn du dein a zu kurz wählst, dann überschreibst du Dinge, die du besser stehen lässt ;-).

[Ich habe noch einmal meinen Code gecheckt - und finde keine Fehler. Solltest du meinen Code bei dir laden und laufen lassen und einen Fehler entdecken, dann schreib mir. Danke. Ich verlasse dieses Thema.]

Michael II 3. Mai 2017 14:13

AW: DEC 5.2 String hashen?
 
Zitat:

Nur die Position ist mir ja, nachdem mit der Exe ( dem Tool die meine Exen modifiziert) die Programm-Exe an sich modifiziert wurde, nicht mehr bekannt da ich sie nicht mehr finden kann.
Aber sowas von bekannt. Wenn du md5c.exe startest (aus meinem Beispiel), dann siehst du ja, dass es klappt.

Ich weiss, ich hätte dir zwei Teile anbieten sollten; einen Teil
- "Codiere Hash in die exe" und einen zweiten Teil
- "Prüfe den Hash in der exe".
Didaktisch wäre das so korrekt, aber es wäre weniger Magie :glaskugel: dabei.


Wir schreiben ja den Hash Wert aus ¦FILE EXE TEIL 1¦FILE EXE TEIL 2¦ in die neue exe (md5c.exe) an die Position von a.


Schau jetzt noch einmal in den Code an, den ich gepostet habe.

Die md5c.exe macht genau die gleichen Dinge, wie die ursprüngliche exe. Nur dass jetzt in der md5c.exe an Stelle von

a : RawByteString = 'In EXE nach diesem Text suchen..';
sowas drin steht:
a : RawByteString = 'a8910908bcd9012ba29208210120cd9e';


Der Delphi Quellcode von md5c.exe sähe also genau gleich aus wie bei der alten exe bis auf NEU
a : RawByteString = 'a8910908bcd9012ba29208210120cd9e';


Was macht das Programm md5c.exe?
Das neue Programm (md5c.exe) ist ja bis auf den neuen Wert von a absolut identisch mit dem alten. Es sucht also wieder nach dem Wert von a.
Dieses Mal sucht das Programm aber nicht nach 'In EXE nach diesem Text suchen..', sondern nach a='a8910908bcd9012ba29208210120cd9e'. Natürlich wird der Wert gefunden (wir lesen ja den Wert von a und suchen nun wieder genau gleich, wo a in der exe gespeichert ist). Wir kennen also nun die Position von a in der md5c.exe. Wir berechnen den Hash Wert h über den Rest der md5c.exe. Wir vergleichen h mit dem Wert in a. Fertig :thumb:.

a.def 3. Mai 2017 14:16

AW: DEC 5.2 String hashen?
 
Ach ich glaube ich lasse es jetzt auch sein und belasse es beim Hash am Ende der Datei.

Nur damit ihr wisst wo ich dran bin:
Mein RawByteString: _TESTTESTTEST_1234AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5678_TESTTESTTEST_

Mein Code
Delphi-Quellcode:
procedure TForm1.Button6Click(Sender: TObject);
var
 aByteStream, aByteStream2: TBytesStream;
 iPosRawByte: Int64;
 sHash: string;
begin
 aByteStream := TBytesStream.Create;
 try
  aByteStream.LoadFromFile(aFileName);
  iPosRawByte := Pos(RawByteString(a), RawByteString(aByteStream.Bytes));

  if iPosRawByte > 0 then
   begin
    iPosRawByte := iPosRawByte + 4;

    aByteStream2 := TBytesStream.Create;
    try
     aByteStream2.Write(aByteStream.Bytes[0], iPosRawByte - 1);
     aByteStream2.Write(aByteStream.Bytes[iPosRawByte + Length(a) - 9], aByteStream.Size - (iPosRawByte + (Length(a) - 9)));

     ShowMessage('"' + Trim(TEncoding.ANSI.GetString(aByteStream2.Bytes)) + '"');
     sHash := System.hash.THashSHA2.GetHashString(Trim(TEncoding.ANSI.GetString(aByteStream2.Bytes)));

     Move(AnsiString(sHash)[1], aByteStream.Bytes[iPosRawByte - 1], Length(a) - 8);
     aByteStream.SaveToFile(aFileName);
    finally
     aByteStream2.Free;
    end;
   end;
 finally
  aByteStream.Free;
 end;
end;

// Das mit dem -8 und -9 ist einfach nur rumexperimentiere da ich keine Ahnung hab wie es richtig geht.
In der Datei kommt an:
Zitat:

_TESTTESTTEST_12340e9b25c3947ef8f165223ac1ab447011cbf6196533678552da 4d19447552cbd5678_TESTTESTTEST_
Am Ende des Hashs steht cbd, korrekt wäre aber cbd1.

nahpets 3. Mai 2017 14:26

AW: DEC 5.2 String hashen?
 
Deine A-Reihe ist "nur" 63 A lang. Müssten das nicht 64 A sein?

a.def 3. Mai 2017 14:33

AW: DEC 5.2 String hashen?
 
Wenn du bei mir um die Ecke wohnen würdest, würde ich dir ein Bier ausgeben.
So dumm wie ich mich anstelle, so dumm bin ich wohl auch :wall:

Ist der Rest denn so in Ordnung? Speziell dieses Herumhantier mit +4, -9 und -8?

Hier mein erstes Ergebnis.

Delphi-Quellcode:
 iHashLengthInBytes = 64;
 aPrefixSuffixLen: Byte = 4;
 a: RawByteString = '1234';
 b: RawByteString = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
Datei einlesen, Hash bilden und in die Datei an die Stelle von RawByteString speichern
Delphi-Quellcode:
var
 aByteStream, aByteStream2: TBytesStream;
 iPosRawByte: Int64;
 sHash: string;
 c: RawByteString;
begin
 // This code adds a hash of the original file content to the destination files position of RawByteString

 aByteStream := TBytesStream.Create;
 try
  aByteStream.LoadFromFile(aFileName);

  c := a + b + a;
  iPosRawByte := Pos(RawByteString(c), RawByteString(aByteStream.Bytes));
  if iPosRawByte > 0 then
   begin
    iPosRawByte := iPosRawByte + Length(a);

    aByteStream2 := TBytesStream.Create;
    try
     aByteStream2.Write(aByteStream.Bytes[0], iPosRawByte - 1);
     aByteStream2.Write(aByteStream.Bytes[iPosRawByte + Length(c) - (aPrefixSuffixLen * 2 + 1)], aByteStream.Size - (iPosRawByte + (Length(c) - (aPrefixSuffixLen * 2 + 1))));
     sHash := System.Hash.THashSHA2.GetHashString(Trim(TEncoding.ANSI.GetString(aByteStream2.Bytes)));

     Move(AnsiString(sHash)[1], aByteStream.Bytes[iPosRawByte - 1], Length(c) - aPrefixSuffixLen * 2);
     aByteStream.SaveToFile(aFileName);
    finally
     aByteStream2.Free;
    end;
   end;
 finally
  aByteStream.Free;
 end;
end;
Datei einlesen und den Hash des Inhalts (ohne RawByteString) bilden
Delphi-Quellcode:
var
 aByteStream: TBytesStream;
 iPosRawByte, iPosEx: Int64;
 sTmp, sContent: string;
begin
 // This code reads the original file content and calculates the hash

 aByteStream := TBytesStream.Create;
 try
  aByteStream.LoadFromFile(aFileName);

  iPosRawByte := Pos(RawByteString(a), RawByteString(aByteStream.Bytes));
  if iPosRawByte > 0 then
   begin
    iPosRawByte := iPosRawByte + Length(a);
    iPosEx := Pos(RawByteString(a), RawByteString(aByteStream.Bytes), iPosRawByte + 1);

    // Hier bin ich auf String umgestiegen, da ich nicht weiß wie man Bytes aus TBytesStream löscht
    sTmp := Trim(TEncoding.ANSI.GetString(aByteStream.Bytes));
    sContent := Copy(sTmp, 0, iPosRawByte - 1);
    sContent := sContent + Copy(sTmp, iPosEx, Length(sTmp));

    ShowMessage(sContent);
   end;
 finally
  aByteStream.Free;
 end;
end;
Hash auslesen, der an Position des RawByteStrings gespeichert ist
Delphi-Quellcode:
var
 aByteStream: TBytesStream;
 iPosRawByte: Int64;
begin
 // This code reads the hash added at the position of RawByteString

 aByteStream := TBytesStream.Create;
 try
  aByteStream.LoadFromFile(aFileName);

  iPosRawByte := Pos(RawByteString(a), RawByteString(aByteStream.Bytes));
  if iPosRawByte > 0 then
   begin
    iPosRawByte := iPosRawByte + Length(a);

    aByteStream.Position := iPosRawByte - 1;
    aByteStream.Read(aByteStream.Bytes[0], iHashLengthInBytes);

    ShowMessage(Trim(TEncoding.ANSI.GetString(aByteStream.Bytes)));
   end;
 finally
  aByteStream.Free;
 end;
end;
Denkst du, das ist so "OK"? Ja, das ist viel Copy&Paste aber anders wüsste ich nicht wie es klappen soll.

Michael II 3. Mai 2017 17:13

AW: DEC 5.2 String hashen?
 
Hallo a.def

schau dir nach deinen nächsten Ferien dann nochmal an, wie du den Hash Wert ins File schreibst. Es ist echt keine Zauberei.

Wenn du den Hash Wert ans Ende des Files schreiben willst, dann ist es natürlich einfacher. [ Aber jemand der deine exe abändern will, sieht sofort, dass am Ende was steht und...]

So geht's [du musst den Code natürlich noch absichern - ich mach's mit Absicht nicht, damit du das Wesentliche siehst]:

Hash Wert ans Ende des Files schreiben:

Delphi-Quellcode:
procedure SchreibeHashWertAnFileEnde( filename : string );
var s : string;
    f : TStringStream;
begin
    f := TStringStream.Create;
   try
    f.LoadFromFile( filename );
    s := System.hash.THashMD5.GetHashString( f.ReadString( f.Size ));
    f.WriteString( s );
    f.SaveToFile( filename );
   finally
    f.Free;
   end;
end;

Hash Wert überprüfen:

Delphi-Quellcode:
function PruefeHashWert( filename : string ) : boolean;
var HashWertAmEndeDesFiles , HashWertVomFile : string;
    f : TStringStream;
begin
    f := TStringStream.Create;
   try
    f.LoadFromFile( filename );
    HashWertVomFile := System.hash.THashMD5.GetHashString( f.ReadString( f.Size-32 ));
    HashWertAmEndeDesFiles := f.ReadString( 32 );
   finally
    f.Free;
   end;
    Result := HashWertAmEndeDesFiles = HashWertVomFile;
end;

Beispiel:

Delphi-Quellcode:
procedure TForm79.Button1Click(Sender: TObject);
var fn : string;
begin
  fn := 'C:\Users\Michael\Documents\Embarcadero\Studio\Projekte\Win32\Debug\Project29.exe';
  SchreibeHashWertAnFileEnde( fn );
  if PruefeHashWert( fn ) then ShowMessage( 'OK' ) else showmessage('Error');
end;

Ich hoffe das hilft.

Gruss
M

a.def 3. Mai 2017 17:58

AW: DEC 5.2 String hashen?
 
Danke für die Hilfe. Ein paar Seiten vorher hatte ich meine Unit schon einmal vorgestellt die genau das auch macht :P Mein letztes Problem war nur das Setzen des Hashes mitten in die Datei.
Meine Primitive Lösung dafür ist

Delphi-Quellcode:
var
 aPrefixSuffixLen: Byte = 4;
 iHashLengthInBytes = 64;
 a: RawByteString = '1234';
 b: RawByteString = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';

function doHashAction(aHashAction: THashAction): string;
var
 aByteStream, aByteStream2: TBytesStream;
 iPosRawByte, iPosEx: Int64;
 sHash, sTmp, sContent: string;
 sTmpRawByte, c: RawByteString;
begin
 Result := '';

 if not FileExists(aFileName) then
  Exit;

 aByteStream := TBytesStream.Create;
 try
  aByteStream.LoadFromFile(aFileName);

  case aHashAction of
   THashAction.addHashToFile:
    begin
     c := a + b + a;
     sTmpRawByte := c;
    end
  else
   sTmpRawByte := a;
  end;

  iPosRawByte := Pos(RawByteString(sTmpRawByte), RawByteString(aByteStream.Bytes));
  if iPosRawByte > 0 then
   begin
    iPosRawByte := iPosRawByte + Length(a);

    case aHashAction of
     THashAction.addHashToFile:
      begin
       // This code adds a hash of the original file content to the destination files position of RawByteString
       // ==============================================================================================================================================
       aByteStream2 := TBytesStream.Create;
       try
        aByteStream2.Write(aByteStream.Bytes[0], iPosRawByte - 1);
        aByteStream2.Write(aByteStream.Bytes[iPosRawByte + Length(c) - (aPrefixSuffixLen * 2 + 1)], aByteStream.Size - (iPosRawByte + (Length(c) - (aPrefixSuffixLen * 2 + 1))));
        sHash := System.Hash.THashSHA2.GetHashString(Trim(TEncoding.ANSI.GetString(aByteStream2.Bytes)));

        Move(AnsiString(sHash)[1], aByteStream.Bytes[iPosRawByte - 1], Length(c) - aPrefixSuffixLen * 2);
        aByteStream.SaveToFile(aFileName);
       finally
        aByteStream2.Free;
       end;
       // ==============================================================================================================================================
      end;
     THashAction.getHashedFileContent:
      begin
       // This code reads the original file content and calculates the hash
       // ==============================================================================================================================================
       iPosEx := Pos(RawByteString(a), RawByteString(aByteStream.Bytes), iPosRawByte + 1);

       sTmp := Trim(TEncoding.ANSI.GetString(aByteStream.Bytes));
       sContent := Copy(sTmp, 0, iPosRawByte - 1);
       sContent := System.Hash.THashSHA2.GetHashString(sContent + Copy(sTmp, iPosEx, Length(sTmp)));

       Result := sContent;
       ShowMessage(Result);
       // ==============================================================================================================================================
      end;
     THashAction.getAddedHash:
      begin
       // This code reads the hash added at the position of RawByteString
       // ==============================================================================================================================================
       aByteStream.Position := iPosRawByte - 1;
       aByteStream.Read(aByteStream.Bytes[0], iHashLengthInBytes);

       Result := Trim(TEncoding.ANSI.GetString(aByteStream.Bytes, 0, iHashLengthInBytes));
       ShowMessage(Result);
       // ==============================================================================================================================================
      end;
     THashAction.doCompareHashes:
      begin
       // ==============================================================================================================================================
       ShowMessage(BoolToStr(doHashAction(THashAction.getHashedFileContent) = doHashAction(THashAction.getAddedHash), True));
       // ==============================================================================================================================================
      end;
    end;
   end;
 finally
  aByteStream.Free;
 end;
end;
Delphi-Quellcode:
 // Hash hinzufügen
 doHashAction(THashAction.addHashToFile);

 // Inhalt gehasht auslesen
 doHashAction(THashAction.getHashedFileContent);

 // Hinzugefügten Hash auslesen
 doHashAction(THashAction.getAddedHash);

 // Selftest ausführen
 doHashAction(THashAction.doCompareHashes);

Zacherl 3. Mai 2017 18:50

AW: DEC 5.2 String hashen?
 
Zitat:

Zitat von Michael II (Beitrag 1370078)
Wenn du den Hash Wert ans Ende des Files schreiben willst, dann ist es natürlich einfacher. [ Aber jemand der deine exe abändern will, sieht sofort, dass am Ende was steht und...]

Naja, letztlich ist es ja eh eine Spielerei. Wenn ich die Anwendung modifizieren will, finde ich auch mit Leichtigkeit die Stelle, an der auf Korrektheit des hinterlegten Hashs geprüft wird. Diese Bedingung negiere ich jetzt einfach im Assembly und schon ist der ganze Zauber ausgehebelt. Das ist in den meisten Fällen tatsächlich ein 1-Byte Patch, den selbst Anfänger auf diesem Gebiet innerhalb von ein paar Minuten vornehmen können.

a.def 3. Mai 2017 19:08

AW: DEC 5.2 String hashen?
 
Zitat:

Das ist in den meisten Fällen tatsächlich ein 1-Byte Patch, den selbst Anfänger auf diesem Gebiet innerhalb von ein paar Minuten vornehmen können.
Ich behaupte einfach mal, dass das aus der Luft gegriffen ist.

Ich mache diese Spielerei aus zwei Gründen:
1) ich bin dumm und will lernen
2) es gibt Webseiten die mein Programm geklaut haben und bieten es nun modifiziert selber an

Klar, ein Zertifikat wäre hier die Lösung denke ich. Aber das ist unglaublich teuer (Notar und blaa)

Michael II 3. Mai 2017 19:19

AW: DEC 5.2 String hashen?
 
Also Zacherl hat voll Recht.

Wenn du die Abfrage nicht verschleierst, dann ist man durch, wenn man wie hier die Bedingung "stimmt der Hashwert noch" einfach aushebelt.

Als kleine Knobelei könntest du ja deine Abfrage etwas verstecken und Zacherl dann mal deine exe übergeben ;-).

... und die fünf Minuten stoppen.

[ Und dein Programm sollte dann nicht einfach ausgeben "Ich wurde gehackt" sondern zum Beispiel wenn es ein Spiel ist - einfach schlechter mitspielen. ]

a.def 3. Mai 2017 19:32

AW: DEC 5.2 String hashen?
 
Eine Abfrage verschleiern? Höre ich zum ersten mal, dass das überhaupt möglich ist.

Was ich mir jetzt darunter vorstelle:
- mehrere Abfragen statt nur eine
- ein paar mal Strings herumschupsen
- spezielle Datentypen
?

Fritzew 3. Mai 2017 22:02

AW: DEC 5.2 String hashen?
 
Zitat:

Zitat von Michael II (Beitrag 1370088)
Also Zacherl hat voll Recht.

Wenn du die Abfrage nicht verschleierst, dann ist man durch, wenn man wie hier die Bedingung "stimmt der Hashwert noch" einfach aushebelt.

Als kleine Knobelei könntest du ja deine Abfrage etwas verstecken und Zacherl dann mal deine exe übergeben ;-).

... und die fünf Minuten stoppen.

[ Und dein Programm sollte dann nicht einfach ausgeben "Ich wurde gehackt" sondern zum Beispiel wenn es ein Spiel ist - einfach schlechter mitspielen. ]

Wenn ich deine vorherigen Antworten so anschaue:
Du lehnst Dich aber sehr weit aus dem Fenster, eine Exe Datei in einem Stringstream zu verarbeiten, grenzt meiner Meinung nach schon an masochismus.....

nahpets 3. Mai 2017 22:05

AW: DEC 5.2 String hashen?
 
Zitat:

Zitat von Fritzew (Beitrag 1370098)
Wenn ich deine vorherigen Antworten so anschaue:
Du lehnst Dich aber sehr weit aus dem Fenster, eine Exe Datei in einem Stringstream zu verarbeiten, grenzt meiner Meinung nach schon an masochismus.....

Mindestens ...

Filestream wäre da meine Wahl, aber binäre Daten als Zeichenfolge, eher nicht.

Fritzew 3. Mai 2017 22:12

AW: DEC 5.2 String hashen?
 
Zitat:

Filestream wäre da meine Wahl, aber binäre Daten als Zeichenfolge, eher nicht.
Danke.. Dachte schon ich bin allein :-)
ok nur auf die schnelle zum erzeugen einer Hash:

Delphi-Quellcode:
procedure tFileHasher.SchreibeHashWertAnFileEnde(filename: string);
const
  cChunkSize = 1024 * 1024; // Buffersize 1 MB

var
  f: TFileStream;
  lFileBytes: TBytes;
  lHashBytes: TBytes;
  lHasher: THashMD5;
begin
  f := TFileStream.Create(filename, fmOpenReadWrite);
  try
    setlength(lFileBytes, cChunkSize);
    lHasher.Reset;
    while f.ReadData(lFileBytes, cChunkSize) > 0  do
      lHasher.Update(lFileBytes);


    lHashBytes := lHasher.HashAsBytes;
    f.Seek(0, soFromEnd);
    f.WriteData(lHashBytes, Length(lHashBytes));
  finally
    f.Free;
  end;
end;

a.def 3. Mai 2017 22:42

AW: DEC 5.2 String hashen?
 
Ich bedanke mich für die Hilfe aller Beteiligten.

Ich habe mir jetzt eine schöne Unit zusammengebaut, welche (für mich) keine Wünsche offen lässt was die Funktionalität angeht.
Ach, Moment. Doch. Einen Wunsch äußert die Unit von sich aus. Er lautet in etwa ... "RÄUM MICH AUF!" :stupid:

Ich habe es so einfach gehalten wie möglich (mit eurer Hilfe).
Delphi-Quellcode:
// Selbsttest ausführen
THashFunctions_Selftest.doSelfTest(<Dateiname>);

// Hash einer Datei unterjubeln
THashFunctions_Selftest.doHashAction(<Dateiname>, <Option XY [Hash ans Ende oder mitten drin]>);

Zacherl 3. Mai 2017 23:44

AW: DEC 5.2 String hashen?
 
Zitat:

Zitat von a.def (Beitrag 1370085)
Zitat:

Das ist in den meisten Fällen tatsächlich ein 1-Byte Patch, den selbst Anfänger auf diesem Gebiet innerhalb von ein paar Minuten vornehmen können.
Ich behaupte einfach mal, dass das aus der Luft gegriffen ist.

Du darfst mir deine Testanwendung gerne zukommen lassen, dann setze ich mich morgen mal ran und patche dir die Abfrage raus, ohne den Hash anzufassen (gerne kann ich dir danach auch näher erklären, wie ich es gemacht habe). Das ist wirklich keine Hexerei, glaub mir.

Zitat:

Zitat von a.def (Beitrag 1370085)
Ich mache diese Spielerei aus zwei Gründen:
1) ich bin dumm und will lernen
2) es gibt Webseiten die mein Programm geklaut haben und bieten es nun modifiziert selber an

Erster Grund ist ja vollkommen legitim. Gegen den zweiten Umstand wird deine Spielerei hier absolut gar nicht helfen.

Allgemein kann ich dir zum Thema Anti-Cracking nur sagen, dass dein Programm mit entsprechendem Zeitaufwand wirklich IMMER gecrackt werden kann. Des Weiteren ist es vom Aufwand-/Nutzen Verhältnis her auch immer Blödsinn irgendeine eigene Lösung zu basteln. Nimm fertige Anwendungen wie VMProtect oder Themida, dann wird der Zeitaufwand für jeden 0815 Cracker auf jeden Fall zu hoch (kosten allerdings auch je nach Version eine Kleinigkeit).

a.def 4. Mai 2017 07:47

AW: DEC 5.2 String hashen?
 
Das lohnt sich alles nicht. Ist schließlich Freeware.

Frage: kann man eine simple Abfrage überhaupt "verstecken" oder schleiern oder geht das nicht?

nahpets 4. Mai 2017 10:02

AW: DEC 5.2 String hashen?
 
Habe ja auch mal 'ne MD5-Checksummenprüfung für meine Programme gebaut.
Und früher auch mit UPX gepackt.

Das kann man kombinieren.

Exe erstellen.
Mit UPX packen.
MD5-Checksumme (oder auch beliebige andere) hinten dran hängen.

Zur Prüfung wird ja die EXE-Datei gelesen, die Checksumme ermittelt und mit dem Ende der Datei verglichen.

Die Prüfroutine befindet sich nun aber in dem gepackten "Teil" und wird erst nach dem Entpacken beim Start der eigentlichen Exe ausgeführt.

Frage: Kann man die Prüfung dann auch "mal eben" wegpatchen?


'ne "somaleben"-Änderung der gepackten Exe kann ich mir jedenfalls nicht vorstellen.
Die Änderung müsste dann wohl eher zur Laufzeit im Arbeitsspeicher passieren.

Naja, und wenn man dann bei der Checksummenerstellung und -prüfung nicht einfach die gesammte Datei nimmt oder eine nicht handelsübliche Routine nimmt, kann man bei 'ner gepatchten Datei nicht unbedingt so mal eben eine korrekte Checksumme "hintendranhängen".

Klar, was man mit UPX packt, kann man auch mit UPX entpacken, dann passt aber die Checksumme nicht mehr und die Prüfung muss man dann aushebeln.

Wer will kann also schon dran, nur bis zu welchem Aufwand soll's getrieben werden?

Michael II 4. Mai 2017 11:12

AW: DEC 5.2 String hashen?
 
Zitat:

Danke.. Dachte schon ich bin allein
ok nur auf die schnelle zum erzeugen einer Hash:

Hast natürlich voll Recht Fritz - ein Hash welcher einer Bytefolge Bytes zuordnet muss auch bei Bytes bleiben. :thumb:

Zu deinem Code: Beim Lesen des letzten File Teils, solltest du den Hash nur über die effektiv gelesenen Bytes updaten. [Mit dem momentanen Code hast du cChunkSize - filesize mod cChunkSize Files mit gleichem Wert.]

Nebenbei: Wie jemand hier bereits erwähnt hat: GetHashBytesFromFile( filename ) ist in System.Hash bereits definiert.

Rollo62 4. Mai 2017 11:48

AW: DEC 5.2 String hashen?
 
+1 @Zacherl

Zitat:

Verschleiern
Ich würde also nicht
Delphi-Quellcode:
  if not CheckHashValid then
    Message('Ich wurde gehackt');
schreiben.

Sondern wenigstens
Delphi-Quellcode:
  if not CheckHashValid then
  begin
    Flag1 := False;
    Flag2 := False;
    Flag3 := False;
    ...
    Flagn := False;
  end;

...

//Nach unspezifischem Vorgang, z.B. Timer
if not Flag1 then
  TimedCrash1.Start( Time1 );


//Nach unspezifischem Vorgang, z.B. OnHidDeviceArrival
if not Flag2 then
  TimedCrash2.Start( Time2 );

....

Das hat nur zwei Probleme:
  • Darüber grinst Zacherl immer noch, aber aus 5 Minuten werden vielleicht 5h, und er geht vorher in die Mittagspause und hats am Nachmittag vergessen :stupid:
  • Deine Kunden kriegen unvermittelte, zufällige Crashes, das gibt u.U. schlechtes Image bei deinen "Usern".
    Ich habe es mal so gemacht das ich die CrashReason irgendwo vorher gespeichert haben, File, Registry.
    Und dann erst nach neuem Start etwas angezeigt habe.

Rollo

a.def 4. Mai 2017 11:53

AW: DEC 5.2 String hashen?
 
Was mir auch direkt aufgefallen ist:

Delphi-Quellcode:
  if not CheckHashValid then
    Message('Ich wurde gehackt');
Bei dieser Ausgabe wäre der Text "Ich wurde gehackt" sehr nah an der Position von CheckHashValid in der Datei gespeichert.
Hast du daher die Flags dazwischen geschrieben und den Timer, damit das weiter auseinander ist?

Den Text der MessageBox auszulagern, wäre auch eine tolle Idee. Dann kann man wenigstens nicht mehr direkt danach suchen.
Schöner wäre natürlich, wenn der Text der MessageBox irgendwie "verschlüsselt" in der Exe liegt und dieser dann entschlüsselt wird (behaupte ich als Laie einfach mal :stupid: )
Oder man könnte die Texte ja in eine Resourcedatei packen, die dann in die Exe eingebunden wird.

Rollo62 4. Mai 2017 11:58

AW: DEC 5.2 String hashen?
 
Exakt, das wäre mein Vorschlag.

Wenn es zeitlich und räumlich nicht so nah ist, und an zig verschiedenen Stellen,
wird es zumindest nicht so leicht zu hacken sein.

Der Hacker braucht ja events um zu checken wann geprüft wird und wann wans entschieden wird.
Ich würde die Prüfung daher niemals direkt bei Start machen.

Lass das Programm doch eine Weile laufen, und überleg dir mittendrin ein paar Scherze, oder speichere erst bei Programmende die neue Situation.

Ist natürlich witzlos wenn die App nach einer Minute Ihren Zweck erfüllt hat, aber für Daueranwendungen
kann man Hacker schon etwas beschäftigen.

Rollo

a.def 4. Mai 2017 13:30

AW: DEC 5.2 String hashen?
 
Zitat:

Lass das Programm doch eine Weile laufen, und überleg dir mittendrin ein paar Scherze, oder speichere erst bei Programmende die neue Situation.
Das ginge bei meinem Programm leider nicht. Es ist zwar eine Anwendung die dauernd läuft, aber sie erledigt zeitkritische Dinge. U.a. direkt bei Programmstart und Programmende.

Bin mit meiner aktuellen Lösung zufrieden. Werde die aber noch weiter ausbauen.

nahpets 4. Mai 2017 13:43

AW: DEC 5.2 String hashen?
 
Zitat:

Zitat von a.def (Beitrag 1370178)
Zitat:

Lass das Programm doch eine Weile laufen, und überleg dir mittendrin ein paar Scherze, oder speichere erst bei Programmende die neue Situation.
Das ginge bei meinem Programm leider nicht. Es ist zwar eine Anwendung die dauernd läuft, aber sie erledigt zeitkritische Dinge. U.a. direkt bei Programmstart und Programmende.

Ist das relevant, wenn es darum geht herauszufinden, ob da jemand was manipuliert hat?

Klar, bei 'ner zeitkritischen Anwendung darf die "Zwischendurchprüfung" das Programm nicht ins Stolpern bringen, aber wenn dann festgestellt wurde, dass da was manipuliert wurde, würd' ich mal sagen:

Korrekte Funktionalität ist nicht zwingend erforderlich, da das Programm ja sowieso per entsprechender Meldung beendet werden soll.

Beim Start prüfen, aber per Timer "verspätet" reagieren?

a.def 4. Mai 2017 14:04

AW: DEC 5.2 String hashen?
 
Zitat:

Beim Start prüfen, aber per Timer "verspätet" reagieren?
Wäre eventuell eine Möglichkeit.
Nur das würde dann meine schöne Unit wieder auseinanderreißen (ich suche einen weinenden Smiley. Gibt es wohl nicht) *Stell dir hier einen weinenden Smiley vor!*

Aktuell ist meine Unit umfangreich mit ein paar Einstellungsmöglichkeiten und ich brauche nur an einer einzigen Stelle etwas hinschreiben, damit der Selbsttest ausgeführt wird.
Mit dem Timer wären das dann ja schon 2 Stellen.

Quatsch! Wäre ja trotzdem nur eine Stelle! Einfach eine Timer-Instanz in der Unit selber erzeugen, starten und warten!

Ich sehe gerade, meine Unit hat Potential :hello:

Zacherl 4. Mai 2017 14:45

AW: DEC 5.2 String hashen?
 
Liste der Anhänge anzeigen (Anzahl: 4)
Zitat:

Zitat von nahpets (Beitrag 1370142)
Exe erstellen.
Mit UPX packen.
MD5-Checksumme (oder auch beliebige andere) hinten dran hängen.

Zitat:

Zitat von nahpets (Beitrag 1370142)
Frage: Kann man die Prüfung dann auch "mal eben" wegpatchen?

UPX bietet - wie du ja selbst erwähnst - von Haus aus eine Funktion an, mit der man Dateien wieder entpacken kann. Bietet also auch keinen größeren Schutz. Man patcht nicht den Hash, sondern die Prüfung ansich.

Zitat:

Zitat von nahpets (Beitrag 1370142)
Die Änderung müsste dann wohl eher zur Laufzeit im Arbeitsspeicher passieren.

Diese Möglichkeit gibt es natürlich auch noch jederzeit. Entweder per Loader, oder man modifiziert die IAT, um dem Programm eine extra DLL unterzumogeln. Lohnt sich bei Tools, welche auch erst zur Laufzeit (partiell) unpacked werden und so gute Hash-Checks besitzen, dass es vom Zeitaufwand schnell in die Stunden/Tage gehen könnte sie auszubauen.

Zitat:

Zitat von Rollo62 (Beitrag 1370164)
Wenn es zeitlich und räumlich nicht so nah ist, und an zig verschiedenen Stellen,
wird es zumindest nicht so leicht zu hacken sein.

Das ist in der Tat schonmal eine Stufe aufwändiger - besonders, wenn man eine dynamische Analyse per Debugger vornimmt.

Zitat:

Zitat von Rollo62 (Beitrag 1370164)
Der Hacker braucht ja events um zu checken wann geprüft wird und wann wans entschieden wird.

Exakt. Wobei viele Leute auch statische Analysen mit IDA vornehmen und dabei nicht auf irgendwelche Events angewiesen sind. Hierfür muss man allerdings in der Regel schon direkt mehr Zeit einplanen, um relevante Codestellen zu finden.

Zitat:

Zitat von a.def (Beitrag 1370184)
Aktuell ist meine Unit umfangreich mit ein paar Einstellungsmöglichkeiten und ich brauche nur an einer einzigen Stelle etwas hinschreiben, damit der Selbsttest ausgeführt wird.

Genau das ist aber leider absolut kein Vorteil. Hast du eine inline Funktion, welche du an mehreren Stellen - z.b. wie von Rollo beschrieben beim Auftreten "zufälliger" Events - einsetzt, dann muss ich auch diverse Stellen patchen und kann mir außerdem erstmal nie sicher sein, wirklich alle Vorkommen gefunden zu haben. Nagut, habe ich eine Stelle, kann ich nach der entsprechenden Code-Signatur im ganzen Programm suchen, aber im Optimalfall verwendest du mehrere komplett individuelle Funktionen.

Edit:
Ich habe mal noch ein paar Bilder angehangen, die die Vorgehensweise demonstrieren. Den String zu verschleiern würde in diesem Falle keinen Mehrwert erzeugen, da man stattdessen auch einen Breakpoint auf MSDN-Library durchsuchenMessageBoxW setzen könnte. Und selbst komplett ohne MessageBox kann man die Routine finden, welche den hinterlegten Hash aus der Datei ausliest, indem man einen BP auf MSDN-Library durchsuchenCreateFileW platziert.

a.def 4. Mai 2017 15:11

AW: DEC 5.2 String hashen?
 
Zitat:

aber im Optimalfall verwendest du mehrere komplett individuelle Funktionen.
Habe ich zum Glück schon. Mein Programm prüft einmal diese Hash-Sache und dann aber noch etwas komplett anderes.

Zitat:

indem man einen BP auf CreateFileW platziert.
Um CreateFileW kommt man vermutlich nicht herum richtig? (Datei anderweitig laden)

Allgemeine Frage an dich nahpets:
wirst du deine Methode weiterhin benutzen und einen Selbsttest durchführen?

Zacherl 4. Mai 2017 15:34

AW: DEC 5.2 String hashen?
 
Zitat:

Zitat von a.def (Beitrag 1370197)
Zitat:

indem man einen BP auf CreateFileW platziert.
Um CreateFileW kommt man vermutlich nicht herum richtig? (Datei anderweitig laden)

Würde mir zumindest auf Anhieb jetzt keine Möglichkeit einfallen, die nicht genauso einfach zu erkennen ist.

a.def 4. Mai 2017 15:38

AW: DEC 5.2 String hashen?
 
Zitat:

Würde mir zumindest auf Anhieb jetzt keine Möglichkeit einfallen, die nicht genauso einfach zu erkennen ist.
Ok. Zeugenvernehmung beendet. Urteil gesprochen: Zacherl hat das Zepter und kommt eh um alles rum :stupid:

himitsu 4. Mai 2017 16:06

AW: DEC 5.2 String hashen?
 
Die wichtigen Teile der EXE sind in den RAM gemappt, also kann man das auch im RAM hashen, anstatt die Datei.
Nur muß man hier erstmal alle Teile finden, da erstens die PE-Sektionen einzeln geladen werden, die Reallocationstabellen übershrieben werden und auch überall die Sprung-/Speicheradressen werden vom Windows gepatcht, wenn das Image im RAM verschoben wurde.

a.def 4. Mai 2017 16:10

AW: DEC 5.2 String hashen?
 
Klingt kompliziert und resultiert bestimmt wieder in keinerlei Mehrwert. Denn CreateFile muss man ja nicht suchen denke ich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:29 Uhr.
Seite 2 von 3     12 3      

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