Die “RoboAuth”-Challenge erzählt von einem Authentisierungssystem und übergibt uns ein Binary, das wir analysieren sollen um zwei Passwörter als Flagge zu erhalten. In guter Manier starten wir das fremde Programm natürlich erstmal als Administrator 😉
Wir werden zur Eingabe des ersten Passwortes aufgefordert. Jeder fehlerhafte Versuch führt direkt zum Abbruch der Programmausführung. Nutzen wir also den Immunity Debugger um das Programm zu untersuchen.
Dazu starten wir das Programm im Debugger und Pausieren sobald die Passwort abfrage erscheint. Nun geben wir das Passwort ein lassen das Binary so lange weiter arbeiten (continue until return) bis wir in das Code Segment des Programmes zurück kehren. Im Ergebnis landen wir direkt an der Position, wo das Passwort auf Korrektheit überprüft wird:
Wir erkennen deutlich den Aufruf der Funktion strcmp(), die das von uns eingegebene Wort mit dem korrekten Passwort vergleicht und im Erfolgsfall die Meldung “You passed level1” ausgibt. Werfen wir also einen Blick auf den Stack, an dem zu diesem Zeitpunkt die Übergabewerte für strcmp() liegen sollten.
Aha! Unsere Eingabe wird also mit der Zeichenkette “r0b0RUlez!” verglichen! Demnach muss es sich dabei um das erste Passwort handeln, dass zum Lösen der Challenge benötigt wird. Wir starten das Programm nochmals ein geben es mit folgendem Ergebnis ein:
Die erste Abfrage konnten wir damit tatsächlich überwinden! Nun verlangt das Programm nach dem zweiten Passwort. Auch dieses werden wir versuchen mit einem ähnlichen Vorgehen zu erhalten. Zunächst hängen wir uns mit dem Debugger an das Binary an (attach) während es auf das zweite Passwort wartet. Anschließend tippen wir irgendetwas ein und setzen die Ausführung bis zum Code Segment fort (continue until return).
Wir landen in einem Bereich, der offensichtlich vom Immunity Debugger nicht korrekt analysiert und in Opcodes umgewandelt werden kann. Das soll uns jedoch an dieser Stelle nicht stören und wir setzen die Abarbeitung für wenig Kommandos fort (step into). Kurze Zeit später erreichen wir einen Schleifenblock, der sehr interessant wirkt.
Hier werden einzelne Zeichen aus dem Speicher in das Register EAX geladen, mittels “XOR 0x02” verknüpft und anschließend mit den Zeichen unserer Eingabe (EDX) verglichen. Daher muss nach jedem Durchlauf jeweils ein korrektes Zeichen des Passwortes im Register EAX zu finden sein. Das prüfen wir direkt nach.
In EDX befindet sich der Wert 0x72, was dem Buchstaben “r” entspricht und damit dem ersten Zeichen des Wortes, das wir eingeben haben (“rup0rt”). In EAX befindet sich der Wert 0x77, was dem Buchstaben “w” entspricht und der erste Buchstabe des zweiten Passwortes sein sollte.
Um an die restlichen Zeichen zu gelangen, gaukeln wir dem Binary vor, dass wir eine korrektes Passwort eingegeben haben und nutzen den Debugger um EDX auf 0x77 zu ändern. Anschließend setzen wir einen Breakpoint auf die CMP Operation und lassen die Ausführung fortsetzen.
Bei jedem Halt am Breakpoint schreiben wir das Zeichen ab, ändern EDX auf EAX und setzen die Ausführung fort. Diese Schritte wiederholen wir, so lange bis die Schleife erfolgreich durchlaufen ist. Im Ergebnis konnten wir so folgende Buchstaben erlangen:
- 0x77 (w)
- 0x33 (3)
- 0x6c (l)
- 0x6c (l)
- 0x64 (d)
- 0x30 (0)
- 0x6e (n)
- 0x65 (e)
Das zweite Passwort lautet also “w3lld0ne”. Sicherheitshalber testen wir die beiden Passwörter nochmals mit folgendem Ergebnis.
Beide Passwörter sind korrekt! Nun müssen wir nur noch die Flagge aus beiden Wörtern zusammen setzen.
Die Lösung lautet “r0b0RUlez!_w3lld0ne“.