![]() |
SSL/TLS-Kommunikation aus Indy 10 mit Wireshark entschlüsseln
Hallo!
Aus ursprünglich einer ![]() Wenn man mittels Indy mit externen Diensten Daten austauscht, hat man es heutzutage oftmals mit SSL/TLS-gesicherten Verbindungen zu tun. Gerade beim Debugging kann das ziemlich hinderlich sein, wenn der Server eine Anfrage abweist und man nur sehr umständlich heraus findet, woran es scheitert. Die meisten modernen Webbrowser unterstützen ![]() ![]() ![]() Nun wollte ich gerne mit eigenen HTTP-Clienten ebenso verfahren und eine solche ![]() ![]() Nachdem das aus der Welt geschafft war, ist das Erstellen einer NSS-Datei mit Indy eigentlich ganz einfach. Auf das Grundgerüst eines HTTPS-Clients gehe ich hier nicht weiter ein, dafür gibt es bereits ![]()
Delphi-Quellcode:
OnStatusInfoEx wird während einer Verbindung mehrfach aufgerufen. Deshalb prüfen wir den Verbindungsstatus mit
uses
IdSSLOpenSSL, IdSSLOpenSSLHeaders; const FNSSFilePath = 'C:\Log\SSLKEYLOG.LOG'; var FLastNSSLine: AnsiString; procedure TForm1.DoSSLStatusInfoEx(ASender: TObject; const AsslSocket: PSSL; const AWhere, Aret: Integer; const AType, AMsg: string); var LMasterByte, LRandomByte: Byte; LRandomChar: AnsiChar; LMasterSecret, LClientRandom, LLogLine: AnsiString; LMode: Word; LFileStream: TFileStream; LS3: Pssl3_state; begin if AWhere = SSL_CB_HANDSHAKE_DONE then begin LS3 := AsslSocket^.s3; Dec(PByte(LS3)); // <-- Bug in IdSSLOpenSSLHeaders.pas Deklaration write_mac_secret : array [0..EVP_MAX_MD_SIZE] of TIdAnsiChar; // muss [0..EVP_MAX_MD_SIZE - 1] lauten for LRandomChar in LS3.client_random do begin LRandomByte := Ord(LRandomChar); LClientRandom := LClientRandom + AnsiString(Format('%2.2x', [LRandomByte])); end; for LMasterByte in AsslSocket^.session^.master_key do begin LMasterSecret := LMasterSecret + AnsiString(Format('%2.2x', [LMasterByte])); end; LLogLine := 'CLIENT_RANDOM ' + LClientRandom + ' ' + LMasterSecret + sLineBreak; if LLogLine <> FLastNSSLine then begin LMode := (fmOpenReadWrite or fmShareDenyNone); if DirectoryExists(ExtractFilePath(FNSSFilePath)) then begin if not FileExists(FNSSFilePath) then begin LMode := fmCreate or LMode; end; LFileStream := TFileStream.Create(FNSSFilePath, LMode); try LFileStream.Position := LFileStream.Size; LFileStream.Write(LLogLine[1], Length(LLogLine)); Exit; finally FLastNSSLine := LLogLine; FreeAndNil(LFileStream); end; end; end; end; end;
Delphi-Quellcode:
auf den richtigen Moment. Anschließend erzeugen wir mittels zweier Schleifen aus den beiden Arrays
if AWhere = SSL_CB_HANDSHAKE_DONE
Delphi-Quellcode:
und
AsslSocket^.s3.client_random
Delphi-Quellcode:
zwei Strings und bauen daraus die neue Zeile für die NSS-Datei zusammen. Diese schaut dann in etwa so aus:
AsslSocket^.session^.master_key
Code:
Die SSL-Schlüssel werden jedoch nicht bei jeder weiteren HTTPS-Anfrage, die wir mit unserem Indy-Client absetzen, neu ausgehandelt sondern teilweise wiederverwendet. Damit wir also nicht mehrfach die selben NSS-Einträge schreiben, benutze ich hier einfach eine globale AnsiString-Variable
CLIENT_RANDOM 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
Delphi-Quellcode:
und prüfe ob diese mit der neuen Zeile identisch ist. Es ist übrigens durchaus wichtig, AnsiStrings zu verwenden und nicht etwa Strings. Dies würde der Compiler auch mit mehreren Implizite-Umwandlung-Warnungen quittieren.
FLastNSSLine
Die NSS-Datei wird mittels Pfadangabe (hier die globale Konstante
Delphi-Quellcode:
an einem bestimmten Platz gespeichert. Anstelle der Konstante sollte man sinnigerweise die Environment-Variable %SSLKEYLOGFILE% auswerten. Diese wird z.B. auch vom Firefox-Browser verwendet. Aber Vorsicht: Firefox und den eigenen Client nicht parallel laufen lassen, weil der Browser die Datei Write-Exclusive öffnet. Wir öffnen sie jedoch Shared-Read-Write, sodass wir zumindest keine anderen Anwendungen blockieren.
FNSSFilePath
Schließlich muss ![]() ![]() Der oben schon erwähnte Bug in Indy 10 befand sich in der IdSSLOpenSSLHeaders.pas und wurde am 3. Dezember 2018 in den Indy-Quellen behoben. Daher ist es erforderlich, die Zeile
Delphi-Quellcode:
zu löschen, wenn man den Indy-10-Quellenstand vom 3.12.2018 oder später verwendet. Delphi 10.3 Rio wurde jedoch noch mit dem fehlerhaften Stand ausgeliefert.
Dec(PByte(LS3));
Unterstützt wird aktuell SSLv1 bis SSLv3 sowie TLS 1.0 bis TLS 1.2. Zum jetzigen Zeitpunkt ist TLS 1.3 noch kein Thema, weil dafür größere Umbauten an Indy notwendig sind. So, das wars dann auch schon. Happy SSL/TLS-Hacking! ;-) Euer Cody |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:18 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