[CrackMe 9.0 by WiteG ]
par Amenesia
D'apres  PEiD, le programme est packé avec FSG:
L'option "Trace real entry blockwise" de OllyDbg permet de trouver assez vite l'OEP... 
Ensuite  dump et reconstruction de l'IAT...
 

seg001:00413831 loc_0_413831: 
seg001:00413831                 dec     byte ptr [esi]
seg001:00413833                 jz      near ptr dword_0_402D71    ; OEP
seg001:00413839                 push    esi
seg001:0041383A 
seg001:0041383A loc_0_41383A: 
seg001:0041383A                 push    ebp
seg001:0041383B                 call    dword ptr [ebx+4]
seg001:0041383E                 stosd
seg001:0041383F                 jmp     short loc_0_413821
seg001:0041383F start           endp
 


1-Entée

Tenter des bpx sur  GetDlgItemText  ou GetWindowTextA ne mene a rien ( il utilse WM_GETTEXT)...   mais une recherche de la chaine "Invalid user data." nous conduit:

seg000:00403991                 mov     ebx, offset aInvalidUserData
seg000:00403996                 mov     esi, offset Serial
seg000:0040399B                 push    esi             ; lParam
seg000:0040399C                 push    41h             ; wParam
seg000:0040399E                 push    0Dh             ; Msg
seg000:004039A0                 push    3EAh            ; nIDDlgItem
seg000:004039A5                 push    [ebp+hDlg]      ; hDlg
seg000:004039A8                 call    SendDlgItemMessageA
seg000:004039AD                 cmp     eax, 40h
seg000:004039B0                 jnz     short End

seg000:004039B2                 mov     edi, offset Name
seg000:004039B7                 push    edi             ; lParam
seg000:004039B8                 push    41h             ; wParam
seg000:004039BA                 push    0Dh             ; Msg
seg000:004039BC                 push    3E9h            ; nIDDlgItem
seg000:004039C1                 push    [ebp+hDlg]      ; hDlg
seg000:004039C4                 call    SendDlgItemMessageA
seg000:004039C9                 cmp     eax, 5
seg000:004039CC                 jl      short End

Donc, la longueur du Serial = 40h et celle du Nom doit etre superieur à 4


