FreshDisk 2.0

By Christal, Falcon and Scarabée (The Dark Side of Chris)

Heu !
Salut.
Dis, tu pourrais me cracker FreshDisk 2.0 ?


Ben...
Non !
Si tu recherches un cracke.exe va plutôt sur un site Warez

Et si j'essaye de le cracker moi-même, tu m'aides ?

Oui, pas de problèmes...

Par quoi je peux commencer ?

Procures toi W32dasm, désassemble l'exécutable, et repère les strings Data Références qui te sembleront correspondrent soit à ce que tu auras pu observer en utilisant le programme, soit qui évoquent nettement une version Shareware. Relève les adresses, et essaye d'analyser ce que tu auras trouvé.

Le programme se lance avec cet écran :

Dans les Strings Data Ref de Wdasm, on trouve plusieurs références qui semblent directement liées à cet écran :

004951BC    "FreshDisk [Version d'"
00481427    "Bienvenue !"
00485F18    "jours d'"
004811E2    "Evaluer"
004811F2    "Annuler"
00481202    "Enregistrer"
00481212    "Infos"

En cliquant sur enregistrer, une boite apparaît :


Et en la manipulant un peu, on obtient différents messages :

00480BBC   "Veuillez inscrire le Code fournit avec votre licence."
00480C80   "Veuillez inscrire le Code fournit avec votre licence."
00480BFC   "Le Code d'Identification est correct."

00480BAF    "Le Code d'Identification est incorrect."
00480C73    "Le Code d'Identification est incorrect."

Parmi les autres références susceptibles d'être intéressantes, il y a aussi :

00480B47    "Veuillez remplir la case 'Code d'Identification'."
00480AF3    "Veuillez remplir la case 'Nom et Pr"
00481452    "1 jour d'"
0045E881    "Licence accord"
0045E89B    "Version d'"
0047814C    "La version shareware de FreshDisk limite le nombre de scripts"
0048148B    "FreshDisk est en version shareware limit"
004814CA    "Durant cette p"
0048094E    "Informations d'enregistrement "
004814A0    "jours d'utilisation et "

L'ensemble de ces éléments me permet de dire que:

- Le programme s'enregistre avec un code, probablement généré à partir du nom entré
- Il est limité à 30 jours
- Il a des fonctions limités

Bien vu, non ?


Héhé,
Facile !
Mais il fait quoi, au juste, ton programme ?

Les éléments pris en compte par FreshDisk sont :

1 - Les éléments ajoutés

·	Fichiers * (Mise dans la corbeille / suppression totale)
·	Dossiers * (Mise dans la corbeille / suppression totale)
·	Clefs dans la base de registre * (suppression totale)
·	Lignes contenues dans les Fichiers système * (suppression totale)


2 - Les éléments modifiés

·	Taille, date, Attributs des fichiers
·	Valeur des clefs dans les Fichiers système * (rétablissement de la valeur d'origine)


3 - Les éléments supprimés

·	Fichiers
·	Dossiers
·	Clefs dans la base de registre
·	Lignes contenues dans les Fichiers système

'*' = éléments désinstallables.

Et bien voici un programme qui pourrait être utile à notre quête, en lui faisant jouer le rôle d'espion lors de l'installation d'une nouvelle cible...

Maintenant, qu'est ce que tu envisages de faire ?

Heu...
Tu ferrais quoi toi ?


J'essayerai de trouver les branchements qui vont, ou évitent, certaines références " indésirables "...

Tiens, un exemple :

* Referenced by a CALL at Addresses:
|:0047F927   , :00498720   
|
:004951A4 55                      push ebp
:004951A5 8BEC                    mov ebp, esp
:004951A7 E880A4FEFF              call 0047F62C
:004951AC 803D70B9490000          cmp byte ptr [0049B970], 00
:004951B3 7513                    jne 004951C8
:004951B5 A15CA44900              mov eax, dword ptr [0049A45C]
:004951BA 8B00                    mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"FreshDisk [Version d'"
                                  |
:004951BC BAE4514900              mov edx, 004951E4

Il y a deux call qui branchent sur cette routine chargée d'afficher "FreshDisk [Version d'évaluation]" dans le bandeau de l'écran Shareware et le message " code invalide ".
On pourrait commencer par là, non ?

