	  Ŀ
	                                                                 Ŀ
	                             
	                  
	                              
	                                 
	                             
	                                      
	                                                
	                                           
	                                        
	                                 
	                                 
	                                   
	                                     
	                                  
	                                                      
	                                                                     
	                            
	                  p r o u d l y     p r e s e n t s                  
	                            
	Ŀ                                              www.tscube.cjb.net 
	  


			Tutorial for Phrozen Crew crackme #1
			-------------------------------------


+----------+
| 1. Intro |
+----------+

Well, this crackme was the first one I ever downloaded... and Phrozen Crew was the first group
I ever heard of; it was in 98. 

At that time, I had never used a debugger, nor a disassembler, THE_q had no '+',
an I was wondering how it was possible to find a good serial without the source code of the
proggy. Of course, It was too soon for me to be able to solve crackmes, and at that time I said 
to myself "One day, I'll be able to find valid serials for this crackme".

Now the time has come, so here is a tutorial and a keygen for this crackme.



+----------------------------------+
| 2. A journey in the dead listing |
+----------------------------------+

The serial is checked every time you type/delete a letter; so type something, 'BPX HMEMCPY',
type a letter, SICE pops, disable breakpoints, F12 a few times, and you land here :


:00425F99 E8AAF3FEFF              call 00415348 
:00425F9E 8B45F8                  mov eax, dword ptr [ebp-08] ->  serial
:00425FA1 E8CAD5FDFF              call 00403570 => strlen
:00425FA6 8BD0                    mov edx, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00425F39(C)
|
:00425FA8 8D45F4                  lea eax, dword ptr [ebp-0C]
:00425FAB E894D8FDFF              call 00403844
:00425FB0 8B45F8                  mov eax, dword ptr [ebp-08]
:00425FB3 E8B8D5FDFF              call 00403570
:00425FB8 8BD0                    mov edx, eax
:00425FBA 8D45F0                  lea eax, dword ptr [ebp-10]
:00425FBD E882D8FDFF              call 00403844
:00425FC2 8B45F8                  mov eax, dword ptr [ebp-08]
:00425FC5 E8A6D5FDFF              call 00403570
:00425FCA 83F808                  cmp eax, 00000008
:00425FCD 7D0D                    jge 00425FDC
:00425FCF 8D45F4                  lea eax, dword ptr [ebp-0C]
:00425FD2 BA08000000              mov edx, 00000008
:00425FD7 E868D8FDFF              call 00403844

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00425FCD(C)
|
:00425FDC C645EF01                mov [ebp-11], 01 -> counter_1 used in loop_1
:00425FE0 C645EE01                mov [ebp-12], 01 -> counter_2 used in loop_1
:00425FE4 8B45F8                  mov eax, dword ptr [ebp-08] -> serial
:00425FE7 E884D5FDFF              call 00403570 (strlen)
:00425FEC 84C0                    test al, al
:00425FEE 7664                    jbe 00426054
:00425FF0 8845EA                  mov byte ptr [ebp-16], al -> strlen(serial)
:00425FF3 B301                    mov bl, 01

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00426052(C)
|


begin_loop_1
------------

We will loop [EBP-16] = strlen(serial) times

this loop will generate 2 strings from the serial. First string will be stored at @ [EBP-0C],
second one at @ [ebp-10]


:00425FF5 33C0                    xor eax, eax
:00425FF7 8AC3                    mov al, bl
:00425FF9 8B55F8                  mov edx, dword ptr [ebp-08]
:00425FFC 8A4402FF                mov al, byte ptr [edx + eax - 01] -> serial[i]
:00426000 25FF000000              and eax, 000000FF
:00426005 0FA30540784200          bt dword ptr [00427840], eax

Well, in short, this test checks if serial[i] is a even number (ie 0,2,4,6,8)

:0042600C 7321                    jnb 0042602F -> jump is serial[i] is NOT a even number

	We land here if serial[i] is an even number
	--------------------------------------------

:0042600E 8D45F4                  lea eax, dword ptr [ebp-0C] -> string_1
:00426011 E82AD7FDFF              call 00403740
:00426016 33D2                    xor edx, edx
:00426018 8A55EF                  mov dl, byte ptr [ebp-11] -> counter_1
:0042601B 33C9                    xor ecx, ecx
:0042601D 8ACB                    mov cl, bl
:0042601F 8B75F8                  mov esi, dword ptr [ebp-08]
:00426022 8A4C0EFF                mov cl, byte ptr [esi + ecx - 01] -> serial[i]
:00426026 884C10FF                mov byte ptr [eax + edx - 01], cl
:0042602A FE45EF                  inc [ebp-11]
:0042602D EB1F                    jmp 0042604E

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042600C(C)

	We land here if serial[i] is NOT an even number (1,3,5,7,9 and all letters)
	----------------------------------------------------------------------------