Ensuite le Nom est utilisé pour creer une clef de 256 bits ( pour simplifier je l'appelle NameKey ). 

seg000:004039CE                 push    edi
seg000:004039CF                 push    eax              ; Name length
seg000:004039D0                 push    edi              ; Name
seg000:004039D1                 call    GenSubKey



... et les lettres composant le serial sont remplacé par leur valeur numerique, ie '0' -> 0, '1' ->1, ..., 'F' -> F
( le  serial doit etre composé uniquement de [0-9] et [A-F]  )

seg000:004039D6                 push    esi
seg000:004039D7                 push    esi             ; serial
seg000:004039D8                 call    AsciiToHex
seg000:004039DD                 jb      End



2- Serial

Puis NameKey et une constante ( MagicKey ) sont utilisés pour modifier le Serial et creer ModifiedSerial:

seg000:004039E2 Loop: 
seg000:004039E2                 push    esi             ; NameKey
seg000:004039E3                 push    offset MagicKey ; a constant
seg000:004039E8                 push    edi             ; Serial
seg000:004039E9                 call    GenereKey
seg000:004039EE                 add     esi, 10h
seg000:004039F1                 add     edi, 10h
seg000:004039F4                 dec     ecx
seg000:004039F5                 jnz     short Loop 

seg000:00403A45 GenereKey       proc near 
seg000:00403A45 
seg000:00403A45 Name            = dword ptr  8
seg000:00403A45 MagicKey        = dword ptr  0Ch
seg000:00403A45 Serial          = dword ptr  10h
seg000:00403A45 
seg000:00403A45                 push    ebp
seg000:00403A46                 mov     ebp, esp
seg000:00403A48                 pusha
seg000:00403A49                 mov     esi, [ebp+Serial]
seg000:00403A4C                 mov     edi, [ebp+Name]
seg000:00403A4F                 xor     eax, eax
seg000:00403A51                 mov     ecx, 80h
seg000:00403A56 
seg000:00403A56 LoopGenKey: 
seg000:00403A56                 shl     dword ptr [edi+0Ch], 1
seg000:00403A59                 rcl     dword ptr [edi+8], 1
seg000:00403A5C                 rcl     dword ptr [edi+4], 1
seg000:00403A5F                 rcl     dword ptr [edi], 1
seg000:00403A61                 setb    al
seg000:00403A64                 or      [edi+0Ch], eax
seg000:00403A67                 push    esi
seg000:00403A68                 push    [ebp+MagicKey]
seg000:00403A6B                 call    [off_0_403A79 + eax*4]
seg000:00403A72                 loop    LoopGenKey
seg000:00403A74                 popa
seg000:00403A75                 leave
seg000:00403A76                 retn    0Ch
seg000:00403A76 GenereKey       endp

seg000:00403A79 off_0_403A79    dd offset Cas1 
seg000:00403A7D                 dd offset Cas2

Si le bit se situant le plus a gauche de NameKey est 0 GenereKey appelle Cas1 sinon il appelle Cas2...



 

seg000:00403B87 Cas1            proc near 
seg000:00403B87 
seg000:00403B87 MagicKey        = dword ptr  8
seg000:00403B87 Serial          = dword ptr  0Ch
seg000:00403B87 
seg000:00403B87                 push    ebp
seg000:00403B88                 mov     ebp, esp
seg000:00403B8A                 pusha
seg000:00403B8B                 xor     ecx, ecx
seg000:00403B8D                 push    ecx
seg000:00403B8E                 push    ecx
seg000:00403B8F                 push    ecx
seg000:00403B90                 push    ecx
seg000:00403B91                 mov     esi, [ebp+MagicKey]
seg000:00403B94                 mov     edi, [ebp+Serial]
seg000:00403B97                 mov     edx, 80h
seg000:00403B9C 
seg000:00403B9C LoopCase1: 
seg000:00403B9C                 shr     dword ptr [edi], 1
seg000:00403B9E                 rcr     dword ptr [edi+4], 1
seg000:00403BA1                 rcr     dword ptr [edi+8], 1
seg000:00403BA4                 rcr     dword ptr [edi+0Ch], 1
seg000:00403BA7                 jnb     short loc_0_403BB7
seg000:00403BA9 
seg000:00403BA9 Loop64_C1: 
seg000:00403BA9                 mov     eax, [ecx+esi]
seg000:00403BAC                 xor     [esp+ecx], eax
seg000:00403BAF                 add     ecx, 4
seg000:00403BB2                 and     ecx, 0Fh
seg000:00403BB5                 jnz     short Loop64_C1
seg000:00403BB7 
seg000:00403BB7 loc_0_403BB7: 
seg000:00403BB7                 add     esi, 10h
seg000:00403BBA                 dec     edx
seg000:00403BBB                 jnz     short LoopCase1
seg000:00403BBD                 cld
seg000:00403BBE                 pop     eax
seg000:00403BBF                 stosd
seg000:00403BC0                 pop     eax
seg000:00403BC1                 stosd
seg000:00403BC2                 pop     eax
seg000:00403BC3                 stosd
seg000:00403BC4                 pop     eax
seg000:00403BC5                 stosd
seg000:00403BC6                 popa
seg000:00403BC7                 leave
seg000:00403BC8                 retn    8
seg000:00403BC8 Cas1            endp
seg000:00403BC8 

Si on veut pouvoir trouver un Serial valide, il faut qu'on soit capable de calculer la valeur du Serial a partir de la valeur de ModifiedSerial.

On remarque que si "Y1 = Cas1(Serial1)"  et "Y2 = Cas1(Serial2)" alors  "Y2 xor Y1 = Cas1(Serial2 xor Serial1)"
Or toutes les valeurs peuvent etre considerées comme une suite de bit BnBn-1...B1B0, or :

BnBn-1...B1B0 = 000...001*B0 xor  000...010*B1 xor  ... xor 010...000*B(n-1) xor 100...000*Bn

donc Cas1(BnBn-1...B1B0 ) = Cas1(000...001)*B0 xor  Cas1(000...010)*B1 xor  ... xor Cas1(010...000)*B(n-1) xor Cas1(100...000)*Bn

Donc  AnAn-1...A1A0 = Cas1(BnBn-1...B1B0 )  = BnBn-1...B1B0 *M avec M la matrice: 
 

B0 B1 ... Bn-1 Bn
\/ \/ \/ \/ \/
( Cas1(B0 )n Cas1(B1 )n ... Cas1(Bn-1 )n Cas1(Bn )n ) >  An
( Cas1(B0 )n-1 Cas1(B1 )n-1 ... Cas1(Bn-1 )n-1 Cas1(Bn )n-1 ) >  An-1
( ... ... ... ... ... ) > ...
( Cas1(B0 )1 Cas1(B1 )1 ... Cas1(Bn-1 )1 Cas1(Bn )1 ) > A1
( Cas1(B0 )0 Cas1(B1 )0 ... Cas1(Bn-1 )0 Cas1(Bn )0 ) > A0

Un effectuant des xor entre les differentes colonnes on peut facilement s'arranger pour mettre M sous la forme d'une matrice triangulaire superieur :
 

B? xor ... xor B? B? xor ... xor B? ... B? xor ... xor B? B? xor ... xor B?
\/ \/ \/ \/ \/
( 1 Cas1(B1 )n ... Cas1(Bn-1 )n Cas1(Bn )n ) >  An
( 0 1 ... Cas1(Bn-1 )n-1 Cas1(Bn )n-1 ) >  An-1
( ... ... ... ... ... ) > ...
( 0 0 ... 1 Cas1(Bn )1 ) > A1
( 0 0 ... 0 1 ) > A0

 

Une fois sous cette forme il est assez simple de detreminer les colonnes sur les quelles effectuer des xor pour que:

AnAn-1...A1A0 = ModifiedSerial...



 
 
 

... B? xor ... xor B?
\/ \/ \/ \/ \/
( 1 Cas1(B1 )n ... Cas1(Bn-1 )n (ModifiedSerial)n ) >  An
( 0 1 ... Cas1(Bn-1 )n-1 (ModifiedSerial)n-1 ) >  An-1
( ... ... ... ... ... ) > ...
( 0 0 ... 1 (ModifiedSerial)1 ) > A1
( 0 0 ... 0 (ModifiedSerial)0 ) > A0

Donc Cas1(B? xor ... xor B?) = ModifiedSerial... autrement dit B? xor ... xor B? = Serial 
 


seg000:00403BCB Cas2            proc near 
seg000:00403BCB 
seg000:00403BCB var_2C          = dword ptr -2Ch
seg000:00403BCB var_28          = dword ptr -28h
seg000:00403BCB var_24          = dword ptr -24h
seg000:00403BCB MagicKey        = dword ptr  8
seg000:00403BCB Serial          = dword ptr  0Ch
seg000:00403BCB 
seg000:00403BCB                 push    ebp
seg000:00403BCC                 mov     ebp, esp
seg000:00403BCE                 pusha
seg000:00403BCF                 xor     ecx, ecx
seg000:00403BD1                 push    ecx
seg000:00403BD2                 push    ecx
seg000:00403BD3                 push    ecx
seg000:00403BD4                 push    ecx
seg000:00403BD5                 mov     esi, [ebp+MagicKey]
seg000:00403BD8                 mov     edi, [ebp+Serial]
seg000:00403BDB                 cld
seg000:00403BDC                 mov     edx, 80h
seg000:00403BE1 
seg000:00403BE1 LoopCase2: 
seg000:00403BE1                 xor     ebx, ebx
seg000:00403BE3 
seg000:00403BE3 Loop64_C2: 
seg000:00403BE3                 lodsd 
seg000:00403BE4                 and     eax, [ecx+edi]
seg000:00403BE7                 call    NumEax
seg000:00403BEC                 add     ecx, 4
seg000:00403BEF                 and     ecx, 0Fh
seg000:00403BF2                 jnz     short Loop64_C2
seg000:00403BF4                 shr     ebx, 1
seg000:00403BF6                 rcl     [esp+30h+var_24], 1
seg000:00403BFA                 rcl     [esp+30h+var_28], 1
seg000:00403BFE                 rcl     [esp+30h+var_2C], 1
seg000:00403C02                 rcl     dword ptr [esp], 1
seg000:00403C05                 dec     edx
seg000:00403C06                 jnz     short LoopCase2
seg000:00403C08                 pop     eax
seg000:00403C09                 stosd
seg000:00403C0A                 pop     eax
seg000:00403C0B                 stosd
seg000:00403C0C                 pop     eax
seg000:00403C0D                 stosd
seg000:00403C0E                 pop     eax
seg000:00403C0F                 stosd
seg000:00403C10                 popa
seg000:00403C11                 leave
seg000:00403C12                 retn    8
seg000:00403C12 Cas2            endp

Ici aussi,il suffit d'utiliser la matrice N : 
 

B0 B1 ... Bn-1 Bn
\/ \/ \/ \/ \/
( Cas2(B0 )n Cas2(B1 )n ... Cas2(Bn-1 )n Cas2(Bn )n ) >  An
( Cas2(B0 )n-1 Cas2(B1 )n-1 ... Cas2(Bn-1 )n-1 Cas2(Bn )n-1 ) >  An-1
( ... ... ... ... ... ) > ...
( Cas2(B0 )1 Cas2(B1 )1 ... Cas2(Bn-1 )1 Cas2(Bn )1 ) > A1
( Cas2(B0 )0 Cas2(B1 )0 ... Cas2(Bn-1 )0 Cas2(Bn )0 ) > A0

... pour determiner le Serial a partir de ModifiedSerial:



Donc pour recupere le Serial a partir ModifiedSerial il faut utiliser la matrice M si le bit le plus a droite de NameKey est a 0, ou la matrice N si il est a 1.
 
 
 

3 - Verification

Ensuite le 128 premiers bits de ModifiedSerial sont verifiés:

seg000:004039FD                 push    esi             ; ModifiedSerial
seg000:004039FE                 push    edi             ; NameKey
seg000:004039FF                 call    vTEA 
seg000:00403A04                 jb      short Fin


seg000:00403A81 vTEA             proc near 
seg000:00403A81 
seg000:00403A81 TEA1_A          = dword ptr -28h
seg000:00403A81 TEA1_B          = dword ptr -24h
seg000:00403A81 TEA2_A          = dword ptr -20h
seg000:00403A81 TEA2_B          = dword ptr -1Ch
seg000:00403A81 var_18          = byte ptr -18h
seg000:00403A81 arg_0           = dword ptr  8
seg000:00403A81 arg_4           = dword ptr  0Ch
seg000:00403A81 
seg000:00403A81                 push    ebp
seg000:00403A82                 mov     ebp, esp
seg000:00403A84                 pusha
seg000:00403A85                 mov     esi, [ebp+arg_4]
seg000:00403A88                 mov     edi, [ebp+arg_0]
seg000:00403A8B                 mov     ecx, 2
seg000:00403A90 
seg000:00403A90 LoopTEA_Encode: 
seg000:00403A90                 sub     esp, 8
seg000:00403A93                 push    esp             ; Buffer
seg000:00403A94                 push    edi             ; Key
seg000:00403A95                 push    esi             ; Data
seg000:00403A96                 call    vTEA_Encode
seg000:00403A9B                 xchg    esi, edi
seg000:00403A9D                 loop    LoopTEA_Encode
seg000:00403A9F                 mov     eax, [esp+28h+TEA1_A]
seg000:00403AA2                 xor     eax, [esp+28h+TEA2_A]
seg000:00403AA6                 jnz     short Invalid
seg000:00403AA8                 mov     eax, [esp+28h+TEA1_B]
seg000:00403AAC                 sub     eax, [esp+28h+TEA2_B]
seg000:00403AB0                 jnz     short Invalid
seg000:00403AB2                 mov     ecx, 4
seg000:00403AB7                 repe cmpsd
seg000:00403AB9                 jecxz   short Invalid
seg000:00403ABB                 clc
seg000:00403ABC 
seg000:00403ABC loc_0_403ABC: 
seg000:00403ABC                 lea     esp, [esp+10h]
seg000:00403AC0                 popa
seg000:00403AC1                 leave
seg000:00403AC2                 retn    8

Donc pour que la premiers partie du ModifiedSerial soit considerée comme valide il faut que   vTEA_Encode(ModifiedSerial_P1,NameKey) == vTEA_Encode(NameKey,ModifiedSerial_P1) 
ModifiedSeria_P1l != NameKey



Analysons le fonctionnement de vTEA_Encode:

seg000:00403B17 vTEA_Encode     proc near
seg000:00403B17 
seg000:00403B17 InternalKey4    = dword ptr -34h
seg000:00403B17 InternalKey2    = dword ptr -30h
seg000:00403B17 InternalKey1    = dword ptr -2Ch
seg000:00403B17 InternalKey0    = dword ptr -28h
seg000:00403B17 ptrData         = dword ptr  8
seg000:00403B17 ptrKey          = dword ptr  0Ch
seg000:00403B17 Buffer          = dword ptr  10h
seg000:00403B17 
seg000:00403B17                 push    ebp
seg000:00403B18                 mov     ebp, esp
seg000:00403B1A                 pusha
seg000:00403B1B                 cld
seg000:00403B1C                 mov     esi, [ebp+ptrKey]
seg000:00403B1F                 mov     ebx, [ebp+ptrData]
seg000:00403B22                 push    [ebp+Buffer]
seg000:00403B25                 lodsd
seg000:00403B26                 push    eax
seg000:00403B27                 lodsd
seg000:00403B28                 push    eax
seg000:00403B29                 lodsd
seg000:00403B2A                 push    eax
seg000:00403B2B                 lodsd
seg000:00403B2C                 push    eax
seg000:00403B2D                 xor     edx, edx
seg000:00403B2F                 mov     esi, [ebx]
seg000:00403B31                 mov     edi, [ebx+4]
seg000:00403B34                 mov     ebp, 20h
seg000:00403B39 
seg000:00403B39 LoopTEA: 
seg000:00403B39                 add     edx, 9E3779B9h
seg000:00403B3F                 mov     eax, edi
seg000:00403B41                 mov     ecx, eax
seg000:00403B43                 mov     ebx, edi
seg000:00403B45                 rol     eax, 4
seg000:00403B48                 ror     ebx, 5
seg000:00403B4B                 add     eax, [esp+34h+InternalKey0]
seg000:00403B4F                 add     ebx, [esp+34h+InternalKey1]
seg000:00403B53                 add     ecx, edx
seg000:00403B55                 xor     ecx, eax
seg000:00403B57                 xor     ecx, ebx
seg000:00403B59                 add     esi, ecx
seg000:00403B5B                 mov     eax, esi
seg000:00403B5D                 mov     ebx, esi
seg000:00403B5F                 mov     ecx, esi
seg000:00403B61                 shl     eax, 4
seg000:00403B64                 shr     ebx, 5
seg000:00403B67                 add     eax, [esp+34h+InternalKey2]
seg000:00403B6B                 add     ebx, [esp+34h+InternalKey4]
seg000:00403B6E                 add     ecx, edx
seg000:00403B70                 xor     ecx, eax
seg000:00403B72                 xor     ecx, ebx
seg000:00403B74                 add     edi, ecx
seg000:00403B76                 dec     ebp
seg000:00403B77                 jnz     short LoopTEA
seg000:00403B79                 add     esp, 10h
seg000:00403B7C                 pop     ebx
seg000:00403B7D                 mov     [ebx], esi
seg000:00403B7F                 mov     [ebx+4], edi
seg000:00403B82                 popa
seg000:00403B83                 leave
seg000:00403B84                 retn    0Ch
seg000:00403B84 vTEA_Encode     endp

Donc vTEA_Encode calcule:
 

void code(long* v, long* k)  { 
unsigned long y=v[0],z=v[1], sum=0,   /* set up */
 delta=0x9e3779b9, n=32 ;             /* a key schedule constant */
while (n-->0) {                       /* basic cycle start */
  sum += delta ;
    y += (ROL4(z)+k[0])  xor  ( y+sum)  xor ( ROL5(z)+k[1]) ; 
    z += (SHL4(y)+k[2])  xor  ( y+sum)  xor ( SHR5(y)+k[3]) ; 
              } 
v[0]=y ; v[1]=z ; }

Donc si on remplace  k[2] et k[3] par ( k[2] xor 2^31 ) et ( k[3] xor 2^31 ) le resultat sera le meme bien que les clefs soient differentes ( si vous en doutez, faites une table de verité pour vous en convaincre ;))