Si on prend le premier call, celui qui appel cette procédure de l'adresse 0047F927, on ne trouve ni saut, ni test dans les lignes au-dessus, mais deux branchements liés à des call.

Par contre le second appel est précédé d'un branchement conditionnel :

* Referenced by a (U)nconditional or (C)onditional Jump at Address 004986FE(C)

Histoire de gagner du temps, tu peux poser un BreakPoint sur 0047F927 et 004986FE, pour regarder par où passe le programme.

BreakPoint ?
Comment faut faire ?


Tu récupère sur le net (http://protools.cjb.net) un débuggeur comme SoftIce ou TRW2000 (avec lequel tu auras moins de problème de configuration avec ta carte graphique), tu cliques sur BROWSE pour sélectionner ta cible, puis sur LOAD pour lancer l'application.

Immédiatement, tu auras un écran noir (façon Old_Dos mais avec de la couleur), et tu pourras taper " BPX 47F927 " et " BPX 498720 ".
Deux choses cependant, il faudra que tu actives le pavé numérique, et te rappeler les conversions clavier QWERTY/AZERTY (pour le " a " taper " q ", pour le " z " taper " w " etc…)
A toi de jouer...

Heu...
Le premier breakpoint ne donne rien, le suivant break 37 fois !


Bon, abandonne cette piste pour le moment, mais tu avais une solution pour shunter le nag shareware en noppant le call 0042E134:

:0049831E 8BC3                    mov eax, ebx
:00498320 E80F5EF9FF              call 0042E134    > call à nopper
:00498325 8BC3                    mov eax, ebx

Voici l'explication " how to " de Falcon :

Personnellement j'utilise par défaut Wdasm pour situer le CALL qui créera le NAGSCREEN.
Avant tout, nous regardons dans les " String Data References " les références qui pourraient nous aider : ayant par exemple Nagscreen ou Version d'évaluation, …

Comme nous pouvons voir sur la copie d'écran suivante, nous avons que de chien ! (Christal n'a pas rencontré ce problème)

