Reverse-Engineering mit radare2 - Teil 1
Nach langer Pause bin ich wieder zurück mit einem kleinen crackme. Ein Backup von dem crackme findet ihr unter:
http://www.nullday.de/img/IOLI-crackme.tar.gz
Als Werkzeug zum Reverse-Engineeren werde ich radare2 einsetzen. Also dann, Happy Hacking!
Level0
Schauen wir uns die binary erstmal an was sie tut:
Wie man sieht erwartet uns eine Passwort-Prompt. Schauen wir uns also mal standardmäßig als erstes die Strings an. Ist ja schließlich Level 1 ;-)
Und sie an wir haben das Passwort gefunden: 250382.
Level1
Diesesmal scheinen wir schon nicht so leichtes Spiel zu haben:
Schauen wir uns also mal den Disassembly an:
Was sofort auffällt ist der Vergleich an Offset 0x0804842b
. Wenn wir
das Level also in C-Code darstellen müssten, würde dieser ungefähr so
aussehen:
#include <stdio.h>
int main() {
int input;
printf("IOLI Crackme Level 0x01\n");
printf("Password: ");
scanf("%d", &input);
//hex(5274) == 0x149a
if(input == 5274) {
printf("Password OK\n");
} else {
printf("Invalid Password\n");
}
return 0;
}
Das Passwort lautet also 5274.
Level2
Im zweiten Level ist die Sache wieder etwas komplizierter. Dieses mal wird vor dem Vergleich wild umher gerechnet um die zu vergleichende Zahl etwas zu verschleiern. Der entscheidende Part des Disassembly ist also der Teil nach dem scanf-Aufruf.
Die Lösung ist also 0x52b24 in dezimaler Form: 338724.
Level3
Im dritten Level sehen wir ebenfalls wieder unser wildes umhergerechne. Der
Unterschied zu Level2 liegt allerdings in dem Funktions-Aufruf: call sym.test
.
Vor dem Aufruf werden via mov
unsere beiden Werte auf den Stack manövriert.
Schauen wir uns also mal sym.test
an:
Vor dem cmp
sehen wir das unsere Eingabe an der Stelle [ebp+0x8]
in das
Register eax
geschoben wird. Danach wird bei Offset 0x8048477
der Wert in
Register eax
, also unsere Eingabe, mit dem Wert 0x52b24 auf dem Stack
verglichen. Je nach dem wie das Ergebnis ausfällt wird gesprungen. Es hat sich
also nichts verändert. Das Passwort ist genau das Gleiche wie im Level zuvor.
Das einzige was sich verändert hat sind die Strings in der Binary. Diese wurden
diesesmal etwas obfuscated. Die Funktion sym.shift
scheint die
“verschlüsselten” Strings zu “entschlüsseln”. Schauen wir uns diese spaßeshalber
auch mal an:
Entscheidend am disassembly ist das sub al, 3
hier wird jeder Char im String
um den wert 0x3 dekrementiert. Die Funktion kann man sich so in C-Code
vorstellen:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void shift(char* string) {
size_t length = strlen(string);
size_t i;
for (i = 0; i < length; ++i) {
string[i] -= 0x3;
}
printf("%s\n", string);
}
int main() {
char string1[] = "Lqydolg_Sdvvzrug";
char string2[] = "Sdvvzrug_RN";
printf("%s = ", string1 );
shift(string1);
printf("%s = ", string2 );
shift(string2);
return 0;
}
Wenn man dies nun ausführt, sieht das Ergebnis so aus:
Den Rest gibt es dann im zweiten Teil. Stay tuned ;-)