PC Screen Tool

Défi de la Main Rouge

Mars 2000

Petit Essai de Reverse Engineering
by Christal

Beaucoup semble regretter que le sérial généré ne le soit pas sur la base du Name ou de la Company, entrés dans les deux premiers champs de la boite d'enregistrement.
Voyons si il n'y a pas moyen de remédier à cela...

Pour réussir ce petit exercice, il va donc falloir:

> Trouver à quel moment les champs des la boite d'enregistrement sont saisis (à supposer que les champs Name et Company soit récupérés, sinon il faudra essayer de trouver comment les catcher par leurs identificateurs), après l’appui sur le bouton [OK] de la boite d’enregistrement
> Contrôler la validité des caractères entrés, sachant que le sérial ne peut contenir que des caractères numériques de 0 à 9 et alphabétiques de A à F.
> Générer un sérial qui soit accepté SANS toucher à MAG.DLL ni aux tests liés au retour de cette librairie.
> Permettre de mutiples essais avec des Name/Company différents
> Afficher le sérial valide, le faire accepter et reconnaître par le programme, qui utilise la base de Registres pour déterminer le statut Utilisateur:

[HKEY_LOCAL_MACHINE\SOFTWARE\PC Screen Tools]
« RegName"
« RegCompany"
« RegNo"


La boite de Dialogue:

En premier lieu, il va falloir trouver la routine chargée de récupérer le sérial entré avant de le vérifier. Pour cela, le plus facile est d'utiliser un éditeur de Ressources (type Borland ou ExeEscope...).

Voici le script de la boite d'enregistrement:

132 DIALOG 0, 0, 309, 95
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Register PC Screen Tools"
FONT 8, "MS Sans Serif"
{
CONTROL "OK",
1, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 99, 52, 50, 14
CONTROL "Cancel", 2, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 155, 52, 50, 14
CONTROL "Name",
-1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 10, 10, 20, 8
CONTROL "Company", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 10, 24, 50, 8
CONTROL "Registration Number", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 10, 39, 65, 8
CONTROL "",
1015, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 100, 7, 196, 12
CONTROL "",
1016, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 100, 21, 196, 12
CONTROL "",
1019, "EDIT", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 100, 34, 196, 12
CONTROL "Give me a Serial Number", 1035, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 99, 71, 194, 14
CONTROL 128, -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 33, 57, 21, 20


Dans un tel script, vous avez tout un ensemble d'informations. Celles que j'ai retenue sont les suivantes:

Identificateur de la DialogBox: 132 (d)
identificateurs des trois champs de saisie: 1015 (d), 1016 (d), 1019 (d)
le bouton OK avec sa valeur égale à 1 risque d'être plus difficile à coincer...

Comme un éditeur de ressources peut retrouver le script d'une boite de dialogue, il n'y a pas de raisons que nous ne puissions pas en faire autant. Jetons un regard pudique sur ce que pourrait nous livrer un éditeur hexa:

0000 3501 5F00 0000 0000 5200 6500 6700 ..5._.....R.e.g. > coordonnées D.Box
6900 7300 7400 6500 7200 2000 5000 4300 i.s.t.e.r. .P.C.
2000 5300 6300 7200 6500 6500 6E00 2000  .S.c.r.e.e.n. .
5400 6F00 6F00 6C00 7300 0000 0800 4D00 T.o.o.l.s.....M.
5300 2000 5300 6100 6E00 7300 2000 5300 S. .S.a.n.s. .S.
6500 7200 6900 6600 0000 0000 0100 0150 e.r.i.f........P
0000 0000 6300 3400 3200 0E00 0100 FFFF ....c.4.2....... > coordonnées [OK]+ ID
8000 4F00 4B00 0000 0000 0000 0000 0150 ..O.K..........P
0000 0000 9B00 3400 3200 0E00 0200 FFFF ......4.2....... > coordonnées [cancel]+ ID
8000 4300 6100 6E00 6300 6500 6C00 0000 ..C.a.n.c.e.l...
0000 0000 0000 0250 0000 0000 0A00 0A00 .......P........ > coordonnée Name
1400 0800 FFFF FFFF 8200 4E00 6100 6D00 ..........N.a.m. > static -1
6500 0000 0000 0000 0000 0250 0000 0000 e..........P.... 
0A00 1800 3200 0800 FFFF FFFF 8200 4300 ....2.........C.
3000 6D00 7000 6100 6E00 7900 2000 2000 0.m.p.a.n.y. . .
2000 2000 0000 0000 0000 0250 0000 0000 . ........P....
0A00 2700 4100 0800 FFFF FFFF 8200 5200 ..'.A.........R.
6500 6700 6900 7300 7400 7200 6100 7400 e.g.i.s.t.r.a.t.
6900 6F00 6E00 2000 4E00 7500 6D00 6200 i.o.n. .N.u.m.b.
6500 7200 0000 0000 8000 8150 0000 0000 e.r........P.... > fin des "static"
6400 0700 C400 0C00 F703 FFFF 8100 0000 d............... > 1015 control + coord
0000 0000 8000 8150 0000 0000 6400 1500 d............... > coordonnées 2ème champ
C400 0C00 F803 FFFF 8100 0000 0000 0000 .......P....d... > 1016 control_ID
8000 8150 0000 0000 6400 2200 C400 0C00 ...............P > coordonnées 3ème champ
FB03 FFFF 8100 0000 0000 0000 0000 0150 ...............P > 1019 control_ID

(Vous aurez remarqué que les caractéristiques de chacun des scripts de champs se finissent par FFFF, ce qui est un bon point de repère...)
Si dans votre boite de Dialogue vous voulez faire "disparaître" un champ (par exemple celui de Registration Number), vous pouvez soit remplacer ces coordonnées (6400 2200 C400 0C00) par des 01 pour réduire le champ EDIT à 1 pixel, soit la rendre "invisible" en modifiant les caractéristiques WS_VISIBLE | WS_BORDER (8000 8150) qui correspondent à: champ visible avec bordure. Dans la foulée, vous pouvez remplacer le texte "registration Number" par des espaces, ou ce que vous voudrez...

Si vous avez eu l'occasion de lire un des textes de Fravia (admirablement complété par un essai de +Frog's Print) sur Screen Ruller (un petit utilitaire permettant d'obtenir les coordonnées d'un objet à l'écran), vous comprendrez l'intérêt qu'il peut y avoir à retrouver ces coordonnées dans la section ressources, et à poser ensuite un BPM Read sur celles ci...

Maintenant, petit coup d'œil dans les Dialog références de Wdasm:

Dialog: DialogID_0064
Dialog: DialogID_0084
Dialog: DialogID_0085
Dialog: DialogID_0086

Parmi d'autres, la DialogBox qui nous intéresse est ici: DialogID_0084 (132d = 84h)
Un double clic sur cette référence:

* Possible Reference to Dialog: DialogID_0084 
                                  |
:00404B48 6884000000      push 00000084  > pousse l'identificateur (ID) de la DialogBox sur la pile

* Reference To: MFC42.Ordinal:0144, Ord:0144h
                                  |
:00404B4D E8B6190000      Call 00406508
:00404B52 C706A88A4000    mov  dword ptr [esi], 00408AA8
:00404B58 8BC6            mov  eax, esi
:00404B5A 5E              pop  esi
:00404B5B C20400          ret  0004


C'est le début de la procédure d'affichage de la boite d'enregistrement.
Pour autant, ce n'est pas ce qui va être le plus intéressant, mais plutôt ce qui suit:

DialogID_0084, # of Controls=010, Caption:"Register PC Screen Tools", ClassName:""
001 - ControlID:0001, Control Class:"BUTTON" Control Text:"OK" 
002 - ControlID:0002, Control Class:"BUTTON" Control Text:"Cancel" 
003 - ControlID:FFFF, Control Class:"STATIC" Control Text:"Name" 
004 - ControlID:FFFF, Control Class:"STATIC" Control Text:Company " 
005 - ControlID:FFFF, Control Class:"STATIC" Control Text:"Registration Number" 
006 - ControlID:03F7, Control Class:"EDIT"   Control Text:"" 
007 - ControlID:03F8, Control Class:"EDIT"   Control Text:"" 
008 - ControlID:03FB, Control Class:"EDIT"   Control Text:"" 
009 - ControlID:040B, Control Class:"BUTTON" Control Text:"Give me a Serial Number" 
010 - ControlID:FFFF, Control Class:"STATIC" Control Text:""

L'identificateur du champ "Registration Number" est 03FBh (1019d).
Une recherche (fonction search) dans Wdasm va donner:

* Possible Reference to Dialog: DialogID_0084, CONTROL_ID:03FB, ""
                                  |
:00404D3C 68FB030000              push 000003FB  > pousse l'identificateur du Champ
                                                 > "Registration Number" sur la pile
:00404D41 8BCE                    mov ecx, esi

et cette routine se trouve placée un peu au dessus de:

* Possible StringData Ref from Data Obj ->"Registration successful !"
                                  |
:00404DAB 68FCA24000              push 0040A2FC
:00404DB0 8D4C240C                lea ecx, dword ptr [esp+0C]
:00404DB4 E8E7D5FFFF              call 004023A0 

Glop! Glop! Entre les deux il y a peut être notre champ de saisie du sérial...

:00404D54 E8D91A0000              Call 00406832
:00404D59 8D942470020000          lea edx, dword ptr [esp+00000270] > Name
:00404D60 8D842470010000          lea eax, dword ptr [esp+00000170] > Company
:00404D67 52                      push edx
:00404D68 8D8C24F4010000          lea ecx, dword ptr [esp+000001F4] > Sérial

Au retour du call, vous trouvez les TROIS saisies de champs, joliment complétés par les informations entrées dans les formulaires de saisie...

Le TOP! D'un même coup, nous avons toutes les informations utiles, regroupées bien gentiment...

Glop! Glop! Glop! Glop!

Que va-t-on en faire?

Et bien elles vont servir pour la seconde étape:

La fabrication du Sérial

En premier lieu, il va falloir utiliser les caractères entrés pour le Name et la Company, trier les caractères ASCII inférieurs à 0 et Supérieurs à F.
On va rajouter une option. Dans la mesure ou il est assez habituel de rentrer des infos en panachant majuscules et minuscules, la routine suivante va prendre en compte les deux cas de figures.

Pour établir la base du sérial, j'ai choisi d'en écrire un modèle dans une espace disponible du programme. Reste à trouver cette place:

Number of Objects = 0005 (dec), Imagebase = 00400000h

Name     Virt Size  Virt Offset   Raw Size   Raw Offset Characteristics

.text    000060B5    00001000     00006200    00000400     60000020
.rdata   000014A0    00008000     00001600    00006600     40000040
.data    00000818    0000A000     00000600    00007C00     C0000040
.idata   00000F3E    0000B000     00001000    00008200     C0000040
.rsrc    00003D04    0000C000     00003E00    00009200     40000040

La Virtual size de la section est 00003D04, ce qui veut dire que la mémoire qui sera allouée pour cette section sera de 00003D04 bytes. Le Virtual Offset de la section est de 0000C000, additionné à l'Image base qui vaut 00400000, ça nous donne une adresse virtuelle de 0000C000 + 00400000 = 0040C000.
La taille sur disque (Raw Size) est de 00003E00, ce qui veut dire que le code n'utilise que 00003E00 bytes dans le fichier PCST.exe. Autrement dit le code s'étale de l'adresse 0040C000 jusqu'à 0040C000 + 00003E00 = 0040FE00.
Il est probable que vous pourrez disposer de place avant l'adresse 0040FE00, si les ressources ne monopolisent pas l'ensemble de l'espace qui leur est réservé.

La taille d'une section doit être un multiple du Code, cela veut dire que le compilateur rajoute des 00 pour que celle ci ait la taille voulue, c'est le Padding.

En regardant à l'aide d'un éditeur hexadécimal, la place disponible commence à l'offset CF00. Dans Hiew, l'adresse correspondante est 0x0040FD00, soit 0x0040DF00 - 0x00400000 (image base) => 0x0000DF00 - 0x0000CF00 => 0x1000 de différence d'alignement entre l'exécutable sur le Disque dur et le programme chargé en mémoire.
Donc, si l'alignement n'est pas le même pour les deux, les adresses seront différentes quand vous éditerez le fichier avec un éditeur hexa de celles que vous verrez avec SoftIce !

Bref, il y a 0x100 (256d) octets de disponible pour notre patch...
L'image que je vais commencer par y placer va être la suivante:

ST10-00-000-0-00000000000000-00

Et correspond à la forme que doit avoir le serial. (D'autre tutoriaux, dans le cadre du défi de la Main Rouge) parleront en détail de la routine de contrôle du sérial)

Maintenant, il va falloir remplacer les 0 par les caractères acceptables du Name et de la Company, sachant:

> Que les caractères à accepter doivent être compris entre 0 et F, et entre a et f, mais transformés en majuscules.
> Que "ST10" et les "-" ne doivent pas être effacés.
> Que le nombre de caractères entrés ne doit pas permettre de dépasser la longueur du sérial-modèle
> Que l'état des registres devra être restauré à la sortie de ce patch.

Je suis loin de savoir coder proprement, et une sous routine de vérification de la validité des caractères auraient été préférable, mais voici ce que je propose:

On trouvera à l'entrée de cette routine:
ECX (Name), EAX (Company) et EDX (sérial entré)

:0040FD20  60         PUSHAD                 > sauve l'état des registres
:0040FD21  90         NOP                    
:0040FD22  BF05000000 MOV     EDI,00000005   > prépare un pointeur à 5
:0040FD27  BA00FD4000 MOV     EDX,0040FD00   > charge l'adresse de l'image du sérial
:0040FD2C  8BF0       MOV     ESI,EAX        > place le Name dans ESI
                                             > (j'aurai besoin de AL plus tard)

EAX

   

32 bits

 

ESI

 

32 bits

 

AX  

16 bits

 

 

SI

16 bits

AH

  AL

8 bits

       

Comme il me fallait un registre qui gère les caractères sur 8 bits, j’ai opté pour utiliser AL, Si ne gérant qu'au minimum des Words sur 16 bits.

:0040FD2E  03FA       ADD     EDI,EDX           > Ajoute le pointeur à l'adresse du sérial
                                                > EDI va pointer sur 0040FD005 (après ST10-)
:0040FD30  803F00     CMP     BYTE PTR [EDI],00 > fin de l'image du sérial?
                                                > celui ci se terminant par NULL
:0040FD33  7440       JZ      0040FD75          > Goto Fin
:0040FD35  803F2D     CMP     BYTE PTR [EDI],2D > le caractère suivant est-il un (-)?
:0040FD38  7438       JZ      0040FD72          > Goto Suite
:0040FD3A  8A01       MOV     AL,[ECX]          > 1 caractère de Name dans AL
:0040FD3C  3C00       CMP     AL,00             > est-ce le dernier?
:0040FD3E  7417       JZ      0040FD57          > si oui, Goto Suite1
:0040FD40  3C30       CMP     AL,30             > caractère inférieur à "0"?
:0040FD42  7C10       JL      0040FD54          > Goto Caractère_suivant
                                                > (JL saute si plus petit que…)
:0040FD44  3C46       CMP     AL,46             > caractère inférieure à "F"
:0040FD46  7E0A       JLE     0040FD52          > Goto Caractère_suivant
:0040FD48  3C61       CMP     AL,61             > caractère inférieur à "a"
:0040FD4A  7C08       JL      0040FD54          > Goto Caractère_suivant
:0040FD4C  3C66       CMP     AL,66             > caractère supérieur à "f"
:0040FD4E  7F04       JG      0040FD54          > Goto Caractère_suivant
                                                > (JG saute si plus grand que…)
:0040FD50  2C20       SUB     AL,20             > transforme caractère en majuscule     
:0040FD52  8807       MOV     [EDI],AL          > place caractère dans image

Caractère_suivant (1er champ):
:0040FD54  41         INC     ECX               > incrémente Name 
:0040FD55  EB1B       JMP     0040FD72          > boucle

Suite1:
:0040FD57  8A06       MOV     AL,[ESI]          > caractère de Company dans AL
:0040FD59  3C00       CMP     AL,00             > est ce le dernier?
:0040FD5B  7415       JZ      0040FD72          > si oui, Goto Fin
:0040FD5D  3C30       CMP     AL,30             > caractère inférieur à 0?
:0040FD5F  7C10       JL      0040FD71          > Goto Caractère_suivant
:0040FD61  3C46       CMP     AL,46             > caractère inférieur à "F"?
:0040FD63  7E0A       JLE     0040FD6F          > Goto OK_Champ2
:0040FD65  3C61       CMP     AL,61             > caractère inférieur à "a"?
:0040FD67  7C08       JL      0040FD71          > Goto Caractère_suivant
:0040FD69  3C66       CMP     AL,66             > caractère supérieur à "f"?
:0040FD6B  7F04       JG      0040FD71          > Goto Caractère_suivant
:0040FD6D  2C20       SUB     AL,20             > transforme AL en majuscule

OK_Champ2:
:0040FD6F  8807       MOV     [EDI],AL          > place caractère dans image

Caractère_suivant (2er champ):
:0040FD71  46         INC     ESI               > incrémente Company

Suite:
:0040FD72  47         INC     EDI               > incrémente Boucle
:0040FD73  EBBB       JMP     0040FD30          > boucle

Fin:
:0040FD75  E94A040000 JMP     004101C4          > vers générateur du sérial
:0040FD7A  0000       ADD     [EAX],AL          > espace disponible
:0040FD7C  0000       ADD     [EAX],AL          > espace disponible

Cette routine n'est pas très optimisée, mais elle fonctionne, et c'est malgré tout le principal...

A la fin de cette routine, le Name et la Company ont été intégré à l’image du sérial :

Name :       Christal
Company : Hello, les gars

Vont donner :

ST10-C0-000-0-A000E000000E000-A0
     Ch ris t al Hello, les g ars
Il est bien sur possible de modifier l'image pour avoir autre chose que des 0...

Il va falloir maintenant utiliser cette base pour générer un sérial valable.
Au début j’avais bien pensé utiliser la DLL qui se charge de contrôler le sérial entré, et de la « retourner », mais comme cette procédure est utilisée à d’autres moments (Affichage de la boite About, Statuts Utilisateurs…), j’ai du me résoudre à abandonner cette idée pour réécrire ailleurs la routine en question. Par contre pour ceux d’entres vous qui liront d’autres tuts sur PC Screen Tools, vous verrez qu’elle est particulièrement longue (4 pages !), et je vais avoir du mal à la loger dans les codes du programme sans quelques modifications.


Ajout d’une section :

.Pcst    00000000    00010000     00001000    0000D000     C0000040

Je vais rajouter une section de 0x1000 bytes à la suite des autres.
Pour y arriver, je me suis basé sur des textes écrits par Nody et TeeJi auxquels je vous renvoie. En deux mots, le principe est simple, on profite du Padding du à l’alignement des sections sur 0x1000 bytes, pour y rajouter les informations liées à la section à créer (principalement le nom de la section, la VirtualAddress, la SizeOfRawData, et les caractéristiques), et il ne reste plus qu’à rajouter la place nécessaire en insérant les 4096 octets supplémentaires désirés avec un éditeur hexa (Insert)...


Insertion du Générateur :

A y regarder de prés, le contrôleur de validité du sérial, aussi long soit-il, peut facilement être inséré dans notre nouvelle section. Il y a même très peu de modifications à faire.

Commençons d’abord par récupérer le code de Mag.Dll avec un éditeur hexadécimal. Une fois le début et la fin de la routine repéré, il n’y a plus qu’à faire un Copy/Paste des codes de la DLL à l'exécutable.

Ensuite, il faut procéder à quelques modification.

:10001130 8B4C2404 mov ecx, dword ptr [esp+04]

Au début de la routine de contrôle dans la DLL, ECX reçoit le sérial à valider. Il va falloir faire de même, passer notre image dans ECX, puis « retourner » deux trois petites choses, et finalement virer les contrôles de validité.

A chaque fois que la routine à finie de calculer un des nombres clés du sérial (les 14ème, 19ème, 20ème, 24ème, 26ème, 27ème, 29ème et 30ème ), le résultat (« dl ») est stocké dans un tampon ([esp+4]), pour être comparé avec son équivalent dans le sérial entré, et logé en ECX

Ces 8 calculs prévoit la possibilité que le résultat obtenu dépasse 9, et auquel cas réajuste la valeur trouvé (add, dl, 07).

:10001279 88542404  mov  byte ptr [esp+04], dl > Place dl dans le tampon de contrôle
:1000127D 7607      jbe  10001286              > SI dl > "9"
:1000127F 80C207    add  dl, 07                > alors dl = dl + 7
:10001282 88542404  mov  byte ptr [esp+04], dl > et change la valeur dans ESP+04

la modification envisagée va permettre de placer « dl » directement dans l’image du sérial final placé dans ECX, et chaque mov byte ptr [esp+04], dl, vont devenir des :

:00410225  885113  MOV [ECX+13],DL > place DL dans l'image du sérial à la 20ème place
:00410228  90      NOP             > pour garder le même nombre d’octets et ne pas
                                   > avoir à modifier les sauts conditionnels.

Après cela, il faut encore supprimer les tests de comparaisons :

:10001298 8A4113       mov    al, byte ptr [ECX+13]  > 20ème caractère du sérial entré
:1000129B 8B542404     mov   edx, dword ptr [esp+04] > récupère la valeur de DL  dans [ESP+4]
:1000129F 0FBEC0       movsx eax, al                 > place AL dans EAX
:100012A2 81E2FF000000 and   edx, 000000FF           > DL dans EDX 
:100012A8 3BC2         cmp   eax, edx                > les compare 
:100012AA 0F8561010000 jne   10001411                > et dégage si pas Glop !

Il y en a 5. Tous peuvent disparaître sans problème. Il est bien sur possible de les nopper, mais pour faire plus clean, le plus simple est de les sélectionner dans l’éditeur hexa, et de les supprimer. Il n’y a pas d’incidence sur le reste de la routine, sauts compris.
Dans la foulée, le code se trouve allégé…
Glop ! Glop !

J’avais envisagé de rajouter le nombre d’octets disparus à la fin de la section crée (ou de recalculer la longueur de la section), mais en fait ça marche très bien avec quelques octets en moins …

Cure d’amaigrissement…

Le générateur étant en place, il faut encore s’occuper de l’entrée de cette procédure, et de sa sortie.

A la tête de celle ci, il va falloir placer l’image de notre sérial dans ECX :

0137:004101C4  B900FD4000          MOV     ECX,0040FD00

et après génération du bon sérial :

0137:0041037E  61                  POPAD
0137:0041037F  BA00FD4000          MOV     EDX,0040FD00
0137:00410384  E9E349FFFF          JMP     00404D6C

Restaurer les registre
Replacer l’adresse du sérial calculé dans EDX (le Popad lui en a fait perdre la mémoire)
Et retourner au programme comme si de rien n’était.

Justement, il est temps de s’occuper de l’adressage vers notre bidouille :

:00404D54 E8D91A0000       Call 00406832 
:00404D59 8D842470010000   lea eax, dword ptr [esp+00000170] > Company
:00404D60 8D8C24F0010000   lea ecx, dword ptr [esp+000001F0] > Name
:00404D67 E9B4AF0000       jmp 0040FD20                      > Go to patch
:00404D6C 52(ad de retour) push edx       > pousse le sérial « amélioré »            
:00404D6D 50               push eax       > la company
:00404D6E 51               push ecx       > le Name
:00404D6F 90               nop            > équilibrage
:00404D70 90               nop            > (on aurait pu choisir INC EAX DEC EAX…)
:00404D71 8D4C2410         lea ecx, dword ptr [esp+10]       > continue...

Voici le sérial que j'ai obtenu:

ST10-C0-000-0-A00E0E0000D0BB-53

Il resterait encore bien d’autres choses à faire. Dans son tut, TeeJi propose une solution pour faire apparaître une message box en cliquant sur un des boutons de la boite de Dialogue "About"...
On peut cependant pallier à un inconvénient : quand la boite « registration successfull » apparaît, elle cache le 3ème champ « registration Number » où il aurait été possible d’afficher la sérial généré (histoire de voir sa bouille sans avoir à passer par la boite About !).

Ca va être la dernière modification que je vais vous proposer :

Détourner l’affichage de la MessageBox :

Le principe est simple, comme la message box existe, il suffit de mettre la main sur les paramètres poussés sur la pile avant son appel, et de remplacer l’adresse de « Registration successfull » par l’adresse où se trouve logé notre sérial...

* Possible StringData Ref from Data Obj ->"Registration successful !"
                                  |
:00404DAB 68FCA24000           push 0040A2FC           > et Voilà !
:00404DB0 8D4C240C             lea ecx, dword ptr [esp+0C]
:00404DB4 E8E7D5FFFF           call 004023A0           > affichage MessageBox

Et il ne reste qu’à modifier le Push 0040A2FC par un Push 0040FD00, et le tour est joué :

:00404DAB  6800FD4000          PUSH    0040FD00
:00404DB0  8D4C240C            LEA     ECX,[ESP+0C]
:00404DB4  E8E7D5FFFF          CALL    004023A0

Pas utile, mais joli...

Bonne journée
Christal