![]() |
C# nach Delphi aber keine Ahnung wie?
Ich habe hier C# Code den ich gerne nach Delphi portieren möchte aber ich verstehe speziell die Array-Sachen nicht.
Könnt ihr mir helfen? Alles was unwichtig ist habe ich rausgenommen. Ist das in Delphi überhaupt möglich? Als Entschlüsselungsmechanik würde ich Wolfgang Erhardts Bibliothek nutzen.
Code:
So eine Datei kann beispielsweise so aussehen (nur ein Teilausschnitt)
byte[] bytes = LoadFileToMemory(file_to_load);
byte[] buffer = new byte[bytes.Length - 0x38]; byte[] keyBytes = new byte[] { 0x2a, 0x5f, 0xcb, 0x17, 0x91, 210, 0x2f, 0xb6, 2, 0x45, 0xb3, 0xd8, 0x36, 0x9e, 0xd0, 0xb2, 0xc2, 0x73, 0x71, 0x56, 0x3f, 0xbf, 0x1f, 60, 0x9e, 0xdf, 0x6b, 0x11, 130, 90, 0x5d, 10 }; byte[] destinationArray = new byte[0x10]; Array.Copy(bytes, 0x38, buffer, 0, buffer.Length); Array.Copy(bytes, 0x24, destinationArray, 0, destinationArray.Length); byte[] bytebuffer = AESDecrypt(buffer, keyBytes, destinationArray); string input = ""; using (MemoryStream stream = new MemoryStream(bytebuffer)) { using (InflaterInputStream stream2 = new InflaterInputStream(stream)) { using (StreamReader reader = new StreamReader(stream2)) { input = reader.ReadToEnd(); } } } private static byte[] AESDecrypt(byte[] _encryptedData, byte[] _keyBytes, byte[] _iv) { RijndaelManaged managed = new RijndaelManaged { Mode = CipherMode.CBC, Padding = PaddingMode.None, IV = _iv, KeySize = 0x80, BlockSize = 0x80, Key = _keyBytes }; return managed.CreateDecryptor().TransformFinalBlock(_encryptedData, 0, _encryptedData.Length); }
Code:
5363 7343 fe11 7934 9f07 6068 ad49 bd21
0dd4 16a5 3c76 c189 9860 6f90 19b3 85d0 3603 ee3a 1f22 7c57 eb4d 71f0 c369 cca8 |
AW: C# nach Delphi aber keine Ahnung wie?
Ich würde vorschlagen den C# Code weitestgehendes zu vergessen und nur die Funktionalität zu reproduzieren. Sprich:
Wenn Wolfgang Erhardts Lib die genannten AES Parameter unterstützt, solltest du diese verwenden können. `InflateInputStream` gehört meiner Recherche nach zu ZLib. Dafür gibt es in Delphi auch eine Lib. |
AW: C# nach Delphi aber keine Ahnung wie?
Ganz ehrlich? Schon bei Punkt 2 kann ich aussteigen :D
|
AW: C# nach Delphi aber keine Ahnung wie?
Habe grade kein Delphi hier, aber grob aus dem Kopf:
Delphi-Quellcode:
Zur Dekompression:
var
FS: TFileStream; Key: TBytes; begin FS := TFileStream.Create('...', fmOpenRead); try FS.Seek($24, soBeginning); SetLength(Key, 16); FS.Read(Key[0], Length(Key)); // ... finally FS.Free; end;
Delphi-Quellcode:
ZLibStream := TZDecompressionStream.Create(FS);
OutputStream.CopyFrom(ZLibStream, 0);
Delphi-Quellcode:
kann z.B. auch ein
OutputStream
Delphi-Quellcode:
, welcher die unkomprimierten Daten direkt auf der Platte ablegt.
TFileStream
|
AW: C# nach Delphi aber keine Ahnung wie?
Der Ehrlichkeit halber hier mal erbärmlicher Versuch von vorher. Mehr als da ist bei mir nicht drin
Delphi-Quellcode:
Nur damit ich das richtig verstehe. Ist der IV der Schlüssel zum Entschlüsseln?
iv := MemoryStream.Read(iv^, 36, 16);
|
AW: C# nach Delphi aber keine Ahnung wie?
Nee, der Schlüssel befindet sich in dem
Delphi-Quellcode:
Array aus deinem Beispiel. Der IV ist der Initialisierungsvektor für den AES-Cipher (verwendet man analog zu einem Salt, damit gleiche Daten selbst bei gleichem Schlüssel nicht den gleichen Cyphertext generieren). Man benötigt beides, um die Daten zu entschlüsseln.
keyBytes
|
AW: C# nach Delphi aber keine Ahnung wie?
Ach so. Wie würdest du die Keybytes denn deklarieren? Ich würde jetzt alles nach Dezimal umrechnen und daraus ein Array bauen.
Oder eben so
Delphi-Quellcode:
Ach herr je das wird mir zu kompliziert. Das mit den von Position 24 und 0x10 verstehe ich ja schon nicht weil ich den Originalcode eben nicht verstehe.
keyBytes: array [0 .. 31] of byte = ($2A, $5F, $CB, $17, $91, 210, $2F, $B6, 2, $45, $B3, $D8, $36, $9E, $D0, $B2, $C2, $73, $71, $56, $3F, $BF, $1F, 60, $9E, $DF, $6B, $11, 130,
90, $5D, 10); Wenn ich der Logik aber folge, dann übergebe ich dem AES-Decrypt den Stream von Position (0x38 bis (Streamlänge minus 0x38)) Ungefähr so
Delphi-Quellcode:
Im Original sieht das so aus
StreamToEncrypt.CopyFrom(FS, FS.Size - $38); // Den FileStream vom Anfang bis Ende minus $38
StreamToEncrypt.Position := $38; // An Position $38 gehen (die ersten und letzten $38 sind scheinbar unwichtig). Gibt aber einen stream-Schreibfehler als Fehlermeldung
Code:
byte[] buffer = new byte[bytes.Length - 0x38]; // ignoriere die letzten $38
Array.Copy(bytes, 0x38, buffer, 0, buffer.Length); // ignoriere auch die ersten $38 und kopiere alles von >38 und <ende-38 Aber AES verstehe ich noch viel weniger. Was da an parametern verlangt wird :pale: So weit bin ich aber weiter geht wirklich nicht
Delphi-Quellcode:
var
ctx: TAESContext; aesblck: TAESBlock; i: Integer; begin for i := 1 to 16 do aesblck[i - 1] := byte(Key[i]); ctx.IV := aesblck; AES_CBC_Init_Decr(Key, 256, aesblck, ctx); // warum 256 ?! AES_CBC_Decrypt(xyz, xyz, Length(xyz), ctx); |
AW: C# nach Delphi aber keine Ahnung wie?
Das ist doch gar nicht so schwer mit der Position.
Es gibt da eine Folge von Bytes (Stream) und ab der Position 24hex kommen 10hex Bytes und die repräsentieren den Initialisierungs-Vektor. Und ab der Position 38hex fangen die echten Daten an.
Delphi-Quellcode:
var
file_to_load: string; bytes, destinationArray, buffer: TArray<byte>; begin bytes := TFile.ReadAllBytes(file_to_load); SetLength(buffer,Length(bytes)-$38); SetLength(destinationArray,$10); TArray.Copy<Byte>(bytes,buffer,$38,0,Length(buffer)); TArray.Copy<Byte>(bytes,destinationArray,$24,0,$10); end; |
AW: C# nach Delphi aber keine Ahnung wie?
Aufbauend auf beider eurer Beispiel habe ich das hier erweitert.
Delphi-Quellcode:
Irgendwas mache ich aber noch falsch denn Res ist 0 Zeichen lang.
var
ctx: TAESContext; aesblck: TAESBlock; i: Integer; Res: RawByteString; begin // Das ist scheinbar notwendig ( https://www.delphipraxis.net/1208740-post21.html ) for i := 1 to 16 do aesblck[i - 1] := Byte(initVector[i]); ctx.IV := aesblck; AES_CBC_Init_Decr(initVector, 256, aesblck, ctx); AES_CBC_Decrypt(@EncryptedData[1], @Res[1], Length(EncryptedData), ctx); Im original gibt es eine Key- und BlockSize sowie Padding. Was auch immer die bedeuten. |
AW: C# nach Delphi aber keine Ahnung wie?
Zitat:
|
AW: C# nach Delphi aber keine Ahnung wie?
Der AESContext ist folgendermaßen deklariert
Delphi-Quellcode:
Die KeySize (0x80) sind vermutlich 128. Aber was auch immer die BlockSize ist und das Padding, das gibt es bei den WE's glaube ich nicht.
TAESContext = packed record
RK : TKeyArray; {Key (encr. or decr.) } IV : TAESBlock; {IV or CTR } buf : TAESBlock; {Work buffer } bLen : word; {Bytes used in buf } Rounds : word; {Number of rounds } KeyBits : word; {Number of bits in key } Decrypt : byte; {<>0 if decrypting key } Flag : byte; {Bit 1: Short block } IncProc : TIncProc; {Increment proc CTR-Mode} end; |
AW: C# nach Delphi aber keine Ahnung wie?
Delphi-Quellcode:
function AES_CBC_Init_Decr(const Key; KeyBits: word; const IV: TAESBlock; var ctx: TAESContext): integer;
Hier musst du sowohl Key, KeyBits (= 128) und IV übergeben. Den Context solltest du meiner Meinung nach nicht per Hand modifizieren. BlockSize sollte normalerweise automatisch gleich der KeySize sein bei CBC. Müsstest du einfach mal probieren, ob was Sinnvolles als Resultat bei rauskommt. Edit: Auch wenn es egal sein sollte. Nimm bitte `TBytes` oder `TArray<Byte>` als Typ für Binärdaten anstelle von `RawByteString`. Edit 2: Die Rückgabe der AES Funktionen geben dir auch einen Fehlercode. Eventuell den mal prüfen, wenn im Output Buffer komplett gar nichts rauskommt. |
AW: C# nach Delphi aber keine Ahnung wie?
Zitat:
Delphi-Quellcode:
for i := 1 to 16 do
aesblck[i - 1] := Byte(initVector[i]); ctx.IV := aesblck; AES_CBC_Init_Decr(initVector, 128, aesblck, ctx); AES_CBC_Decrypt(@EncryptedData[1], @Res[1], Length(EncryptedData), ctx); Zitat:
|
AW: C# nach Delphi aber keine Ahnung wie?
Vergleiche mal deinen Aufruf:
Zitat:
mit der Funktionsdefinition:
Delphi-Quellcode:
function AES_CBC_Init_Decr(const Key; KeyBits: word; const IV: TAESBlock; var ctx: TAESContext): integer;
Richtig wäre:
Delphi-Quellcode:
AES_CBC_Init_Decr(keyBytes, 128, aesblk, ctx);
|
AW: C# nach Delphi aber keine Ahnung wie?
Entweder bin ich zu dumm dafür oder Delphi kann das nichtm (was ich nicht glaube).
Delphi-Quellcode:
Ergebnis in einen TBytesStream schreiben, der dann von TZDecompressionStream auf die Festplatte geschrieben werden soll
AES_CBC_Init_Decr(keyBytes, 128, aesblck, ctx);
SetLength(Res, 4096); // irgendeine große Nummer weil ich keine Ahnung habe wie groß das Ergebnis sein soll? AES_CBC_Decrypt(@EncryptedData[1], @Res[1], length(EncryptedData), ctx);
Delphi-Quellcode:
Die Ausgabe ist immer leer. Ich habe vorher Res auf die Platte schreiben lassen ohne irgendetwas zu dekomprimieren. Da ist auch tatsächlich was drin. Sieht im Prinzip genau so aus wie die Eingangsdaten. Das muss dann noch dekomprimiert werden woran ich scheitere leider.
BytesStream := TBytesStream.Create;
try BytesStream.Write(Res, Length(Res)); ZLibStream := TZDecompressionStream.Create(BytesStream); try OutputStream := TFileStream.Create('dec.txt', fmCreate); try OutputStream.CopyFrom(ZLibStream, 0); finally OutputStream.Free; end; finally ZLibStream.Free; end; finally BytesStream.Free; end; Das hier ist mein letzter Versuch. Die zweite showmessage erzeugt schon einen data error. Jetzt gebe ich wohl oder übel auf.
Delphi-Quellcode:
BytesStream := TBytesStream.Create(Res);
try ShowMessage(BytesStream.Size.ToString); ZLibStream := TZDecompressionStream.Create(BytesStream); try ShowMessage(ZLibStream.Size.ToString); OutputStream := TFileStream.Create('dec.txt', fmCreate); try OutputStream.CopyFrom(ZLibStream, 0); finally OutputStream.Free; end; finally ZLibStream.Free; end; finally BytesStream.Free; end; |
AW: C# nach Delphi aber keine Ahnung wie?
Dein
Delphi-Quellcode:
macht vermutlich Murks, weil du immer noch die
BytesStream.Write(Res, Length(Res))
Delphi-Quellcode:
verwendest. Deren Indizierung beginnt bei 1 und nicht bei 0. Teste mal
RawByteStrings
Delphi-Quellcode:
. Bei dynamischen Arrays/Strings immer explizit den Index angeben, wenn du mit Zeigern arbeitest, sonst zeigt die Referenz nicht auf die Daten selbst, sondern das gemanagte Objekt.
Res[1]
|
AW: C# nach Delphi aber keine Ahnung wie?
Delphi-Quellcode:
Hier mal alles
Res: TBytes;
Kann das vielleicht daran liegen, weil ich Res auf Länge 4096 setze? Ich hab das einfach mal so groß gesetzt weil ich nicht weiß wieviel da rein muss.
Delphi-Quellcode:
Hier etwas sauberer und die Ausgabedatei ist trotzdem 0 byte groß. Das Problem scheint TZDecompressionStream zu sein. Oder meine 4096 feste Arraygröße.
procedure TFormMain.Button4Click(Sender: TObject);
const keyBytes: array [0 .. 31] of Byte = ($2A, $5F, $CB, $17, $91, 210, $2F, $B6, 2, $45, $B3, $D8, $36, $9E, $D0, $B2, $C2, $73, $71, $56, $3F, $BF, $1F, 60, $9E, $DF, $6B, $11, 130, 90, $5D, 10); var FS: TFileStream; Key, EncryptedData: TBytes; DecompressionStream, ZLibStream: TZDecompressionStream; OutputStream: TFileStream; ctx: TAESContext; aesblck: TAESBlock; i: Integer; Res: TBytes; BytesStream: TBytesStream; MemoryStream: TMemoryStream; var fileContent, initVector: TArray<Byte>; begin {* fileContent := TFile.ReadAllBytes('enc.txt'); SetLength(EncryptedData, length(fileContent) - $38); SetLength(initVector, $10); TArray.Copy<Byte>(fileContent, EncryptedData, $38, 0, length(EncryptedData)); TArray.Copy<Byte>(fileContent, initVector, $24, 0, $10); for i := 1 to 16 do aesblck[i - 1] := Byte(initVector[i]); ctx.IV := aesblck; AES_CBC_Init_Decr(keyBytes, 128, aesblck, ctx); SetLength(Res, 4096); AES_CBC_Decrypt(@EncryptedData[1], @Res[1], length(EncryptedData), ctx); Exit; *} FS := TFileStream.Create('enc.txt', fmOpenRead); try FS.Seek($24, soBeginning); SetLength(Key, 16); FS.Read(Key[0], length(Key)); FS.Seek($38, soBeginning); SetLength(EncryptedData, FS.Size - $38); FS.Read(EncryptedData[0], length(EncryptedData)); for i := 1 to 16 do aesblck[i - 1] := Byte(Key[i]); ctx.IV := aesblck; AES_CBC_Init_Decr(keyBytes, 128, aesblck, ctx); SetLength(Res, 4096); AES_CBC_Decrypt(@EncryptedData[1], @Res[1], length(EncryptedData), ctx); finally FS.Free; end; // Die Resultate beider Codeblöcke (oben der kommentierte und der danach) sind gleich BytesStream := TBytesStream.Create(Res); try ShowMessage(BytesStream.Size.ToString); ZLibStream := TZDecompressionStream.Create(BytesStream); try ShowMessage(ZLibStream.Size.ToString); OutputStream := TFileStream.Create('dec.txt', fmCreate); try OutputStream.CopyFrom(ZLibStream, 0); finally OutputStream.Free; end; finally ZLibStream.Free; end; finally BytesStream.Free; end; end; Aber selbst wenn ich Res auf FS.Size setze ist die Ausgabedatei leer.
Delphi-Quellcode:
MemoryStream := TMemoryStream.Create;
try MemoryStream.Write(Res[1], Length(Res)); ZLibStream := TZDecompressionStream.Create(MemoryStream); try OutputStream := TFileStream.Create('dec.txt', fmCreate); try OutputStream.CopyFrom(ZLibStream, 0); finally OutputStream.Free; end; finally ZLibStream.Free; end; finally MemoryStream.Free; end; |
AW: C# nach Delphi aber keine Ahnung wie?
Wenn du jetzt
Delphi-Quellcode:
verwendest, muss hier
TBytes
Delphi-Quellcode:
auf jeden Fall der Index schonmal jetzt 0 sein - sowohl bei
AES_CBC_Decrypt(@EncryptedData[1], @Res[1], length(EncryptedData), ctx);
Delphi-Quellcode:
, als auch bei
EncryptedData
Delphi-Quellcode:
.
Res
Die Zuweisung
Delphi-Quellcode:
ist überflüssig.
ctx.IV := aesblck
An dieser Stelle steht nicht der Key, sondern der IV!
Delphi-Quellcode:
Auch würde ich
FS.Seek($24, soBeginning);
SetLength(Key, 16); FS.Read(Key[0], length(Key));
Delphi-Quellcode:
definitiv nicht hardcoded auf 4096 Bytes festlegen. Vorher hattest du doch bereits einmal korrekt die Länge mit
Res
Delphi-Quellcode:
festgelegt. Wenn am Ende noch zufällige Daten stehen kann hier auch später die Dekompression evtl. fehlschlagen.
FS.Size - $38
Wenn es danach immer noch nicht klappt, kann es natürlich durchaus sein, dass das Entschlüsseln bereits fehlschlägt (es werden zwar Daten entschlüsselt, aber ob die Blöcke später korrekt sind weißt du nicht - könnte man aber prüfen, indem man dem C# Programm beibringt mal einen Zwischenstand zu printen). |
AW: C# nach Delphi aber keine Ahnung wie?
Kannst du mal deine Testdatei hochladen?
|
AW: C# nach Delphi aber keine Ahnung wie?
Ich bekomme jetzt zwar eine Ausgabe aber die sieht in etwa so aus
Code:
usw.
¶•tø–ÙØçèØ¡ŠœÀ!xéâ¬*†W³`Y´ÞÎüX™©é¾NÞ–ˆÕ*ºµàrC¶'bJTEÂ
Das Ur-alt-Originalprogramm ist übrigens in Delphi geschrieben. Dummerweise wurde das Repo gelöscht! Die Exe habe ich noch. Eine sekunde bitte ich muss mir gerade die Edits durchlesen. Zitat:
- Anhang gelöscht |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:01 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