Diesmal geht es um die Transformation Challenge auf picoCTF.
In der Beschreibung erhälst du eine Datei namens ‚enc‘ und einen Code-Schnipsel: ''.join([chr((ord(flag[i]) << 8) + ord(flag[i + 1])) for i in range(0, len(flag), 2)])
.
Wenn man sich den Inhalt der Datei ‚enc‘ ansieht, bekommt man einige asiatisch anmutende Zeichen angezeigt:
$ cat enc
灩捯䍔䙻ㄶ形楴獟楮獴㌴摟潦弸弲㘶㠴挲ぽ
Mein erster Gedanke war, den Code-Schnipsel zu ignorieren und die Zeichen in Online-Übersetzer wie Google Translate oder Deepl zu schmeißen. Aber dabei kam nur heraus, dass die Zeichen anscheinend aus mehreren Sprachen stammen und keinen wirklichen Sinn ergeben. Das war nicht besonders hilfreich.
Also schauen wir uns mal den Code an. Es ist ein Python One-Liner der etwas mit der Flag macht. Da die Kategorie der Challenge Reverse Engineering ist, müssen wir also schauen, was der Code genau macht und die Funktionalität umkehren.
Dann nehmen wir den One-Liner mal etwas auseinander:
# out = ''.join([chr((ord(flag[i]) << 8) + ord(flag[i + 1])) for i in range(0, len(flag), 2)])
# is ziemlich das gleiche wie:
flag = 'secret flag'
out = ""
for i in range(0, len(flag), 2):
out += chr( (ord(flag[i]) << 8) + ord(flag[i + 1]) )
Also was macht das Script:
- Als erstes haben wir die geheime Flag, die in einer Variable flag gespeichert wird.
- Dann haben wir eine
for Schleife
die über jedes zweite der Flag iteriert, beginnend bei Position 0. - innerhalb der Schleife wird das Zeichen in die entsprechende ASCII Zahlenrepresentation konvertiert und die Zahl 8 Bits nach links verschoben, was einer Multiplikation mit 256 entspricht.
- dann wird das nächste Zeichen genommen und in die ASCII Zahlenrepresentation konvertiert
- Beide Zahlen werden addiert
- aus der resultierenden Zahl wird wieder ein Zeichen gemacht
- Das Zeichen wird der Ausgabe hinzugefügt
Nachdem wir jetzt wissen, was das Script macht, müssen wir nur Schritt für Schritt das Gegenteil davon machen.
encrypted_flag = "灩捯䍔䙻ㄶ形楴獟楮獴㌴摟潦弸弲㘶㠴挲ぽ"
flag = ""
for c in encrypted_flag:
number = ord(c)
second = number % 256
first = int( (number - second) / 256 )
flag += chr(first)+chr(second)
print(flag)
Was macht unser Script?
- Als erstes speichern wir die verschlüsselte Flag in
encrypted_flag
- Dann erstellen wir eine Variable für die entschlüsselte Flag
- Als nächstes iterieren wir mit einer
for Schleife
über jedes einzelne Zeichen derencrypted_flag
- Innerhalb der Schleife wandeln wir das Zeichen in die Nummern-Representation um
- Durch den Modulo-Operator erhalten wir den Rest der Division der Nummer durch 256 und speichern diesen als Nummer des jeweils zweiten Zeichens der Flag
- Um die Nummer des jeweils ersten Zeichens der Flag zu bekommen nehmen wir wieder die erste Ausgangsnummer, ziehen die eben ermittelte Nummer davon ab und teilen das Ergebnis durch 256. Da Python das Ergebnis der Division als Fließkommazahl zurück gibt, müssen wir diese noch in eine Ganzzahl umwandeln. Dies ist die Nummern-Representation des jeweils ersten Zeichens.
- Jetzt wandeln wir die beiden Zahlen in Ihre Zeichen-Representationen um und hängen beide Zeichen an unsere Flag-Variable an
- Als letzten Schritt lassen wir uns die komplette Flag ausgeben.
Glückwunsch. Du hast die nächste Flag.