Le fait que le TEA ( cette routine est tres proche de celle du TEA) permette l'utilisation de clefs "equivalentes" est decrit plus precisement dans  "Key-Schedule Cryptanalysis of IDEA, G-DES, GOST, SAFER, and Triple-DES" 


Donc [ModifiedSerial ] == [ NameKey ],
         [ModifiedSerial +4 ] == [ NameKey + 4 ],
         [ModifiedSerial +8 ] == [ NameKey  + 8]    xor 2^31,
         [ModifiedSerial + 12 ] == [ NameKey +12] xor 2^31
 



Puis les 128 derniers bits du ModifiedSerial sont verifiés:

seg000:00403A0C                 push    esi             ; Serial p2
seg000:00403A0D                 push    edi             ; Name
seg000:00403A0E                 push    esi             ; Serial p2
seg000:00403A0F                 call    CheckSerialP2
seg000:00403A14                 dec     dword ptr [esi+0Ch]
seg000:00403A17                 xor     ecx, ecx
seg000:00403A19 
seg000:00403A19 CheckSerial: 
seg000:00403A19                 mov     eax, [ecx+esi]
seg000:00403A1C                 test    eax, eax
seg000:00403A1E                 jnz     short Fin
seg000:00403A20                 add     ecx, 4
seg000:00403A23                 and     ecx, 0Fh
seg000:00403A26                 jnz     short CheckSerial

