Reverse Engineering Dongle geschützte Software
Ich war jung, das Internet hat gerade erst angefangen und wir konnten jede Menge Software kostenlos bekommen. Es war kostenlos, weil jemand da draußen „nett“ genug war, um das zu knacken / patchen.exe-Datei.
Ich habe „kind“ zwischen Anführungszeichen gesetzt, weil dies die Ansicht war, die ich als Kind hatte. Jetzt bin ich Softwareentwickler und weiß, wie viel Aufwand es braucht, um Software zu erstellen. Also bitte, laden Sie keine geknackte Software herunter. Unterstützen Sie den Entwickler und kaufen Sie eine Lizenz!
Wenn ich einen solchen Riss anwende und die exe patche, wollte ich immer wissen, wie man so etwas macht. Es stellt sich heraus, dass Sie Assembler verstehen müssen, eine Maschinensprache, die nur Ihre CPU versteht (und einige andere Nerds da draußen). Da es zu schwierig war, kam ich nie dazu, es zu lernen. Bis vor kurzem (wie 20 Jahre später 😊).
Vor einem Jahr kaufte ich Software (mit einer Lizenz!), die einen USB-Dongle benötigt, um zu funktionieren. Es ist wirklich umständlich, diesen Dongle immer bei sich zu haben. Vor allem, wenn Sie unterwegs sind. Also suchte ich nach Wegen, um es zu umgehen. Das erste, was mir aufgefallen ist, war dieser Schlüsselemulator namens MultiKey. Es speichert den Speicher Ihres Dongles in Ihrer Registrierung und emuliert dann Ihren Dongle, indem es aus Ihrer Registrierung liest. Das funktionierte OK, bis ich es unter Windows 10 ausführen wollte. Anscheinend ist Microsoft kein so großer Fan von MultiKey. In Wirklichkeit ist es kein großer Fan von unsignierten Treibern und MultiKey verwendet einen unsignierten Treiber. Also brauchte ich eine andere Lösung. Zeit, in das Ding namens Assembler-Code einzutauchen!
Ich wusste immer, dass es ein Werkzeug für Reverse Engineering gibt, genannt IDA. Es ist in der Lage, Ihre zu dekompilieren.exe-Datei und zeigen, was los ist. Leider ist die Schnittstelle wirklich schwer zu verstehen. Ich wusste auch von OllyDbg. Es ist ein Debugger. Mit einem Debugger können Sie den Assembler-Code durchlaufen, während das Programm ausgeführt wird! Das heißt, wenn Sie beispielsweise die Taschenrechneranwendung debuggen würden, könnten Sie tatsächlich sehen, wie sie einen Tastendruck ausführt, die Berechnung durchführt und das Ergebnis auf dem Bildschirm anzeigt. Hölle, Sie können sogar pausieren und seinen Speicher ändern, so dass der Rechner 5 zurückgibt, wenn Sie fragen, was 2 + 2 ist!
Aber ich bin nicht hier, um Kalkül zu ändern (obwohl das cool wäre). Ich will frei sein vom Dongle. Also habe ich meine App mit OllyDbg geöffnet.
Das war wirklich überwältigend. Ich hatte keine Ahnung, was all diese Codes bedeuteten. Geschweige denn wissen, wo ich anfangen soll. Also ging ich zurück zum Zeichenbrett. Es stellt sich heraus, dass es etwas namens RetDec gibt, einen Decompiler, der versucht, C-Code aus Maschinencode zu machen. Ich habe einige Zeit gebraucht, um es einzurichten und die Dekompilierung durchzuführen, aber der Aufwand hat sich gelohnt. Das Ergebnis war riesig .c-Datei, über 2 Millionen Zeilen Code mit semi-lesbaren Code.
Tatsächlich konnte ich den Code, der die Bytes des Dongles liest, ziemlich einfach finden:
Mit diesen Informationen kehrte ich zu meinem Debugger zurück. In der Zwischenzeit habe ich herausgefunden, dass OllyDbg wirklich alt ist (aus dem Jahr 2000) und seit 2013 nicht mehr aktualisiert wurde. Also fand ich diesen neuen, verbesserten Debugger namens x64dbg. Es ist Open Source und hat eine große Community von Entwicklern, die daran arbeiten.
Maschinensprache lesen
In Maschinensprache hat jede Anweisung eine Speicheradresse. Also mit den Adressen im RetDec-Code gefunden, Ich wandte mich an x64dbg und siehe da, der Code, der den Dongle ausliest:
Im Assemblercode werden die Argumente der Funktion mit dem Stapelzeiger esp in den Speicher geladen. In unserem Code geschieht dies kurz vor dem Aufruf der Funktion. (die 3 mov-Anweisungen geben an, dass der Aufruf 3 Argumente benötigt). Nach dem Aufruf wird unser Stapelzeiger zurückgesetzt und geprüft (Test), ob der Aufruf der Funktion erfolgreich war. Wenn nicht, sehen wir, dass der Code einen Sprung macht (jne). Dieser Sprung zeigt auf einen Code, der angibt, dass der Dongle nicht vorhanden ist.
Wie Sie sehen können, gibt es einen Aufruf an eine bestimmte Funktion, um den Dongle auszulesen. Ich habe im Referenzhandbuch nachgeschlagen, um herauszufinden, was diese Funktion tut:
Die Funktion liest 2 Byte Speicher (ein Wort) vom Dongle. Wie vermutet, benötigt die Funktion 3 Argumente, wobei das letzte Argument ein Zeiger auf 2 Bytes ist, der einige Daten vom Dongle enthält.
Im Assemblercode werden die Argumente in umgekehrter Reihenfolge geladen. Das Übergeben des letzten Arguments ist dieses:
Das letzte Argument zeigt auf esi, was bedeutet, dass die Daten vom Dongle an der Speicheradresse gespeichert werden, auf die esi zeigt.
In der Tat können wir das Ergebnis im Speicher sehen, wenn wir kurz nach dem Anruf pausieren:
0x74. Das wird vom Dongle ausgelesen und im Speicher des Hauptprogramms gespeichert.
Um diesen Aufruf zu überspringen, muss ich nur 0x74 in den Speicher schreiben, auf den esi zeigt. Dies ist so einfach wie das Ersetzen der 7 Zeilen oben durch:
Wie Sie sehen, habe ich auch den Rest der Assembler-Anweisungen notiert, einschließlich des Tests, ob der Funktionsaufruf gültig war. Dies bedeutet, dass der Sprung nicht gemacht wird und das Programm ohne Prüfung weiterarbeitet.
Nachdem ich alle Anrufe mit dem Dongle gepatcht hatte, habe ich den neuen gespeichert.exe. Ich zog den Dongle, lief meine Gewohnheit .exe und zu meinem eigenen Erstaunen hat es funktioniert! Ich hatte erfolgreich ein Stück Software geknackt.
Eine andere Sache, die ich von meiner Bucket List gekreuzt habe 😊
Ps: Die meisten Dinge wurden verschleiert, wie 0x74 und der Name der App. Dies soll den hart arbeitenden Entwicklern, die diese Software erstellt haben, in keiner Weise schaden. Außerdem hatte ich großes Glück, dass der Dongle nur Bytes zurückgab und keine eigene Verschlüsselung durchführte.