Dans ces cas là j'utilise une méthode que je n'ai d'ailleurs vue nulle part ailleurs, du moins avec Wdasm, mais qui a fait ces preuves.
Mon but est de trouver le call qui est utilisé pour la création du NAG (c'est souvent le cas).

Je lance WDASM, désassemble le fichier, et le charge en mémoire (menu " Debug - Load Process). Avant de l'exécuter, je pose un point d'arrêt sur Entry Point. Wdasm se place automatiquement dessus. Il ne reste en faite plus qu'a faire un " F2 " = pose du BPX.
C'est notre cas à l'adresse 4986CC

Ensuite je fais " F9 " ou " Run " : et paf il s'arrête sur notre 1ère ligne de programme. Après quoi un petit coup de " F6 " ou " AutoStep Over ". Le but est de voir sur quel CALL notre nagscreen s'affiche.
Notre programme s'arrête donc en 498741 lorsque le Nag s'affiche.
Dans ce cas nous arrêtons le process " Terminate " et nous le chargeons en posant cette fois-ci un BPX en 498741.
Après quoi nous exécutons le process " F9 ". On s'arrête donc en 498741. Il faut alors entrer dans ce call avec un " F7 " ou " StepInto " et continuer notre démarche avec " F6 ".

Idem nous nous arrêtons en 49836D. J'utilise donc la même méthode, Arrêt du process - Chargement - BPX - F9 - F7 - F6.

:0049836D E876FFFFFF              call 004982E8

Nous nous arrêtons en 498320. Et rebelotte …. Mais cette fois-ci nous voyons se créer au ralenti (pas à pas) notre joli NAGSCREEN.

:00498320 E80F5EF9FF              call 0042E134

Voici donc le call de notre Nag : en 498320. Il suffit de nopper ce CALL et bingo le nag ne s'affiche plus !


Mais virer un nag, ce n'est pas une solution en soit, juste une alternative encourageante. Passons à la string suivante :

* Possible StringData Ref from Code Obj ->"Bienvenue !"
                                  |
:00481427 BAA8154800              mov edx, 004815A8
:0048142C E8E3EDF9FF              call 00420214
etc…
* Possible StringData Ref from Code Obj ->"1 jour d'"
                                  |
:00481452 BABC154800              mov edx, 004815BC
:00481457 E8B8EDF9FF              call 00420214
:0048145C EB2D                    jmp 0048148B  -> jump en "Licence accord"

Mais comment le programme il arrive ici. Y'a pas de * Referenced by a (U)nconditional or (C)onditional Jump ou de * Referenced by a CALL ?

Pour arriver à cette procédure, le programme a utilisé un call indexé :

:0042B18F  6683B8CE01000000    CMP     WORD PTR [EAX+000001CE],00
:0042B197  7412                JZ      0042B1AB 
:0042B199  8B5DFC              MOV     EBX,[EBP-04]
:0042B19C  8B55FC              MOV     EDX,[EBP-04]
:0042B19F  8B83D0010000        MOV     EAX,[EBX+000001D0]
:0042B1A5  FF93CC010000        CALL    [EBX+000001CC]  > ici
:0042B1AB  33C0                XOR     EAX,EAX

jouer sur le saut conditionnel au-dessus va bien permettre de dépasser le call fâcheux, mais va aussi mettre la pagaille dans le programme, cette routine servant à différents affichages...
La vérité est ailleurs.

J'veux bien, mais où ?
Et pis comment tu fais pour avoir les codes dans TRW2000 ?


Pour les codes, tu tapes la commande " code on ", comme dans SoftIce, et pour une nouvelle piste, va faire un tour du coté de la boite d'enregistrement...

00480BFC    "Le Code d'Identification est correct."

Ben en partant d'une string " positive ", j'arrive ici...

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00480BA5(U)
|
:00480BEB 8BD6                    mov edx, esi
:00480BED 8B45FC                  mov eax, dword ptr [ebp-04]
:00480BF0 E897ECFFFF              call 0047F88C
:00480BF5 84C0                    test al, al
:00480BF7 7477                    je 00480C70
:00480BF9 8D45F8                  lea eax, dword ptr [ebp-08]

Possible StringData Ref from Code Obj ->"Le Code d'Identification est correct." 

Je me suis demandé où pouvait bien envoyer le JE 007480C70 :

:00480C70 8D45F8                  lea eax, dword ptr [ebp-08]

* Possible StringData Ref from Code Obj ->"Le Code d'Identification est incorrect."
                                  |
:00480C73 BAE80E4800              mov edx, 00480EE8

Bingo !
J'ai trouvé le switch code valide/code invalide.


Bravo !
Reste à trouver pourquoi et comment.
Va donc faire un tour dans le call 0047F88C, et intéresses toi à ce qui arrive à AL

* Referenced by a CALL at Addresses:  > deux appels sur cette procédure
|:0047F58A   , :00480BF0   

Une hypothèse (qui se vérifiera) l'un des call est pour le contrôle du serial via la boite d'enregistrement, l'autre pour le test " is_registered ? " avant le lancement de l'écran Shareware.

:0047F8A2 68D3F84700   push 0047F8D3                > pousse adresse sur la pile
:0047F8A7 64FF30       push dword ptr fs:[eax]      > pousse le contenu de EH sur la pile
:0047F8AA 648920       mov dword ptr fs:[eax], esp  > place ESP dans EH
:0047F8AD 33DB         xor ebx, ebx                 > EBX=0 (flag)
:0047F8AF 8B45FC       mov eax, dword ptr [ebp-04]  > place Name dans EAX
:0047F8B2 E8DDFEFFFF   call 0047F794                > génère le bon serial (en hexa)
:0047F8B7 3BC6         cmp eax, esi                 > compare les deux serials
:0047F8B9 7502         jne 0047F8BD                 > bad boy -> bl=0
:0047F8BB B301         mov bl, 01                   > flag good boy (EBX=1)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0047F8B9(C)
|
:0047F8BD 33C0        xor eax, eax                 > EAX=0
:0047F8BF 5A          pop edx                      > restaure les registres
:0047F8C0 59          pop ecx
:0047F8C1 59          pop ecx
:0047F8C2 648910      mov dword ptr fs:[eax], edx  > adresse EDX dans EH
:0047F8C5 68DAF84700  push 0047F8DA                > pousse adresse sur la pile

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0047F8D8(U)
|
:0047F8CA 8D45FC       lea eax, dword ptr [ebp-04] > eax = Name
:0047F8CD E85241F8FF   call 00403A24               > ? ? ?
:0047F8D2 C3           ret                         > retour en 0047F8DA

:0047F8D3 E9503BF8FF   jmp 00403428                > lié au push 0047F8D3
:0047F8D8 EBF0         jmp 0047F8CA
:0047F8DA 8BC3         mov eax, ebx                > flag EBX dans EAX
:0047F8DC 5E           pop esi                     > restore les registres
:0047F8DD 5B           pop ebx
:0047F8DE 59           pop ecx
:0047F8DF 5D           pop ebp
:0047F8E0 C3           ret                         > bye bye

Ces lignes demandent quand même quelques explications :

A l'entrée du call, ESI contient le serial entré sous sa forme hexadécimale et EAX le serial qu'il placera en [ebp-04], puis EAX est mis à 0.
EAX servira ensuite pour l'EH (Exception Handler) qui permettra au programme de traiter lui-même une erreur, et ce à la place de Windows (voir le texte sur les SEH à ce sujet).

Le principe, grossièrement, est le suivant :

push     offset Problème 
push     FS:[0] 
mov      FS:[0], esp
suite tout_va_bien
le programme continu
RET

Offset   Problème : 
Suite tout_va_mal
Traitement de l'erreur
Call     Exitprocess 

L'adresse poussée en 0047F7A2, qui elle-même branche sur un jmp 00403428, servira à rejoindre la procédure " y_a_un_bug ".

EBX, qui va servir de flag " Good Boy / Bad Boy ", est mis à 0.
EAX récupère le Name entré de [EBP-04].
Le Call suivant génère un serial à partir de EAX,et le place dans ce registre sous une forme hexadécimal.
EAX est comparé avec ESI, le bon serial avec le serial entré.
Si tout est OK, le flag EBX se met à 01 (du moins sa partie basse -> BL)
EAX est remis à 00 (xor eax,eax) pour être réutilisé par l'Exception handler.
0047F8DA est poussé sur la pile. Ce sera l'adresse sur laquelle va se brancher le RET en 0047F8D2 (voir le dossier sur les SEH pour mieux comprendre les mouvements de pile).
EBX (qui contient soit 00, soit 01) est mis dans EAX, et à la sortie de cette procédure la partie basse de EAX (AL) va être testée pour connaître ton statut (Glop ! Glop ! ou Pas Glop ! Pas Glop !)
Pour contourner cette protection, tu as donc le choix entre inverser (ou nopper ou tout ce que tu voudras) le saut en 0047F8B9 (75 -> 74), ou utiliser un convertisseur Hexa/décimal pour connaître le serial qui correspondra à ton Name.

Ouais !
Cool !
Merci...


Hep !
Scarabée !
Tu penses vraiment en avoir fini ?

Ben ouais ! on a le serial, on sait comment patcher le truc…
Ca roule, koa !


Pas si sur !
Es-tu bien certain qu'il n'y a rien d'autres à apprendre ?
Par exemple, le flag que nous avons trouvé...
Je doute que ce soit en permanence le registre AL qui soit sollicité pour savoir si tu es enregistré ou non...
Et partant de là, comment le programme peut-il savoir quel affichage mettre dans la boite ABOUT, et les fonctions limitées, et la time limite...
Tu ne crois pas qu'il n'y aurait pas des trucs à apprendre encore, en cherchant un peu ?
Essaye un BPX RegQueryValueExA if *(esp->8) == 'Name' pour voir...

Quoi c'est ça ?

Un bpx intelligent, il va te permettre de savoir à quel moment la base de registre est sollicitée pour récupérer le Nom et le serial (bidon ou pas) qui s'y trouve
Un utilitaire comme RegMon va te permettre de trouver à quel endroit le programme va fouiller dans la bdR :

Freshdis QueryValueEx  HKCU\Software\Mygalomaniac\FreshDisk ' christal'
Freshdis QueryValueEx  HKCU\Software\Mygalomaniac\FreshDisk
Freshdis QueryValueEx  HKCU\Software\Mygalomaniac\FreshDisk 0x77777(mon serial en hexa)
Freshdis CloseKey      HKCU\Software\Mygalomaniac\FreshDisk
Freshdis OpenKey       HKCU\Software\Mygalomaniac\FreshDisk hKey: 0xC6DB9430
Freshdis QueryValueEx  HKCU\Software\Mygalomaniac\FreshDisk
Freshdis QueryValueEx  HKCU\Software\Mygalomaniac\FreshDisk 0 0 0 0 80 EF E1 40
Freshdis CloseKey      HKCU\Software\Mygalomaniac\FreshDisk

Et un coup d'œil dans la base de registre à l'adresse obligeamment donnée par RegMon :

 HKEY_CURRENT_USER\Software\Mygalomaniac\FreshDisk 2.0\License]
"Name"       = "Christal"
"Id_Number"  = dword:00077777
"Day_one"    = hex:00,00,00,00,80,ef,e1,40

Amusant, non ?
Une autre solution aurait été de regarder tout bêtement dans les String Data references. On y trouve Name et Id_Number...

Le Bpx intelligent va seulement provoquer un break au moment où le programme va interroger le nom entré. Il suffit d'attendre est de pister un peu ce qu'il se passe.
Ainsi tu arriveras ici :

:0047F58A E8FD020000              call 0047F88C  > ca ne te rappel rien ?
:0047F58F 84C0                    test al, al    > AL= 0 -> Pas Glop !
:0047F591 740A                    je 0047F59D    > Jmp if bad Boy
:0047F593 8BD6                    mov edx, esi
:0047F595 8B45FC                  mov eax, dword ptr [ebp-04]
:0047F598 E847030000              call 0047F8E4
:0047F59D 8BC3                    mov eax, ebx

Inverse le saut en 0047F593, et tu seras enregistré.
Une autre façon de contourner la protection…

Pour autant, nous n'avons toujours pas mis la main sur le vrai Flag " is user registered ? ".

Entrons dans la call :

En traçant un peu, on trouve un

:0047F90B A170A44900              mov eax, dword ptr [0049A470]
:0047F910 C60001                  mov byte ptr [eax], 01

du genre :
if registered then true (01)

Eax va pointer sur l'adresse 0049A470, et le Mov [eax],01 va placer TRUE à cette adresse.
Le voilà, notre Flag !

On aurait pu le trouver plus vite ?

Eventuellement, en commençant par une autre String Data . Ici, tu trouveras le switch " Licence accord / Version d'"

:0045E86C A170A44900              mov eax, dword ptr [0049A470]
:0045E871 803800                  cmp byte ptr [eax], 00
:0045E874 7425                    je 0045E89B                   > switch
:0045E876 8B0D64A54900            mov ecx, dword ptr [0049A564]
:0045E87C 8B09                    mov ecx, dword ptr [ecx]
:0045E87E 8D45FC                  lea eax, dword ptr [ebp-04]

* Possible StringData Ref from Code Obj ->"Licence accord"
                                  |
:0045E881 BABCE94500              mov edx, 0045E9BC
:0045E886 E86154FAFF              call 00403CEC
:0045E88B 8B55FC                  mov edx, dword ptr [ebp-04]
:0045E88E 8B83FC010000            mov eax, dword ptr [ebx+000001FC]
:0045E894 E87B19FCFF              call 00420214
:0045E899 EB10                    jmp 0045E8AB

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

* Possible StringData Ref from Code Obj ->"Version d'"
                                  |
:0045E89B BAD8E94500              mov edx, 0045E9D8

Une petite recherche sur [0049A470], va donner plusieurs réponses :

:0047F4ED A170A44900              mov eax, dword ptr [0049A470]
:0047F4F2 C60000                  mov byte ptr [eax], 00

Invalid user, puisque le Flag est mis à 00.
En remplaçant le 00 par 01, tu auras une nouvelle façon de détourner la protection.

En plus de la comparaison user valid/ invalid, il y a deux autres tests du statut utilisateur :

:00475218 A170A44900              mov eax, dword ptr [0049A470]
:0047521D 803800                  cmp byte ptr [eax], 00

:00498363 A170A44900              mov eax, dword ptr [0049A470]
:00498368 803800                  cmp byte ptr [eax], 00

le premier est placé juste avant une string :
· Possible StringData Ref from Code Obj ->"*.dat"

Ce qui me laisse à supposer que le saut conditionnel correspond à la limitation à 5 sauvegardes, et le premier peut être à la Time Limit

Comment le savoir ?

Et bien tu copy la liste des API données par Wdasm dans le clipboard, puis tu fais une recherche dans un éditeur de texte sur " TIME ".
Tu ne trouveras que deux API pouvant faire l'affaire, dont :

* Referenced by a CALL at Addresses:
|:004087CC   , :004087F8   

* Reference To: kernel32.GetLocalTime, Ord:0000h
                                  |
:00405C5C FF2538C34900            Jmp dword ptr [0049C338]
:00405C62 8BC0                    mov eax, eax

Pose un BPX sur les deux appels à cet fonction (ou plus directement un BPX GetSystemTime), et tu arriveras ici

:004087CC E88BD4FFFF              Call 00405C5C
:004087D1 668B4C240E              mov cx, word ptr [esp+0E]  > 27
:004087D6 668B54240A              mov dx, word ptr [esp+0A]  > 07
:004087DB 668B442408              mov ax, word ptr [esp+08]  > 2000

Je pense que tu te rappelles de ce que nous avions vu dans la base de registre :

"Day_one"=   hex:00,00,00,00,80,ef,e1,40

Allons voir dans Wdasm :

* Possible StringData Ref from Code Obj ->"Day_one"
                                  |
:0047F696 BA8CF74700   mov edx, 0047F78C            > EDX = Day_one
:0047F69B 8B45FC       mov eax, dword ptr [ebp-04]
:0047F69E E8CDEBFCFF   call 0044E270                > récupère info date dans BdR

:0047F6BB 8B1554A54900 mov edx, dword ptr [0049A554]> EDX = 1D -> 29 jours
:0047F6C1 8902         mov dword ptr [edx], eax     > EAX = nb de jours  depuis instal
:0047F6C3 A154A54900   mov eax, dword ptr [0049A554]> EAX = nb de jours  depuis instal

:0047F6C8 833800       cmp dword ptr [eax], 00000000> si égale à 0 la BdR a été bidouillée
:0047F6CB 7D0B         jge 0047F6D8                 > sinon continu

:0047F6D8 A154A54900   mov eax, dword ptr [0049A554]> EAX = nb jours
:0047F6DD 833800       cmp dword ptr [eax], 00000000> si <> 0 -> good
:0047F6E0 750D         jne 0047F6EF

:0047F6EF A154A54900   mov eax, dword ptr [0049A554]> EAX = nb jours
:0047F6F4 83381D       cmp dword ptr [eax], 0000001D> inférieur à 29 ?
:0047F6F7 7E0B         jle 0047F704                 > Time not over

:0047F704 A154A54900   mov eax, dword ptr [0049A554]> EAX = nb jours
:0047F709 BA1D000000   mov edx, 0000001D            > EDX = 29d
:0047F70E 2B10         sub edx, dword ptr [eax]     > EDX - EAX
:0047F710 7105         jno 0047F717                 > si <> 0 alors good

Quelques mots d'explication :

Supposons que la date d'installation soit le 25.07.2000, et que le programme tourne depuis deux jours.

En 004087CC il est tout à fait possible de bloquer la date au jour d'installation en faisant

:004087D1 mov cx,   1F (26 en décimal)
:004087D6 mov dx,   07
:004087DB mov ax, 07D0 (2000en décimal)

Et plus de Time Limit, le programme se croira au premier jour d'utilisation.
Méthode un peu bourrin, mais qui fonctionne bien en général.

Après avoir récupéré la date courante, le programme va se rendre en 0047F696, pour tester si le temps est Over ou non.
Il récupère la date codée dans la base de registre ("Day_one"= hex:00,00,00,00,80,ef,e1,40), charge dans EDX les 29 jours d'utilisation maxi, puis le nombre de jours depuis l'installation (calculé dans le call 0044E270), vérifie que ce nombre n'est pas égal à 00 (ce qui normalement est impossible, sauf si la chaîne DAY dans la Banque de registre à été modifiée).
Ensuite il contrôle que le nombre de jours d'utilisation est bien inférieur à 29, avant de calculer le nombre de jours d'utilisation restant (EDX - EAX) pour l'afficher dans le nag shareware.

Pour bénéficier du programme éternellement, il n'y a qu'à intervenir ici :

:0047F6EF A154A54900   mov eax, dword ptr [0049A554] > EAX = nb jours
:0047F6F4 83381D       cmp dword ptr [eax], 0000001D > inférieur à 29 ?
:0047F6F7 7E0B         jle 0047F704                  > Time not over


en forçant un mov byte ptr [eax], 02 pour deux jours d'utilisation, ce qui donnera :

:0047F6EF C60002       mov eax, dword ptr [0049A554] > EAX = nb jours
:0047F6F2 90           nop
:0047F6F3 90           nop
:0047F6F4 83381D       cmp dword ptr [eax], 0000001D > inférieur à 29 ?

préférable à mon avis à un forcing du saut en 0047F6F7 vers 0047F717 (qui vous donnera un nombre de jours restants assez fantaisiste…)
Tiens !
Un dernier truc, regarde comment Falcon s'y est pris pour se débarrasser de la TimeLimit :

2ère étape : Le Time-Limite

J'utilise toujours Wdasm pour cette limitation. Dans ce cas je fais tout simplement une recherche sur le nombre 30 ou 1E en hexa. Il est donc possible qu'il existe quelque part une comparaison entre le nombre de jours restant et ces fameux 30 jours. Je fais donc une recherche sur ",0000001E" (basé sur 8 caractères). Je ne précise pas ce qu'il peut y avoir devant car je n'en sais rien ! (menu " Search - Find Text ")

Voici les différentes adresses trouvées sur lesquelles je pose un BPX !

:00409928 BA1E000000            mov edx, 0000001E

:00439DA  C786C80000001E000000  mov dword ptr [esi+000000C8], 0000001E

:0048149  B81E000000            mov eax, 0000001E

J'exécute mon soft et break en premier en 409928 ! Je trace ensuite et regarde un peu (au dessus et en dessous) si je vois quelque chose d'intéressant. Ici rien …
Je continue avec F9 et break en 481493.

Je regarde au-dessus l'adresse du jump qui a été effectué (48154C).
Je me dirige donc en 48145C et là je constate des comparaisons entre 0 et 1. Je me suis donc posé la question à savoir s'il s'agissait d'un flag pour l'enregistrement. Mais non !! En posant un BPX en 481431 et en traçant j'ai pu constater qu'il s'agissait d'une comparaison effectuée avec le nombre de jours restants !
:00481431 A1D4A44900 mov eax, dword ptr [0049A4D4]

:00481436  cmp dword ptr [eax], 00000000 ; compare le nb de jours restants en hexa avec 0
:00481439  jle 004814F4                  ; si inférieur ou égale alors nag d'expiration
:0048143F  mov eax, dword ptr [0049A4D4]
:00481444  cmp dword ptr [eax], 00000001 ; compare le nb de jours restants en hexa avec 1
:00481447  jne 0048145E                  ; si différent ou égale, nag du nombre de jours restants
…
:0048145C EB2D         jmp 0048148B

On peut donc patcher de la manière suivante :
En 481436, je fais directement un jump en 48145E de telle manière à afficher le nag que l'on supprime par la suite ;-)


Avec les strings data, les même lignes que Falcon donnent :

* Possible StringData Ref from Code Obj ->"FreshDisk est en version shareware limit"
                                  |
:0048148B 6838164800              push 00481638
:00481490 8D55F4                  lea edx, dword ptr [ebp-0C]
:00481493 B81E000000              mov eax, 0000001E
:00481498 E8DB60F8FF              call 00407578
:0048149D FF75F4                  push [ebp-0C]

* Possible StringData Ref from Code Obj ->" jours d'utilisation et "
                                  |
:004814A0 6870164800              push 00481670
:004814A5 8D55F0                  lea edx, dword ptr [ebp-10]
:004814A8 B805000000              mov eax, 00000005
:004814AD E8C660F8FF              call 00407578
:004814B2 FF75F0                  push [ebp-10]

Voilà.
Un petit tour d'horizon de ce programme.
Si tu découvres d'autres choses, n'hésites surtout pas...

Bonne continuation et bonne journée

Christal