:0042602F 8D45F0                  lea eax, dword ptr [ebp-10] -> string_2
:00426032 E809D7FDFF              call 00403740
:00426037 33D2                    xor edx, edx
:00426039 8A55EE                  mov dl, byte ptr [ebp-12] -> counter_2
:0042603C 33C9                    xor ecx, ecx
:0042603E 8ACB                    mov cl, bl
:00426040 8B75F8                  mov esi, dword ptr [ebp-08]
:00426043 8A4C0EFF                mov cl, byte ptr [esi + ecx - 01] -> serial[i]
:00426047 884C10FF                mov byte ptr [eax + edx - 01], cl
:0042604B FE45EE                  inc [ebp-12]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042602D(U)
|
:0042604E 43                      inc ebx
:0042604F FE4DEA                  dec [ebp-16]                                    
:00426052 75A1                    jne 00425FF5

end_loop_1
------------


So, what's happening in this loop ?

The serial is splitted in 2 strings : one of them if composed of the even numbers of the serial,
the second one is composed of all the others caracters

"1234TSC56879" -> "2468" & "13TSC579"

counter_1 is the length of the first string
coutner_2 is the length of the second string






* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00425FEE(C)
|
:00426054 33FF                    xor edi, edi
:00426056 33D2                    xor edx, edx
:00426058 8A55EE                  mov dl, byte ptr [ebp-12]
:0042605B 4A                      dec edx
:0042605C 8D45F0                  lea eax, dword ptr [ebp-10]
:0042605F E8E0D7FDFF              call 00403844
:00426064 8A45EE                  mov al, byte ptr [ebp-12] -> magic2
:00426067 48                      dec eax
:00426068 84C0                    test al, al
:0042606A 761A                    jbe 00426086
:0042606C 8845EA                  mov byte ptr [ebp-16], al -> strlen(string_2)
:0042606F B301                    mov bl, 01

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00426084(C)


begin_loop_2
-------------

We will loop 'strlen(string_2) - 1' times


:00426071 33C0                    xor eax, eax
:00426073 8AC3                    mov al, bl                              
:00426075 8B55F0                  mov edx, dword ptr [ebp-10]   
:00426078 0FB64402FF              movzx eax, byte ptr [edx + eax - 01] -> string_2[i]    
:0042607D 6633F8                  xor di, ax                              
:00426080 43                      inc ebx                                 
:00426081 FE4DEA                  dec [ebp-16]                            
:00426084 75EB                    jne 00426071

end_loop_2
-----------

This loop generates a xor_value by xoring all the letters of string_2





* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042606A(C)
|
:00426086 8A45EF                  mov al, byte ptr [ebp-11]
:00426089 F6D0                    not al
:0042608B 3C08                    cmp al, 08
:0042608D 761F                    jbe 004260AE
:0042608F 8A5DEF                  mov bl, byte ptr [ebp-11] -> counter_1
:00426092 80FB08                  cmp bl, 08
:00426095 7717                    ja 004260AE

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004260AC(C)


begin_loop_3
--------------

:00426097 8D45F4                  lea eax, dword ptr [ebp-0C] -> string_1
:0042609A E8A1D6FDFF              call 00403740                 
:0042609F 33D2                    xor edx, edx                  
:004260A1 8AD3                    mov dl, bl                    
:004260A3 C64410FF30              mov [eax + edx - 01], 30 -> adds '0' at end of string    
:004260A8 43                      inc ebx                       
:004260A9 80FB09                  cmp bl, 09                    
:004260AC 75E9                    jne 00426097

end_loop_3
------------

This loop adds '0' at end of string_1 until length = 8
ex : "2468" -> "24680000"




* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0042608D(C), :00426095(C)
|
:004260AE 8D45F4                  lea eax, dword ptr [ebp-0C]
:004260B1 BA08000000              mov edx, 00000008
:004260B6 E889D7FDFF              call 00403844
:004260BB 8D45F8                  lea eax, dword ptr [ebp-08] -> serial
:004260BE BA04000000              mov edx, 00000004
:004260C3 E87CD7FDFF              call 00403844
:004260C8 B301                    mov bl, 01

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004260E9(C)

begin_loop_4
--------------

We will loop 4 times

:004260CA 8D45F8                  lea eax, dword ptr [ebp-08] -> serial (4 chr)
:004260CD E86ED6FDFF              call 00403740                         
:004260D2 8BF3                    mov esi, ebx                          
:004260D4 81E6FF000000            and esi, 000000FF                     
:004260DA 8B55F4                  mov edx, dword ptr [ebp-0C] -> string_1           
:004260DD 8A5432FF                mov dl, byte ptr [edx + esi - 01] -> string_1[i]     
:004260E1 885430FF                mov byte ptr [eax + esi - 01], dl     
:004260E5 43                      inc ebx                               
:004260E6 80FB05                  cmp bl, 05                            
:004260E9 75DF                    jne 004260CA

end_loop_4
-----------

From now, the serial is not needed anymore... so it is used as an temporary buffer for all the
following operations !

