Starcraft – Let’s CrackIt

Es wird wieder einmal Zeit für einen neuen Artikel. Diesmal habe ich mir ein älteres Spiel ausgesucht und es ist wieder ein Spiel aus dem Hause Blizzard. Heute geht es um Starcraft. Ich versuche herauszufinden, wie der Serial überprüft wird und auf dieser Grundlage versuche ich einen Keygen zu Programmieren. Da ich es im Original habe, ahne ich schon das es vielleicht ein wenig einfacher wird, als die letzten Sachen die ich gecrackt habe. Dies liegt daran dass der Serial nur aus Nummern besteht. Also auf geht es, in eine neue Runde der Zerstörung.

Zunächst einmal habe ich mir mit ImgBurn eine ISO von Starcraft gemacht. Nachdem die ISO fertig erstellt worden ist, habe ich mir einmal die Dateien auf der CD genauer angeschaut. Wieder der übliche Aufbau! Eine Setup.exe die wahrscheinlich nur die Install.exe startet. Also habe ich mir gleich die Install.exe gestartet und geschaut was denn die Installation so macht.

Der Anfang

OK! So sieht das also aus. Nur noch einmal mit PEid analysieren und siehe da:

Es handelt sich um "Microsoft Visual C++ 5.0 [Overlay]". Also können wir gleich mit OllyDbg heransetzen und den Kram debuggen. Schnell nach allen intermodular Calls geschaut und nach Destination Name geordnet finde ich folgende interessanten Stelle.

Nun habe ich 3 Breakpoints auf die GetDlgItemTextA Stellen gemacht und hoffe dass die Eingaben einfach abgefangen werden, wenn ich den Serial eingebe. Jetzt starte ich das Programm, Klick auf installieren, bestätige die AGB und gebe dann den Serial ein. Nachdem ich die erste Zahl, in die Serialbox eingegeben habe, werde ich auch gleich in OllyDbg geschmissen.

