Salzwasser Sauger
Düm Di Dum Düm, trararara DIIING. Ich wollte schon immer einen eigenen Introsong haben! Wer komponiert einen für mich? *liebschau*
Mir war gestern langweilig, also nahm ich ein Programm ausseinander! Ich wusste, dass meine Motivation nicht sehr stark war, deswegen wollte ich heute nur ein einfaches Programm operieren. Ich weiß leider nicht mehr von wem der Tipp kam, aber mir fiel eine gewisse Warez Seite ein, die ihre Angebote auf FTP-Server hochluden. Dafür wird ein eigens konstruierter Leecher verwendet. Auf der Webseite (die übrigens genauso hässlich ist wie das Programm) lädt man sich eine verschlüsselte “Mirror-File” herunter, die nur ein paar KB groß ist. Mit dem Leecher kann dieser nun geöffnet werden.
Wisst ihr nun, was ich mit hässlich meinte?
Die verschlüsselten Dateien haben die Endung “.swl”, deswegen rede ich hier von SWL-Dateien. Wie jeder Reverser weiß, wird zuerst das Programm auf die übliche Art benutzt. Wir klicken unten auf “Open”, es öffnet sich ein Dialogfenster und wir wählen unsere SWL-Datei aus. Nun lädt das Programm diese Datei, und zeigt uns den Inhalt an, sodass wir mit einem Druck auf “Download” das Herunterladen starten können.
So weit, so gut. Ich knackse kurz meine Finger, feuchte meine Lippen an, hole tief Luft, schaue auf die Uhr, merke mir die Zeit, gehe kurz auf die Toilette, hol mir von der Küche eine Tüte Erdnussflips und freue mich auf den Abend.
Als aller erstes will ich schauen, ob das Programm gepackt ist. Dafür verwende ich PEiD. Den entdeckten Packer lasse ich mir durch ein Stück Software automatisch entfernen, denn mir fehlt echt die Lust auf manual unpacking (und das Einlesen in das Thema erst!).
Nun kann ich es ganz bequem in meinen Debugger OllyDbg laden und anfangen. Ich mache mir natürlich Gedanken, wie ich am besten vorgehen soll, um das Geheimnis des Dateiformates zu befreien. Ich werde hier mal die übliche Vorgehensweise von mir schildern:
- Dateiformat in einem Hexeditor ansehen um eine ungefähre Idee davon zu kriegen, wie die Datei strukturiert sein könnte.
- Herausfinden, an welcher Codestelle der Dateiinhalt eingelesen wird
- Herausfinden an welchem Punkt der komplette Inhalt entschlüsselt wurde
- Zwischen diesen beiden Stellen an interessant aussehenden Stellen Breakpoints setzen
- Etwas im Code tracen (während der Ausführung) um ein Gefühl dafür zu bekommen, was (ungefähr) geschieht
- Nach Mustern im Code suchen, die mir Aufschluss darüber geben, WIE entschlüsselt wird (Algorithmus, Schlüssel, etc.)
- Wichtige CALLs dokumentieren und benennen um ein besseres Verständnis für den Codeablauf zu haben. Alles was nach einem Schlüssel aussieht, in einer Text-Datei vormerken.
- Vermutung aufstellen, und bestätigen durch eine Scriptsprache freier Wahl. Beispielsweise Rijndael im ECB Modus auf die Datei anwenden, und schauen ob das Resultat gut aussieht.
- Wenn das allgemeine Verständnis für die Verschlüsslung da ist, einen Decrypter schreiben.
Der erste Schritt ist sehr einfach und ziemlich interessant! In einem Fall war es mir sogar mal möglich, allein durch das Ansehen des Dateiformates im Hexeditor herauszufinden wie es verschlüsselt wurde (ein einfacher XOR mit dem ersten Byte der Datei). Aber hier siehts nicht so aus:
Fast die vollständige Datei sieht verkrüppelt aus. Sieht nach Verschlüsselung aus (wer hätte das gedacht?). Allerdings befindet sich am Ende eine Webadresse und eine lange Zahl. Die sehen ziemlich wichtig aus! Eventuell ist es der Schlüssel (oder der Schlüssel wird damit generiert, oder es wird an die Seite versendet und dieser gibt uns den Key, oder es ist ein IV, oder oder oder ….). Wir müssen unbedingt solche Vermutungen aufstellen, damit uns später in dem Flut von Assemblercode Muster auffallen. Wenn wir die Webadresse aufrufen, wird uns eingeredet, es wäre ein 404. Schade, vermutlich wird diese Zahl per POST gesendet, oder so ähnlich.
Mehr ist aus dem alleinigen Ansehen des Dateiinhalt nicht zu entnehmen. Also gehen wir zu Schritt 2 über. Wir müssen herausfinden, an welcher Codestelle die Datei geöffnet wird. So wissen wir die ungefähre Stelle von der Entschlüsselung. Nun, betrachten wir noch einmal, was passiert wenn wir auf “Open” drücken. Es erscheint ein ein Öffnen-Dialog. Wieso versuchen wir nicht genau an dieser Stelle das Programm zu stoppen? Dieser Öffnen-Dialog scheint so ziemlich einzigartig zu sein.
Viele Windowsprogrammierer kennen bereits die API GetOpenFileName. Damit erstellt man dieses schöne Öffnendialog-Fenster das vielen Windows-Usern bekannt ist. Genau dort will ich ansetzen. Also tippe ich unten in die Commandbar von OllyDbg “bp GetOpenFileNameA”. Jetzt kann ich mir sicher sein, dass ich genau dann breake, wenn das Programm die Datei auswählt. Ich lass das Programm laufen, und genau so kommt es!
Schritt 3 ist nicht unbedingt Notwendig, aber dennoch hilfreich. Nach dem Öffnen der Datei zeigt das Programm eine MessageBox. Aha! Dort können wir auch breaken. “bp MessageBoxA”. Halleluja!
In Schritt 4 sollen wir nun interessante Stellen suchen. Dafür bediene ich mich der String-Suchfunktion von Ollydbg. Ich scrolle etwas rum, und finde süße Dinge wie “TDCP_twofish”. Das sieht nach der DCPCrypt Bibliothek für Delphi aus. Und “twofish” ist der Name des Algorithmus! Und von “SHA1″ ist auch die Rede. Eine Hashfunktion, auch schön! Also breake ich an den Stellen, wo diese Strings referenziert werden.
In Schritt 5 und Schritt 6 kann man Stundenlang verweilen. Es macht Spaß zu sehen, wie der Entwickler das Programm entworfen und programmiert hat. Man versteht langsam, wieso er jenes und anderes getan hat. Wenn man verfolgt, was mit den Strings passiert die eingelesen werden, dann erlangt man ziemlich schnell Erfolge. Einer meiner Tricks, um zu verfolgen was mit dem Dateiinhalt geschieht, ist es den Anfang der Datei so zu ändern, dass daraus ein String entsteht (ansonsten wäre es ein binärer Inhalt). Beispielsweise ändere ich die ersten Bytes zu “INHALT” und füge ein 00-Byte hinzu. Nun wird mir Ollydbg immer diesen String anzeigen, wenn irgendwo der Dateiinhalt referenziert wird. Ich trace also gemütlich durch den Code und knabbere ein paar Snacks.
Nach einiger Zeit bringe ich in Erfahrung, dass anscheinend ein Hash von etwas gebildet wird. Der Hash ist 20 Bytes lang. MD5 kann es nicht sein, denn dieses hätte eine Länge von 16 Bytes. Aus Erfahrung weiß ich, dass es sich bei 20 Bytes eigentlich immer um SHA handelt. Aus den Strings entnehme ich folgende (für viele merkwürdig erscheinende) Zeile:
ASCII “abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq”
Wenn man nach dem String googlet, wird man zahlreiche Indizien dafür finden, dass diese merkwürdige Anreihung von Buchstaben etwas mit SHA zu tun hat. Da kann ich euch aufklären: Viele der kryptografischen Bibliotheken verwenden einen sogenannten “SelfTest” um sich selbst auf Funktionalität zu testen. Dabei wird der Hash von einem bekannten String erstellt, und mit der (vorgefertigten) richtigen Lösung verglichen. Sind beide gleich, funktioniert die Bibliothek. Und um SHA zu testen, wird (unter anderem) der oben genannte String verwendet. Ich setze also einen Breakpoint in den CALL wo dieser String gelinkt ist, in guter Hoffnung, dass die Library sich bei der initialisierung automatisch selbst testet.
Da ich weiß, dass hier DCPCrypt verwendet wird, bediene ich mich einer sehr guten Methode, um alle wichtigen CALLs zu benennen. Somit wären wir also im siebten Schritt. Ich suche nach Mustern im Code! Zuerst lade ich mir die aktuellste Version dieser Kryptobibliothek herunter. Ich sehe mir die Datei DCPsha1.pas an, um nach einem einfach aussehenden Muster zu suchen. Ich finde die folgende Codezeile:
class function TDCP_sha1.GetHashSize: integer;
begin
Result:= 160;
end;
Das sieht doch sehr schön aus! Eine kurze Funktion, die auch noch mit einer ungewöhnlichen Zahl arbeitet. Diese Funktion gibt die Hashgröße in Bits an, aber das braucht uns eigentlich nicht interessieren (160 Bits / 8 ergibt 20 Bytes, die Größe unseres Hashes!). Nun wollen wir uns überlegen, wie wohl diese obige Funktion in Assembler aussehen könnte. Wenn wir absolut keinen Plan davon hätten, könnten wir uns die Delphi IDE installieren und ein Beispielprogramm mit dieser Library kompilieren (mit zusätzlichen Debuginformationen) und uns dann im Debugger das Resultat anschauen.
Ich kann mir aber bereits denken, wie es in Assembler aussieht. Und zwar so:
mov eax, 0A0
ret
So ungefähr. Also suche ich einfach in Olly nach dieser ersten Zeile. Rechtsklick->Search for->command->”mov eax, 0A0″. Olly wird fündig!
Weiter unten sieht man noch einen Teil des SelfTest-Strings. Wir sind also tatsächlich im Code von SHA. Wir drücken nun die Doppelpunkt-Taste auf der Tastatur, und benennen diesen CALL mit “TDCP_sha1.GetHashSize”. Der ein oder andere wird sich nun fragen “Wieso wollen wir unbedingt diese Codestelle wissen?”. Der Grund ist einfach: Die restlichen Funktionen der SHA-Klasse müssen (eigentlich) in der gleichen Reihenfolge wie im Code hier zu finden sein! Im Sourcecode von DCPCrypt folgt nun “TDCP_sha1.SelfTest”. Und “oh Wunder!”, in OllyDBG sehen wir auch direkt nach der GetHashSize Funktion den SelfTest String. Es stimmt also!
Wir machen einen Rechtsklick auf GetHashSize. Find Refernces to->Selected Command. Von den Resultaten wählen wir das Unmarkierte. Wir finden uns an so einer Stelle wieder:
Das sieht leer und düster aus. Aber da wir bereits eine dieser Stellen auf unsere GetHashSize-Methode zurückführen können, haben wir eine Ahnung wie wir den Rest der Funktionen benennen können. Wir wählen den nächsten “dd dump.*****” in der Liste, klicken Enter und hüpfen zum nächsten CALL. Es ist der SelfTest. Also benennen wir diesen. Dann gehen wir zum nächsten dd-Eintrag und bennen ihn mit “Init”. Denn dieser wäre die nächste Methode im Source-Code gewesen. Am Ende erhalten wir eine wunderbar dokumentierte Liste:
An wichtigen Stellen setze ich hier ein Breakpoint. “Init”, “Update” und “Final”. So kann ich verfolgen, aus welchem String ein Hash erzeugt wird.
Ich lasse das Programm nun laufen, wähle meine verschlüsselte SWL-Datei und breake bei einem der Methoden. Ich kann den Registern entnehmen, welche Daten/Parameter/Argumente der Methode mitgegeben wurden. So entnehme ich ihm die Information, dass aus dem folgenden String ein SHA1-Hash gebildet wird:
0×010203 + “PWsaltwaterPW” + 0×030201
Es scheint ein konstanter Wert zu sein. Ein Passwort, dass in die EXE eingebrannt wurde. Vermutlich wird der Hash als Key für die Verschlüsselung verwendet. Der Hash der sich ergibt, ist also immer konstant folgender Wert: EB EA FB E3 B6 7F 8E 98 19 EE C8 AC 7C 7A 1C CF 3A FB 4D BA
Das ist cool! Ich muss den Schlüssel also nicht selbst berechnen! (Trotzdem irgendwie langweilig und monoton ….). Ich schreibe mir diesen Key also auf, damit es mir nicht verloren geht, und ich die ganze Suche von vorne starten muss.
Plötzlich fällt mir nach einigen Minute auf, dass ich die SWL-Datei nicht mehr öffnen kann. Das Programm teilt mir mit, dass die Zeit abgelaufen sei! Wie bitte? Die Webseite des Leechers sagt mir folgendes:
Achtung:
SWL-Dateien können nur innerhalb von 60 Minuten nach Empfang geöffnet werden. Es spielt aber keine Rolle, wie lange sie dann geöffnet bleiben.
Aha! Da wir gerade eben herausgefunden haben, dass das Programm einen konstanten Key verwendet, kann ich mir sicher sein, dass nicht der Server uns einen temporären Key liefert, zum entschlüsseln dieser Datei. Es ist also der Leecher selbst, der Clientseitig entscheidet, dass wir die Datei nicht mehr verwenden dürfen. Und genau dafür war wohl die URL und die Nummer am Ende der SWL-Datei. Ich patche also kurz die Codestelle, sodass ich alle SWL-Dateien unendlich lange verwenden kann. Das wäre schonmal aus der Welt!
Wenn wir uns an die String-Funde von gerade erinnern: Es war die Rede von Twofish! Also lassen wir unsere Vermutung von dem Krypto-ANALyzer in PEiD bestätigen. Und dieser ist genau unserer Meinung: Es wird der Twofish-Algorithmus verwendet. Wir gehen genauso vor, wie gerade. Wir suchen nach Mustern. Ich öffne ein paar SourceCodes von DCPCrypt, und suche nach schönen Zeilen, die einzigartig sind.
class function TDCP_blockcipher64.GetBlockSize: integer;
begin
Result:= 64;
end;
Also suche ich nach:
mov eax, 080
retn
und ich lande genau an der richtigen Codestelle. Nun gehe ich genauso vor, wie bei SHA1. Und am Ende habe ich so einiges dokumentiert:
Ich breake natürlich an allen interessanten Stellen (so gut wie allen oben genannten). Und ich finde heraus, dass DecryptCBC aufgerufen wird. Somit weiß ich mit sehr hoher Wahrscheinlichkeit dass der CBC-Modus benutzt wird. Nachdem ich bei “Init” und “InitStr” breake (leider auf dem Bild nicht zu sehen), sehe ich im EDX Register den Schlüssel. Und, wie hätte man es sonst erwartet, ist es der Hash den wir oben berechnet hatten!
Schritt 8 => Unsere Vermutung ist also, dass der Dateiinhalt per Twofish entschlüsselt wird. Und der Key ist der konstante Hash, den wir oben herausgefunden hatten. Nun holen wir uns irgendeine Scriptsprache, für die es eine fertige Twofish-Bibliothek gibt. Leider hat es das weder Python (jedenfalls keine funktionierende) noch Ruby. Aber PHP hat mcrypt. Also greiffe ich auf PHP! Ich hatte keine Lust auf PHP, und die Einarbeitung in MCrypt, also habe ich mir schnell von den Beispielcodes etwas zusammenkopiert. Den Decrypter braucht ja sowieso niemand.
Ich finde nur noch kurz heraus, wie die Daten im Plaintext strukturiert sind, damit man sie auslesen kann (alle Daten sind per 0×01 voneinander getrennt. Ganz easy!) und es entsteht (Schritt 9) ein Decrypter:
Schachmatt! SWL wurde geknackt!
Ein Teil dieses Blogeintrages wurde auf der Toilette verfasst. Normale Menschen lesen Zeitung auf dem Klo. Geeks bloggen. Vermutlich einer der Gründe wieso ich so viel Scheisse auf dem Blog produziere (Ah, ich liebe Wortspiele!)
If you enjoyed this article please consider staying updated via RSS. Links to your own social media pages could be added here.
This entry was posted on Sunday, January 17th, 2010 at 15:42 and is filed under IT Security, Reverse Engineering. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
January 17th, 2010 at 16:32
Ein Teil dieses Blogeintrages wurde auf der Toilette verfasst. Normale Menschen lesen Zeitung auf dem Klo. Geeks bloggen. Vermutlich einer der Gründe wieso ich so viel Scheisse auf dem Blog produziere (Ah, ich liebe Wortspiele!)
Wie wahr !
January 17th, 2010 at 16:39
Mein WLan auf dem Klo ist ziemlich bekackt, deswegen kann ich leider nur in der Küche, meinem Bett und von meinem Schreibtisch aus bloggen…
Ähja, b2t. Sehr nice gemacht, scheint ja für dich kein allzu schwerer Fall gewesen zu sein. Wie lange hast du nun komplett dafür gebraucht?
January 17th, 2010 at 16:51
Hehe. Das sah hier total lustig aus, als ich noch kein WLAN hatte. Man konnte dem LAN-Kabel folgen, um zu wissen wo ich gerade stecke. Umso peinlicher wurde es, wenn es auf dem Klo endete
Für dieses Target habe ich etwa 3 bis 4 Stunden gebraucht
January 17th, 2010 at 19:20
lol hast ja doch das Programm auseinander genommen, was ich dir mal gesagt hatte^^ gz du geek^^
“Für dieses Target habe ich etwa 3 bis 4 Stunden gebraucht ”
Man das muss aber eine RIESEN Wurst gewesen sein
January 17th, 2010 at 23:48
Interessanter Artikel, schön detailiert vor allem, ich mag dein Blog, werde hier öfters lesen *g*
Mfg,
January 21st, 2010 at 18:50
WoW … ich bin immer wieder erstaunt wie du das zustande bringst.
Hast mein Respekt Und immer schön weiter machen !
Du wirst mal ein ganz großer !
January 26th, 2010 at 16:22
http://***.byethost8.com/
unten auf movies klicken
//sorry, musste den Link zensieren. Keine Warezverlinkung; ich hoste ja in Deutschland.
February 15th, 2010 at 10:37
Woow. ALso jetzt mal ganz Ehrlich, ich hab kein bisschen ahnung, von dem was hier so alles steht Echt krass was du so durchziehst mein lieber. Aber ich denke mal das ist deine Leidenschaft, von daher .. mach weiter soo
Du wirst auf jeden fall erfolg in deinem Leben haben. & berühmt sein Wer weiß ?
Ich bin stolz auf dich mein cousin’chen Du bist ein wundervoller mensch Ich hab dich megaaa doll lieb
Naja eines Tages werde ich wohl checken wovon du hier so alles schreibst Schließlich liegen meine Interessen ja auch an Informatik Aber ich gehe eher in den Medienbereich anstatt IT oder soo Vielleicht werde ich ja deine Nachfolgerin sein Wer weiß, wer weiß
Na dann. Bis dann
<33'
February 25th, 2011 at 23:24
[...] bereits an der GUI des Programmes entlarven. Vielleicht erinnert sich noch jemand an das hier. Jedenfalls, ist dieses Programm genauso [...]