this loop takes the first 4 letters of string_1 and stores them at the beginning of the
'serial' buffer 


:004260EB 8B45F8                  mov eax, dword ptr [ebp-08] -> 4 first letters of string_1
:004260EE E8B5FFFDFF              call 004060A8 => converts string to integer value
:004260F3 668945EC                mov word ptr [ebp-14], ax -> used in final check
:004260F7 B301                    mov bl, 01

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00426118(C)


begin_loop_5
-------------

We will loop 4 times

:004260F9 8D45F8                  lea eax, dword ptr [ebp-08]    
:004260FC E83FD6FDFF              call 00403740                         
:00426101 8BF3                    mov esi, ebx                          
:00426103 81E6FF000000            and esi, 000000FF                     
:00426109 8B55F4                  mov edx, dword ptr [ebp-0C] -> string_1           
:0042610C 8A543203                mov dl, byte ptr [edx + esi + 03]     
:00426110 885430FF                mov byte ptr [eax + esi - 01], dl -> serial[i]     
:00426114 43                      inc ebx                               
:00426115 80FB05                  cmp bl, 05                            
:00426118 75DF                    jne 004260F9

end_loop_5
-----------

this loop takes the *last* 4 letters of string_1 and stores them at the beginning of the
'serial' buffer 



:0042611A 8B45F8                  mov eax, dword ptr [ebp-08] -> 4 last letters of string_1
:0042611D E886FFFDFF              call 004060A8 => converts string to integer value
:00426122 8BC8                    mov ecx, eax
:00426124 6685FF                  test di, di -> xor_value (see loop2)
:00426127 741B                    je 00426144 -> FUCK OFF 

:00426129 668B45EC                mov ax, word ptr [ebp-14] -> first part of string_1 (@4260F3)
:0042612D 6633C1                  xor ax, cx
:00426130 0FB7C0                  movzx eax, ax
:00426133 0FB7D7                  movzx edx, di
:00426136 8BCA                    mov ecx, edx -> ecx= xor_value
:00426138 99                      cdq
:00426139 F7F9                    idiv ecx
:0042613B 83FA0D                  cmp edx, 0000000D

=> (first_number ^ second_number) % xor_value = 13 ???

:0042613E 7504                    jne 00426144 -> FUCK OFF

:00426140 C645EB01                mov [ebp-15], 01 -----> REGISTERED



+------------+
| 3. exemple |
+------------+

Let's take the serial of pc.nfo : "2486PC0288"

1) First, we split this serial in 2 parts : "24860288" (only even numbers) and "PC".
(this serial is a bit special because all numbers are even numbers)

2) We compute the magic_value from the second string :

	magic_value = 'P' ^ 'C' = 80 ^ 67 = 19

3) we split the first string in 2 parts and we converts these strings to 2 integers values :

	"24860288" -> "2486" & "0288" -> 2486 & 288

4) we must check if :

(2486 ^ 288) % 19 = 13

.. which is the case, so we are R-E-G-I-S-T-E-R-E-D !!



+------------------------------+
| 4. making a serial generator |
+------------------------------+

I decided to do it this way : the generated serial will be composed of 3 elements :
- 2 numbers composed only of EVEN digits (0,2,4,6,8)
- a few letters

The users type a few letters ("PC" for example), then the serial generator will use a brute
force approach to find the 2 numbers.

With this method, it's not possible to find serials for every letters you might type ( there's
is no valid serial for the letters "TSC"), so if it bothers you, make a better keygen ;)

<-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><->

Serial generator for Phrozen Crew crackme #1 by TSCube 24/06/2000

Type any letters : PC
Bruteforcing...

Possible serial : 0000PC0222
Possible serial : 0000PC0260
Possible serial : 0000PC0488
Possible serial : 0000PC0602
Possible serial : 0000PC0640
Possible serial : 0000PC0868
Possible serial : 0000PC2008
Possible serial : 0000PC2046
Possible serial : 0000PC2084
Possible serial : 0000PC2426
Possible serial : 0000PC2464
Possible serial : 0000PC2806
Possible serial : 0000PC2844
Possible serial : 0000PC2882
Possible serial : 0000PC4022
Possible serial : 0000PC4060
Possible serial : 0000PC4288
Possible serial : 0000PC4402
Possible serial : 0000PC4440
Possible serial : 0000PC4668
Possible serial : 0000PC4820
[...]

<-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><->


+----------+
| 5. Outro |
+----------+

This tutorial is dedicated to all PC98 guys

    ________     _______     _______
   /__   __/\   /  ____/\   /  ____/\
   \_/  /\_\/  /  /\___\/  /  /\___\/
    /  / /    /  /_/_     /  / / 
   /  / /    /____  /\   /  / /
  /  / /     \___/ / /  /  / /
 /  / /     ____/ / /  /  /_/_
/  / /     /_____/ /  /______/\
\__\/      \_____\/   \______\/ 24/06/2000

www.tscube.cjb.net