CPU Disasm
Address   Hex dump          Command                                  Comments
00401A58  |.  8D4424 00     LEA EAX,[LOCAL.1023]                     ; faengt Zeichen im Serial ab
00401A5C  |.  68 00100000   PUSH 1000                                ; /MaxCount = 4096.
00401A61  |.  50            PUSH EAX                                 ; |String => OFFSET LOCAL.1023
00401A62  |.  51            PUSH ECX                                 ; |ItemID => [ARG.2]
00401A63  |.  52            PUSH EDX                                 ; |hDialog => [ARG.1]
00401A64  |.  FF15 94564400 CALL DWORD PTR DS:[<&USER32.GetDlgItemTe ; \USER32.GetDlgItemTextA
00401A6A  |.  85C0          TEST EAX,EAX

Nicht wirklich eine interessante Stelle, also schnell den Breakpoint auf Disable setzten. Nun gebe ich die nächsten Zahlen ein und nachdem die erste Textbox voll ist und ich noch ein Zeichen eingeben will kommt schon der nächste Halt in OllyDbg.

 CPU Disasm Address   Hex dump          Command                                  Comments
004018BC  |.  81C6 D7070000 ADD ESI,7D7                              ; funktion switcht zur naechsten box
004018C2  |.  56            PUSH ESI                                 ; /ItemID
004018C3  |.  50            PUSH EAX                                 ; |hDialog => [43A658] = 002E061A, class = #32770, text = Starcraft - CD-Code.
004018C4  |.  FFD7          CALL EDI                                 ; \USER32.GetDlgItem
004018C6  |.  50            PUSH EAX                                 ; /hWnd
004018C7  |.  FF15 9C564400 CALL DWORD PTR DS:[]                     ; \USER32.SetFocus
004018CD  |.  8B0D 58A64300 MOV ECX,DWORD PTR DS:[43A658]

Ah! Hier wird einfach nur der Fokus auf die nächste Textbox gesetzt. Sehr nette Funktion. Nachdem ich nun den gesamten Serial eingegeben habe, kann es auch schon losgehen und mit einem Klick auf OK, ploppt wieder OllyDbg auf.

Da sind wir

CPU Disasm
Address   Hex dump          Command                                  Comments
00401DAC  |.  8D4424 18     LEA EAX,[LOCAL.1023]                     ; Serial ueberpruefung beginnt
00401DB0  |.  68 00100000   PUSH 1000                                ; /MaxCount = 4096.
00401DB5  |.  50            PUSH EAX                                 ; |String => OFFSET LOCAL.1023
00401DB6  |.  68 DA070000   PUSH 7DA                                 ; |ItemID = 2010.
00401DBB  |.  56            PUSH ESI                                 ; |hDialog => [ARG.1]
00401DBC  |.  FFD7          CALL EDI                                 ; \USER32.GetDlgItemTextA
00401DBE  |.  85C0          TEST EAX,EAX
00401DC0  |.  75 04         JNE SHORT 00401DC6
00401DC2  |.  884424 18     MOV BYTE PTR SS:[LOCAL.1023],AL
00401DC6  |>  8D4C24 18     LEA ECX,[LOCAL.1023]
00401DCA  |.  56            PUSH ESI                                 ; /Arg2
00401DCB  |.  51            PUSH ECX                                 ; |Arg1 => OFFSET LOCAL.1023
00401DCC  |.  E8 AF000000   CALL 00401E80                            ; \INSTALL.00401E80
00401DD1  |.  83C4 08       ADD ESP,8
00401DD4  |.  85C0          TEST EAX,EAX
00401DD6  |.  0F84 8C000000 JE 00401E68
00401DDC  |.  8D5424 18     LEA EDX,[LOCAL.1023]
00401DE0  |.  52            PUSH EDX                                 ; /Src => OFFSET LOCAL.1023
00401DE1  |.  68 38A64300   PUSH OFFSET 0043A638                     ; |Dest = "TheVamp"
00401DE6  |.  FF15 68554400 CALL DWORD PTR DS:[] ; \KERNEL32.lstrcpy
00401DEC  |.  6A 0E         PUSH 0E                                  ; /Arg3 = 0E
00401DEE  |.  68 28A64300   PUSH OFFSET 0043A628                     ; |Arg2 = ASCII "1111111111111"
00401DF3  |.  56            PUSH ESI                                 ; |Arg1
00401DF4  |.  E8 B7010000   CALL 00401FB0                            ; \INSTALL.00401FB0
00401DF9  |.  83C4 0C       ADD ESP,0C
00401DFC  |.  56            PUSH ESI                                 ; /Arg2
00401DFD  |.  68 28A64300   PUSH OFFSET 0043A628                     ; |Arg1 = ASCII "1111111111111"
00401E02  |.  E8 09010000   CALL 00401F10                            ; \INSTALL.00401F10
00401E07  |.  83C4 08       ADD ESP,8

Die Letzte Funktion ist am interessantesten. Die Funktion 0x00401FB0 aufgerufen wird, handelt es sich nur um eine Kopierfunktion, die den Serial aus den einzelnen Textboxen zusammenbringt. Diese ist somit eher uninteressant und wir gehen sofort zur letzten Funktion (0x00401F10) über.

Wie immer – Auf die Länge kommt’s an

CPU Disasm
Address   Hex dump          Command                                  Comments
00401F26  |> \56            PUSH ESI                                 ; /String => [ARG.1]
00401F27  |.  FF15 64554400 CALL DWORD PTR DS:[] ; \KERNEL32.lstrlenA
00401F2D  |.  83F8 0D       CMP EAX,0D                               ; laenge von 13 zeichen sonst ist nicht alles eingegeben
00401F30  |.  74 1C         JE SHORT 00401F4E
00401F32  |.  8B4424 10     MOV EAX,DWORD PTR SS:[ARG.2]             ; fehlermeldung serial zu kurz
00401F36  |.  50            PUSH EAX                                 ; /Arg3 => [ARG.2]
00401F37  |.  68 5A020000   PUSH 25A                                 ; |Arg2 = 25A
00401F3C  |.  68 58020000   PUSH 258                                 ; |Arg1 = 258
00401F41  |.  E8 DA040100   CALL 00412420                            ; \INSTALL.00412420
00401F46  |.  83C4 0C       ADD ESP,0C

Das erste was uns wieder entgegen grinst ist die Längen-Überprüfung. So wie immer muss erst einmal der Serial die richtige Größe haben. Nachdem diese Prüfung überstanden ist, geht es auch schon zur richtigen Serialüberprüfung.

Zielgerade

CPU Disasm
Address   Hex dump          Command                                  Comments
00401F4E  |> \B8 03000000   MOV EAX,3                                ; laufvariable
00401F53  |.  33D2          XOR EDX,EDX
00401F55  |>  8A0C32        /MOV CL,BYTE PTR DS:[ESI+EDX]
00401F58  |.  80F9 30       |CMP CL,30                               ; ueberpruefe ob zahl
00401F5B  |.  7C 2F         |JL SHORT 00401F8C
00401F5D  |.  80F9 39       |CMP CL,39
00401F60  |.  7F 2A         |JG SHORT 00401F8C
00401F62  |.  0FBEC9        |MOVSX ECX,CL                            ; lese serial zahl ein
00401F65  |.  8D3C00        |LEA EDI,[EAX+EAX]                       ; verdopple laufvariable temporaer
00401F68  |.  83E9 30       |SUB ECX,30                              ; zahl fuer cpu lesbar machen
00401F6B  |.  33F9          |XOR EDI,ECX                             ; serialzahl XOR laufvariable
00401F6D  |.  03C7          |ADD EAX,EDI                             ; fuege XOR Wert zur Laufvariable hinzu
00401F6F  |.  42            |INC EDX
00401F70  |.  83FA 0C       |CMP EDX,0C                              ; bei 0xC rausspringen
00401F73  |.^ 72 E0         \JB SHORT 00401F55
00401F75  |.  33D2          XOR EDX,EDX
00401F77  |.  B9 0A000000   MOV ECX,0A
00401F7C  |.  F7F1          DIV ECX                                  ; rest von der Laufvariable / 0xA
00401F7E  |.  0FBE46 0C     MOVSX EAX,BYTE PTR DS:[ESI+0C]           ; letzte stelle vom serial
00401F82  |.  0FBECA        MOVSX ECX,DL
00401F85  |.  83C1 30       ADD ECX,30
00401F88  |.  3BC1          CMP EAX,ECX                              ; vergleich letzte stelle serial mit rest von laufvariable / 0xA
00401F8A  |.  74 1C         JE SHORT 00401FA8
00401F8C  |>  8B5424 10     MOV EDX,DWORD PTR SS:[ARG.2]             ; Fehlermeldung Serial ist falsch
00401F90  |.  52            PUSH EDX                                 ; /Arg3 => [ARG.2]
00401F91  |.  68 59020000   PUSH 259                                 ; |Arg2 = 259
00401F96  |.  68 58020000   PUSH 258                                 ; |Arg1 = 258
00401F9B  |.  E8 80040100   CALL 00412420                            ; \INSTALL.00412420
00401FA0  |.  83C4 0C       ADD ESP,0C

Blizzard setzte also schon damals auf schöne XOR Funktionen. Die Funktion startet mit einer Anfangsvariable, die auf 3 gesetzt ist, danach wird überprüft ob das eingelesene Zeichen eine Zahl ist. Diese eingelesene Zahl wird dann mit dem doppelten der Anfangsvariable gexored. Das Ergebnis aus diesem XOR wird dann auf die Anfangsvariable aufaddiert. Nachdem die ersten 12 Zeichen eingelesen und gexored worden sind, wird die Schleife verlassen und unsere Anfangsvariable ist ziemlich groß geworden (^.^). Die letzte Stelle des Serials wird somit nicht einberechnet. Der Wert der Anfangsvariable wird nun durch 10 geteilt und der Rest davon wird wiederrum mit der letzten Stelle des Serial verglichen. Wenn beide gleich sind haben wir diese Überprüfung überstanden und können das Spiel installieren.

Random Bruteforce FTW!

Da ich mich noch nicht so extrem mit Kryptografie beschäftigt habe, habe ich keinen Plan wie man aus dieser Serialüberprüfung einen passenden KeyGen macht. Also habe ich einfach, wie bei Diablo 2, eine Random Bruteforce Attacke geschrieben. Einfach die Funktion nach coden und schon kann das gebrute losgehen :D.
Das Programm arbeitet mit Threads, deswegen sind die locks dazwischen ;)

