[SOLVED]Erstes SerialMe

Hallo,
ist mein erstes SerialMe. Den Schwierigkeitsgrad sollte im bereich "Fortgeschrittene Anfänger" liegen, denke bzw. hoffe das Anfänger etwas dabei lernen können.

SOLVED ist es wenn Serial zum Nick gefunden und eine Lösung geschrieben wurde - KeyGen ist zusatz.

Patchen ist nicht erwünscht.

Viel Spass

Oi!Alex


P.S. Für einen Usernamen gibt es viele richtige Serials (einfachhalber)


[SOLVED] bei Lesco
 
Lesco/0258357038
Lesco/ldgjegilej

Gutes CrackMe, ich poste später noch einen Lösungsweg.
Hier der entsprechende Code meines Keygens(Namen voher auf 10 Zeichen erweitern):
Code:
void generateKey(char *name,char *serial)
{
	int i,t;
	char n,s;
	for( i = 0; i < 10; ++i ) {
		n = (name[i] + 3*i) % 10;
		if( n > 4 ) 
			t = 14 - n;
		else
			t = 4 - n;
		serial[i] = 'd' + t; // 'd' kann man auch entsprechend ändern für andere Serials
	}
	serial[i] = 0;
}
Edit: Hier der Lösungsweg:
Per Suche nach referenzierten Text-Strings findet man den entsprechenden Code recht schnell:
Code:
004013A6  |> /83BD C4FDFFFF 09                     /CMP [LOCAL.143], 9
004013AD  |. |77 75                                |JA SHORT SerialMe.00401424
004013AF  |. |8B9D C4FDFFFF                        |MOV EBX, [LOCAL.143]
004013B5  |. |8D45 F8                              |LEA EAX, [LOCAL.2]
004013B8  |. |0385 C4FDFFFF                        |ADD EAX, [LOCAL.143]
004013BE  |. |2D 00010000                          |SUB EAX, 100
004013C3  |. |0FBE10                               |MOVSX EDX, BYTE PTR DS:[EAX]
004013C6  |. |8D45 F8                              |LEA EAX, [LOCAL.2]
004013C9  |. |0385 C4FDFFFF                        |ADD EAX, [LOCAL.143]
004013CF  |. |2D 00020000                          |SUB EAX, 200
004013D4  |. |0FBE00                               |MOVSX EAX, BYTE PTR DS:[EAX]
004013D7  |. |8D0C02                               |LEA ECX, DWORD PTR DS:[EDX+EAX]
004013DA  |. |8B95 C4FDFFFF                        |MOV EDX, [LOCAL.143]
004013E0  |. |89D0                                 |MOV EAX, EDX
004013E2  |. |01C0                                 |ADD EAX, EAX
004013E4  |. |01D0                                 |ADD EAX, EDX
004013E6  |. |8D0401                               |LEA EAX, DWORD PTR DS:[ECX+EAX]
004013E9  |. |8D48 BF                              |LEA ECX, DWORD PTR DS:[EAX-41]
004013EC  |. |B8 CDCCCCCC                          |MOV EAX, CCCCCCCD
004013F1  |. |F7E1                                 |MUL ECX
004013F3  |. |89D0                                 |MOV EAX, EDX
004013F5  |. |C1E8 03                              |SHR EAX, 3
004013F8  |. |89849D C8FDFFFF                      |MOV DWORD PTR SS:[EBP+EBX*4-238], EAX
004013FF  |. |8B949D C8FDFFFF                      |MOV EDX, DWORD PTR SS:[EBP+EBX*4-238]
00401406  |. |89D0                                 |MOV EAX, EDX
00401408  |. |C1E0 02                              |SHL EAX, 2
0040140B  |. |01D0                                 |ADD EAX, EDX
0040140D  |. |01C0                                 |ADD EAX, EAX
0040140F  |. |29C1                                 |SUB ECX, EAX
00401411  |. |89C8                                 |MOV EAX, ECX
00401413  |. |89849D C8FDFFFF                      |MOV DWORD PTR SS:[EBP+EBX*4-238], EAX
0040141A  |. |8D85 C4FDFFFF                        |LEA EAX, [LOCAL.143]
00401420  |. |FF00                                 |INC DWORD PTR DS:[EAX]
00401422  |.^\EB 82                                \JMP SHORT SerialMe.004013A6
Dieses Stück Code berechnet jeweils aus einem Namens- und Serialbuchstaben einen Wert und schreibt ihn in ein Array. Diese Schleife stellt dann fest, ob die Serial gültig ist:
Code:
00401438  |> /83BD C4FDFFFF 09                     /CMP [LOCAL.143], 9
0040143F  |. |77 22                                |JA SHORT SerialMe.00401463
00401441  |. |8B85 C4FDFFFF                        |MOV EAX, [LOCAL.143]
00401447  |. |83BC85 C8FDFFFF 09                   |CMP DWORD PTR SS:[EBP+EAX*4-238], 9
0040144F  |. |75 08                                |JNZ SHORT SerialMe.00401459
00401451  |. |8D85 C0FDFFFF                        |LEA EAX, [LOCAL.144]
00401457  |. |FF00                                 |INC DWORD PTR DS:[EAX]
00401459  |> |8D85 C4FDFFFF                        |LEA EAX, [LOCAL.143]
0040145F  |. |FF00                                 |INC DWORD PTR DS:[EAX]
00401461  |.^\EB D5                                \JMP SHORT SerialMe.00401438
Dieser Code geht das eben gefüllte Array durch und vergleicht jedes Element mit 9. Nun müssen wir den ersten Teil des Codes genauer untersuchen:
Code:
004013C3  |.  0FBE10                               |MOVSX EDX, BYTE PTR DS:[EAX]
004013C6  |.  8D45 F8                              |LEA EAX, [LOCAL.2]
004013C9  |.  0385 C4FDFFFF                        |ADD EAX, [LOCAL.143]
004013CF  |.  2D 00020000                          |SUB EAX, 200
004013D4  |.  0FBE00                               |MOVSX EAX, BYTE PTR DS:[EAX]
004013D7  |.  8D0C02                               |LEA ECX, DWORD PTR DS:[EDX+EAX]
004013DA  |.  8B95 C4FDFFFF                        |MOV EDX, [LOCAL.143]
004013E0  |.  89D0                                 |MOV EAX, EDX
004013E2  |.  01C0                                 |ADD EAX, EAX
004013E4  |.  01D0                                 |ADD EAX, EDX
004013E6  |.  8D0401                               |LEA EAX, DWORD PTR DS:[ECX+EAX]
004013E9  |.  8D48 BF                              |LEA ECX, DWORD PTR DS:[EAX-41]
Hier passiert eigentlich nicht viel, außer dass ein Buchstabe aus Name und Serial addiert werden und ein paar Berechnungen durchgeführt werden. Der Wert der am Ende in ecx steht setzt sich folgendermaßen zusammen:
n + s + 3*i = x
n := Name und s := Serial, wobei der Name sooft aneinandergehangen wird, bis er 10 Zeichen lang ist.
Weiter geht es hiermit:
Code:
004013EC  |.  B8 CDCCCCCC                          |MOV EAX, CCCCCCCD
004013F1  |.  F7E1                                 |MUL ECX
004013F3  |.  89D0                                 |MOV EAX, EDX
004013F5  |.  C1E8 03                              |SHR EAX, 3
004013F8  |.  89849D C8FDFFFF                      |MOV DWORD PTR SS:[EBP+EBX*4-238], EAX
Dies ist eine Compiler-Optimierung, die man vielleicht nicht auf den ersten Blick versteht: Im Grunde handelt es sich hierbei um Rechnung mit Festkommazahlen, um sich die Nutzung eines Div zu ersparen. Statt zu teilen wird einfach mit dem Kehrwert multipliziert. Dabei sind die unteren 32-Bit der gebrochene Teil und die oberen der ganzzahlige(edx:eax im Endergebnis). Es wird also zuerst mit 0:0xCCCCCCCD multipliziert. Dezimal ergibt das 0xCCCCCCCD/0x100000000 = 0.8 also 4/5. Darauf wird das Ergebnis um 3 Bits nach rechts verschoben, was einem Teilen durch 8 entspricht. Dadurch kommen auf eine Multiplikation mit 4/40, gekürzt 1/10. Dieser Code-Abschnitt teilt also x(s.o.) durch 10 und speichert das Resultat im Array und dies ohne die rechenintensive div/idiv-Anweisung zu nutzen.
Nun weiter:
Code:
004013FF  |.  8B949D C8FDFFFF                      |MOV EDX, DWORD PTR SS:[EBP+EBX*4-238]
00401406  |.  89D0                                 |MOV EAX, EDX
00401408  |.  C1E0 02                              |SHL EAX, 2
0040140B  |.  01D0                                 |ADD EAX, EDX
0040140D  |.  01C0                                 |ADD EAX, EAX
0040140F  |.  29C1                                 |SUB ECX, EAX
00401411  |.  89C8                                 |MOV EAX, ECX
00401413  |.  89849D C8FDFFFF                      |MOV DWORD PTR SS:[EBP+EBX*4-238], EAX
Dies verschiebt zuerst x um 2 Bits nach links(also *4). Darauf hin wird wieder x addiert und das Resultat verdoppelt. Zusammengefasst: 2(4x + x) = 10x. Es wird also das Ergebnis der Ganzzahldivision mal 10 gerechnet und von x subtrahiert.
Diese Differenz muss 9 betragen. Dabei handelt es sich nur um eine verschleierte Berechnung des Rest wenn man x durch 10 teilt. Zusammengefasst also:
Code:
(n[i] + s[i] + 3*i + 65) mod 10 = 9
Dies vereinfacht man zu:
(n[i] + s[i] + 3*i) mod 10 = 4
Für s[i] mod 10 muss daher folgendes gelten:
y = (n[i] + 3*i) mod 10
s[i] mod 10 = 14 - y für y > 4
und
s[i] mod 10 = 4 - y für y <= 4
Nun muss man dieses Ergebnis nurnoch zu einem Buchstaben für dessen Ascii-Wert a mod 10 = 0 gilt, addieren(z.B. 'd').
Wirklich ein gutes CrackMe, bei dem man auch ein wenig nachdenken muss(wenn man die Serial nicht einfach per BF berechnen lassen will)
 
Das es schnell geht dachte ich mir aber so schnell. (Habe nathürlich nichts anderes erwartet ;))
Danke für die Blumen und für die ausführliche Lösung Lesco!

Hoffe es besteht interesse auf weitere CrackMe',s mir schwirrt da noch ne idee rum...
 
Zurück
Oben