Donc le resultat de CheckSerialP2 doit etre egal a 1...


seg000:00403CAC CheckSerialP2   proc near 
seg000:00403CAC 
seg000:00403CAC Serial_         = dword ptr  8
seg000:00403CAC Name_P2         = dword ptr  0Ch
seg000:00403CAC Serial          = dword ptr  10h
seg000:00403CAC 
seg000:00403CAC                 push    ebp
seg000:00403CAD                 mov     ebp, esp
seg000:00403CAF                 pusha
seg000:00403CB0                 sub     esp, 20h
seg000:00403CB3                 mov     ecx, 4
seg000:00403CB8                 mov     edi, esp
seg000:00403CBA                 mov     esi, [ebp+Serial_]
seg000:00403CBD                 cld
seg000:00403CBE                 repe movsd
seg000:00403CC0                 mov     ecx, 4
seg000:00403CC5                 mov     ebx, edi
seg000:00403CC7                 mov     esi, [ebp+Name_P2]
seg000:00403CCA                 repe movsd
seg000:00403CCC                 xor     eax, eax
seg000:00403CCE                 mov     ecx, 4
seg000:00403CD3                 mov     edi, [ebp+Serial]
seg000:00403CD6                 repe stosd 
seg000:00403CD8                 sub     edi, 10h
seg000:00403CDB                 mov     ecx, 80h
seg000:00403CE0                 clc
seg000:00403CE1 
seg000:00403CE1 Loop: 
seg000:00403CE1                 mov     eax, 3
seg000:00403CE6 
seg000:00403CE6 _Loop1: 
seg000:00403CE6                 rcl     dword ptr [edi+eax*4], 1 
seg000:00403CE9                 dec     eax
seg000:00403CEA                 jns     short _Loop1 
seg000:00403CEC                 mov     eax, 3
seg000:00403CF1                 jnb     short _Loop2 
seg000:00403CF3                 xor     dword ptr [edi+0Ch], 87h 
seg000:00403CFA 
seg000:00403CFA _Loop2: 
seg000:00403CFA 
seg000:00403CFA                 rcl     dword ptr [esp+eax*4], 1 
seg000:00403CFD                 dec     eax
seg000:00403CFE                 jns     short _Loop2 
seg000:00403D00                 jnb     short Next
seg000:00403D02                 mov     eax, 3
seg000:00403D07 
seg000:00403D07 _Loop3: 
seg000:00403D07                 mov     edx, [ebx+eax*4] 
seg000:00403D0A                 xor     [edi+eax*4], edx
seg000:00403D0D                 dec     eax
seg000:00403D0E                 jns     short _Loop3 
seg000:00403D10 
seg000:00403D10 Next: 
seg000:00403D10                 loop    Loop
seg000:00403D12                 add     esp, 20h
seg000:00403D15                 popa
seg000:00403D16                 leave
seg000:00403D17                 retn    0Ch
seg000:00403D17 CheckSerialP2   endp

