Le Generateur de Codes de Second Copy 97

La base du sérial est composée des 4 premiers chiffres du code que vous avez entré associés à ceux que vous avez entré dans le champ "nom".
Par exemple 1234christal.

:00460D32  0000                ADD     [EAX],AL      > entrée de la precédure
:00460D34  55                  PUSH    EBP
:00460D35  8BEC                MOV     EBP,ESP
:00460D37  83C4E4              ADD     ESP,-1C
:00460D3A  53                  PUSH    EBX           > code entré
:00460D3B  56                  PUSH    ESI           > nom entré
:00460D3C  57                  PUSH    EDI
:00460D3D  33C9                XOR     ECX,ECX
:00460D3F  894DE4              MOV     [EBP-1C],ECX  > 00
:00460D42  894DF0              MOV     [EBP-10],ECX  > 00
:00460D45  894DEC              MOV     [EBP-14],ECX  > 00
:00460D48  8955F8              MOV     [EBP-08],EDX  > 00
:00460D4B  8945FC              MOV     [EBP-04],EAX  > 1234christal
:00460D4E  33C0                XOR     EAX,EAX
:00460D50  55                  PUSH    EBP
:00460D51  68410E4600          PUSH    00460E41
:00460D56  64FF30              PUSH    DWORD PTR FS:[EAX]
:00460D59  648920              MOV     FS:[EAX],ESP
:00460D5C  8B1D90BC4700        MOV     EBX,[0047BC90] > EBX = 7ECA c'est une constante
:00460D62  8B45FC              MOV     EAX,[EBP-04]   > 1234christal
:00460D65  E8D22EFAFF          CALL    00403C3C       > vérif si caractères présent
:00460D6A  85C0                TEST    EAX,EAX        > non
:00460D6C  7E4E                JLE     00460DBC       > saute vers "champs vides"
:00460D6E  8945E8              MOV     [EBP-18],EAX   >
:00460D71  C745F401000000      MOV     DWORD PTR [EBP-0C],00000001

Et voici la routine en tant que telle de calcul du sérial
Au départ EBX vaut 7ECA.

:00460D78  33C0                XOR     EAX,EAX            > EAX = 0
:00460D7A  55                  PUSH    EBP                
:00460D7B  68A50D4600          PUSH    00460DA5
:00460D80  64FF30              PUSH    DWORD PTR FS:[EAX]
:00460D83  648920              MOV     FS:[EAX],ESP
:00460D86  8B45FC              MOV     EAX,[EBP-04]       > 1234christal
:00460D89  8B55F4              MOV     EDX,[EBP-0C]       > caractère suivant
:00460D8C  0FB64410FF          MOVZX   EAX, [EDX+EAX-01]  > valeur ASCII du caractère
:00460D91  F7EB                IMUL    EBX                > EBX * EAX = EAX
:00460D93  030590BC4700        ADD     EAX,[0047BC90]     > ajoute 7ECA à EAX
:00460D99  8BD8                MOV     EBX,EAX            > nouvelle base EBX
:00460D9B  33C0                XOR     EAX,EAX            > EAX réinitialisé
:00460D9D  5A                  POP     EDX                
:00460D9E  59                  POP     ECX                
:00460D9F  59                  POP     ECX                
:00460DA0  648910              MOV     FS:[EAX],EDX       
:00460DA3  EB0F                JMP     00460DB4           > saute tjs !!!???
:00460DA5  E93A24FAFF          JMP     004031E4           > inutile ???
:00460DAA  BBE7030000          MOV     EBX,000003E7       > nouvelle base de EBX ??
:00460DAF  E8D426FAFF          CALL    00403488
:00460DB4  FF45F4              INC     DWORD PTR [EBP-0C] > compteur de boucle
:00460DB7  FF4DE8              DEC     DWORD PTR [EBP-18] > compteur de boucle
:00460DBA  75BC                JNZ     00460D78           > boucle

1234christal donne en ASCII

 1  2  3  4  c  h  r  i  s  t  a  l
31 32 33 34 63 68 72 69 73 74 61 6C

00460D91  IMUL EBX      -> 31 x 7ECA       = 1844AA
00460D93  ADD EAX,7ECA  -> 1844AA + 7ECA   = 18C374

cette valeur est placée dans EAX (460D93), puis dans EBX (00460D9B)
On passe à la lettre suivante avec EBX = 18C374

00460D91  IMUL EBX      -> 32 x 18C374     = 4D62CA8
00460D93  ADD EAX,7ECA  -> 4D62CA8 + 7ECA  = 4D6AB72

et ainsi de suite...

00460D91  IMUL EBX      -> 33 x 4D6AB72    = F6C427B6
00460D93  ADD EAX,7ECA  -> F6C427B6 + 7ECA = F6C4A780

Par contre, si vous utilisez une calculatrice hexadécimale, arrivé à une valeur supérieure à FFFFFFFF, vous serez OverFlow parce que vous aurez dépassé la taille d'un Dword.

0xF6C4A780         =  4140082816d
4140082816d x 52d  =  215284306432d

Comment IMUL gère t il les multiplications supérieures à 0xFFFFFFFF (= 4294967295d)?
Et bien d'après ce qu'il me semble avoir compris, on pourrait décomposer le fonctionnement de IMUL ainsi:

Cette opérande utilise les registres EAX et EDX.
EAX reçoit le résultat de la multiplication, et EDX la "retenue" quand le résultat dépasse 0xFFFFFFFF.

Par exemple, 33 x 4D6AB72 = F6C427B6.
Le résultat est inférieure à FFFFFFFF
EAX= 0F6C427B6
EDX= 0

F6C4A780 x 34 = ??? (4140082816d x 52d = 215284306432d).
Cette fois ci le résultat va dépasser FFFFFFFF

EAX = 1FF1D200 (535941632d)
EDX = FFFFFFFE (4294967294d)

Donc à chaque fois que IMUL va dépasser la valeur d'un Dword, EAX ne conservera que le reste de l'opération

00460D91  IMUL EBX      -> 34 x F6C4A780   => 1FF1D200 
00460D93  ADD EAX,7ECA  ->                 => 1FF2F0CA

et ainsi de suite jusqu'au dernier caractère du nom entré:

00460D91  IMUL EBX      -> D77C6650
00460D93  ADD EAX,7ECA  -> D77CE51A

Or le bon sérial, tel qu'il devrait être entré dans la boite d'enregistrement est:

Serial Number=1234-D77C-E51A

Voilà donc comment le sérial va être calculé, et il est facile maintenant de créer un générateur de codes, pour peu que vous maîtrisiez la multiplication 32 bits. Vous trouverez ici un
source ASM d'un tel KeyMaker.