private void crack_starcraft_key()
{
	int[] serial = { 0x1, 0x1, 0x1, 0x1, 0x1,
                     0x1, 0x1, 0x1, 0x1, 0x1,
                     0x1, 0x1, 0x1 };//13 stellen lang

    while (true)
    {
		//Random Bruteforce
	 	Random r = new Random();
	 	for (int i = 0; i < serial.Length; i++)
		{
			serial[i] = r.Next(0, 9);
		}

		for (int j = 0; j < 1000; j++)
        {
            //Serial Prüfung
            int laufvariable = 0x3;
            for (int i = 0; i < 0xC; i++)
            {
                laufvariable += (laufvariable*2) ^ serial[i];
            }
			//Vergleich
			int check = laufvariable % 0xA;
            if (check == serial[12])
            {
                //serials ausgeben
                string temp = "";
                for (int i = 0; i < serial.Length; i++)                 {                     temp += serial[i].ToString();                 }                 txt_ausgabe.Text += temp + "\n"; 				//Serials abspeichern                 lock (this)                 {                     StreamWriter myFile = new StreamWriter("./starcraft_serials.txt", true);                     myFile.Write(temp + "\n");                     myFile.Close();                 }             }             //Serial hochzählen             for (int i = 12; i > 0; i--)
            {
                //ersten hochzählen
                if (i == 12)
                {
                    serial[i]++;
                }
                //wenn über größe dann davor hochzählen
                if (serial[i] >= 10)
                {
                    serial[i - 1]++;
                    serial[i] = 0;
                }
            }
        }
    }
 }

Ich hoffe es hat euch gefallen und der kleine Ausflug war vielleicht wieder ein wenig lehrreich ;) Ich hau mich jetzt auf’s Ohr und freu mich auf das nächste Spiel oder Programm.
Greetz TheVamp

Starcraft Serial Bruteforcer - Source (5006 Downloads)

2 thoughts on “Starcraft – Let’s CrackIt”

  1. Here’s some C++ code I made from looking at the executable on my system

    /* ———————————————-
    Starcraft CD-Key Generator
    Algorithm @ 004111A5 in INSTALL.EXE
    File Version 1.05
    ———————————————–*/
    #include
    #include
    #include
    #include

    int main() {

    int s=3; // Initial value
    int i=0;
    int serial[13];

    /* Initialize seed value */
    srand(time(NULL));

    while (i<12) {
    serial[i] = rand() % 10;
    s += (s*2)^(serial[i]);
    i++;
    }

    serial[12] = s % 10;

    std::cout << "CD-KEY: ";
    for (int n = 0; n < 13; n++) {
    if ((n == 4)|(n == 9)) {
    std::cout << '-';
    }
    std::cout << serial[n];
    }
    std::cout << std::endl;

    }

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.