Ici aussi l'utilisation d'une matrice L : 
 

B0 B1 ... Bn-1 Bn
\/ \/ \/ \/ \/
( CheckSerialP2(B0 )n CheckSerialP2(B1 )n ... CheckSerialP2(Bn-1 )n CheckSerialP2(Bn )n ) >  An
( CheckSerialP2(B0 )n-1 CheckSerialP2B1 )n-1 ... CheckSerialP2(Bn-1 )n-1 CheckSerialP2(Bn )n-1 ) >  An-1
( ... ... ... ... ... ) > ...
( CheckSerialP2(B0 )1 CheckSerialP2(B1 )1 ... CheckSerialP2(Bn-1 )1 CheckSerialP2(Bn )1 ) > A1
( CheckSerialP2(B0 )0 CheckSerialP2(B1 )0 ... CheckSerialP2(Bn-1 )0 CheckSerialP2(Bn )0 ) > A0

... permet de determiner quelle valeur de ModifiedSerial_P2 verifie CheckSerialP2(ModifiedSerial_P2) == 1



Une fois ModifiedSerial_P1 et ModifiedSerial_P2 obtenus il suffit d'appliquer l'algo, precedement decrit, qui permet de calculer la valeur du Serial a partir de celle de ModifiedSerial 
 
Name   Amenesia
Serial 93180C843E7004FA4F749AB6E82A9E883A4C2C6FBBDF8921927E9ACBC6C885E1

Si vous trouvez une erreur ou avez une question : tchernozium@yahoo.fr