Diese Challenge (TUX-BOMB) stellt eine EXE-Datei bereit und beauftragt uns, den Zugang zu erlangen, der bisher auf Grund fehlendem Benutzernamen und Schlüssel nicht möglich ist.
Nachdem mit dem Tool “file “festgestellt wurde, dass es sich um ein 32bit-Binary handelt, starte ich die entsprechende virtuelle Maschine und führe die EXE-Datei aus, um einen ersten Eindruck von deren Funktionsweise zu erlangen.
Dem ersten Eindruck nach scheint das Programm aus dem übergebenen Benutzernamen (“User 1”) eine “UserID” zu generieren, die hier 529 ist, im optimalen Fall aber wohl 666 (“AdminID”) sein sollte. Darüber hinaus wird der Benutzer als “unbekannt” eingestuft und der Produktschlüssel als “falsch” angesehen.
Da man so nicht weiter kommen wird, bleibt nur die Untersuchung im Debugger. Ich verwende hier den Immunity Debugger.
Bei Adresse 0x0040175E beginnt die Umrechnung des Benutzernamens in die Benutzer-ID, die ich mir zunächst nicht genauer ansehe. Anschließend (0x004017A7) wird überprüft, ob die Zahl größer oder gleich der Zahl 667 (0x29B) ist, um in diesem Fall (an anderer Stelle) ein Modulo mit 666 durchzuführen. Danach (0x004017B5) erfolgt die eigentliche Überprüfung, ob die Benutzer-ID gleich 666 (0x29A) ist, die dafür verantwortlich ist, den Admin-Status zuzuerkennen.
Da ich vorerst zu faul bin, einen Benutzernamen zu bestimmen, der der ID 666 (Admin) zugeordnet wird, setze ich einen Breakpoint auf die Adresse 0x004017B5 und weise an diese Stelle dem Register EBX die Zahl 0x29A (666) zu.
Dadurch geht das Programm zu diesem Zeitpunkt davon aus, dass ich den korrekten Benutzernamen für den Admin-Status eingegeben habe.
Anschließend bewege ich mich schrittweise (F7/F8) weiter durch das Programm und beobachte dessen Verhalten.
Bei Adresse 0x004017FA erfolgt ein Zeichenketten-Vergleich (strcmp), bei dem unser Schlüssel mit dem erwarteten “ProductKey” verglichen wird. Wir sehen, dass “s2” jedoch nicht einmal eine Folge lesbarer ASCii-Zeichen ist und in dieser Art von uns nicht hätte eingegeben werden können.
Die weitere Suche nach dem Entstehen dieses korrekten Produktschlüssels (bei Position EBP-98) führt zu den Adressen 0x004014F6 – 0x0040152C, die viel mit der Funktion rand() arbeiten und darauf schließen lassen, dass der korrekte Produktschlüssel bei jedem Programmaufruf neu generiert wird und von uns gar nicht berechnet werden kann!
Wir lassen die strcmp()-Funktion daher arbeiten (F8) und weisen dem Rückgabewert (EAX) bei Breakpoint 0x004017FF den Wert 0 zu, der bei übereinstimmenen Zeichenketten zurückgegeben worden wäre. Das Programm geht nun davon aus, dass wir auch den korrekten Produktschlüssel eingegeben haben.
Perfekt! Das Ergebnis sollte nun in der Datei “FLAG.pdf” zu finden sein! Wir lassen also das Programm ungebremst weiter laufen (F9) und öffnen die erstellte Datei.
Hmm, schade aber auch. Das Programm hat aufgepasst und uns beim Schummeln erwischt 😉 Es muss also irgendwo nach der Eingabe unseres Benutzernamens und Produktschlüssels noch eine weitere Überprüfung geben. Wir setzen unsere Suche daher nach der strcmp()-Funktion weiter fort.
Bei Position 0x0040183D werden wir fündig! Das Register EDI (bei mir derzeit 9) wird verglichen mit dem Wert bei Speicheradresse 0x0041A000 (bei mir derzeit 8) und davon abhängig ein Sprung bei Adresse 0x00401845 durchgeführt. Woher die Werte stammen, habe ich nicht weiter geprüft – da der Wert an Speicheradresse 0x0041A000 jedoch während des Programmflusses immer wieder statisch inkrementiert wird, gehe ich von einem weiteren “Verwirrspiel” des Challenge-Erstellers aus 😉
Um den Verlauf der Abfrage zu Beeinflussen setze ich einen Breakpoint bei Adresse 0x0040183D und ändere den Wert des Registers EDI auf 8 (den Wert bei Speicheradresse 0x0041A000). Anschließend lasse ich das Programm weiter laufen und überprüfe die PDF-Datei erneut.
Und dieses Mal erhalten wir auch intakte Daten. Jedoch scheinen sich die Fluxfingers hier einen Spass erlaubt zu haben, denn anstatt das Lösungswort auszugeben, müssen wir noch eine Rechenaufgabe lösen.
Da ich aber sehr rechenfaul bin, mir das Integral gar nicht erst ansehen möchte und nicht glaube, dass armen Menschen, wie mir, sehr sschwere Rechenaufgaben gestellt werden, vermute ich, dass die Berechnung des Intergrals 1, 2 oder 3 ergeben sollte. Die Aufsummierung der ASCii-Zeichen des Wortes “Fluxfingers” ergibt 1165, was mit 2 multipliziert und mit 993 subtrahiert, sicher nicht rein zufällig 1337 ergibt. 😉
Im Nachhinein (jetzt) habe ich mir jedoch überlegt, dass ein paar Rechenübungen mit Python sicher nicht schaden können, falls doch mal schwerere Aufgaben auf uns warten. Daher habe ich dieses Skript geschrieben:
#!/usr/bin/python from scipy import Inf from scipy.integrate import quad from math import exp, sqrt from hashlib import md5 # atoi("Fluxfingers") atoi = sum(map(ord, "Fluxfingers")) # integrate(e^-sqrt(u)) du, 0 --> inf integrate = int(quad(lambda u: exp(-sqrt(u)), 0, Inf)[0]) # atoi * integrate - 993 res = atoi * integrate - 993 print "md5(" + str(res) + ") = " + md5(str(res)).hexdigest()
Bei Ausführung dieses Skriptes erhalten wir:
rup0rt@lambda:~$ ./tux-bomb.py
md5(1337) = e48e13207341b6bffb7fb1622282247b
Die Lösung lautet “e48e13207341b6bffb7fb1622282247b“.