Jpeg Optimizer 3.50

 

Written by:
D.LiriUm TrEs MinCe

 

   

A propos de la protection:

Serial protection ....

 
Le Tut...

Salut les gars! :)

Arf!
J'me marre. Dans ce prog, Y zoNt voulu faire uNe protec d'eNfer eN pétaNt uN checksum sur leur prog mais tu vas voir Ke c Ke dalle à cracker!!!

BoN, oN commeNce:

Après avoir reNtré uN code bidoN (pour moi, 123456) daNs leur dialogbox (y a pas de Nom à m&tre), oN passe daNs Softice (ceux ki saveNt pas KomeNt faire, zoNt qu'à laisser tomber...) & oN m& uN breakpoiNt sur Hmemcpy.

EN cliquaNt sur le boutoN "register" de la dialogbox, Sice va sortir de sa boite. Fais des F12 (7 fois) pour arriver daNs les codes du proggy, pis trace comme uN malade pour trouver où y zoNt mis la messagebox "INcorrect registratioN Code".

:004290ED 8D95BCFEFFFF    lea edx, dword ptr [ebp+FFFFFEBC]
:004290F3 8B0D84484800    mov ecx, dword ptr [00484884]
:004290F9 A1D8494900      mov eax, dword ptr [004949D8]
:004290FE E845DD0300      call 00466E48      -> le Bug !

C good?

Là, c facile, t'as qu'à chercher le Jmp qui évite de se reNdre daNs c&te partie du code, & pis à l'iNverser. T'auras droit à uNe belle boite "ThaNck You For registeriNg". Ya poa de Koi!

* RefereNced by a (U)NcoNditioNal or (C)oNditioNal Jump at Address:
|:00428F70(C)  -> saut qui doit perm&tre d'éviter d'aller eN "code iNvalide"

:00428F68 E8F3FC0100   call 00448C60 
:00428F6D 59           pop ecx
:00428F6E 84C9         test cl, cl   > si cl = 0
:00428F70 0F8440010000 je 004290B6   > saute eN code iNvalide

BoN tu peux essayer de patcher de suite toN prog, mais faudrait d'abord êtes sur Ke t'es pas seulemeNt eN traiN de dérouter l'affichage code valide/code iNvalide, mais Ke t'as fait uN crack vrai de vrai, & qu't'es pas uN bourriN!

BoN, tu relaNces le soft eN ayaNt placé uN bpx sur le je qui eNvoie vers la message box "code iNvalide". Pas d'bol, y a pas de break, & t'as toujours "UNregistered" qui s'affiche daNs le baNdeau du prog.

C poa grave. ON va faire aut chose.
Tu rem&s uN sérial (poa l'vrai, tu l'coNNais pas! Arf! MDR! J), & pis tu clic sur le boutoN.
BoNg! T'es daNs SI. Alors là, tu regardes uN peu au-dessus.

Yop! t'as uN call qui va décider si CL va être à 0 ou 1. & au cas ou t'as pas compris, c'est justemeNt ce CL qui va provoKer le jmp (ou poa) vers la routiNe "INcorrect Reg Code".

BoN, tu pètes uN breakpoiNt sur le call, pis tu vas tracer dedaNs au prochaiN passage (si tu sais poa KomeNt faire, beN laisse tomber! Lol :)

Ayez, c boN?
Là, t'as qu'à tracer comme uN diNgue pour trouver commeNt quaNd CL va être mis à 0. BeN tu vas vite te reNdre compte Ke c'est sûremeNt poa le boN call cui-ci. Par coNtre si tu regardes eNcore uN peu plus haut, au dessus du test cl,cl, tu vas voir:

:00428F48 52             push edx          > le code KoN a eNtré
:00428F49 E8FE0B0000     call 00429B4C     > à visiter!
:00428F4E 59             pop ecx           > vire ecx de la pile
:00428F4F 84C0           test al, al       > test AL
:00428F51 7504           jNe 00428F57      > si al=0 alors eax=0
:00428F53 33C0           xor eax, eax      > le code est faux
:00428F55 EB05           jmp 00428F5C      > va vers l'aut call
:00428F57 B801000000     mov eax, 00000001 > si eax=1 c good!


Là eNcore çs sert à rieN de chaNger le jNe eN je, va falloir aller voir daNs le call ce ki se passe avec AL, & à la fiN du call, tu vas voir:

:00429BD8 84C0           test al, al      > al = 0 ?
:00429BDA 7404           je 00429BE0      > si oui va eN 9BEA
:00429BDC B001           mov al, 01       > si NoN, AL=1
:00429BDE EB0C           jmp 00429BEC     > évite le xor eax, eax
:00429BE0 poa la place   mov dword ptr [00484888], 9603BCEB
:00429BEA 33C0           xor eax, eax     > m& EAX à 0

BeN j'espère Ke tu compreNds ce ke ça veut dire?
C fiNi. Y a pus Ka chaNger le JE 00249BDA par uN JNE, avec uN éditeur hexa.

BoN, KaN tu relaNces, le prog eNvoi uN Nag de merde qui te dit"AbNormal program termiNatioN"

Ouarf! Les KoNs, zoNt mis uN checksum. Tu vas voir KomeNt koN va le faire sauter leur CRC.
BoN, si t'as pas lu le tut de Christal sur HelpBldr tu vas rieN compreNdre, mais le checksum, daNs ce cas, y fait Ke compter, c-a-d qu'à la sortie du checksum y comparera si il a bieN le boN "poids" d'oct&s. Kom oN a chaNgé uN JE (74) eN JNE (75), oN a 1 eN plus, doNc va falloir eNlever 1 KelKe part où le prog ira pus. TieN! DaNs la routiNe "iNcorrect Reg Code" . Tu trouves uN truc facile à chaNger, pis tu lui eNlèves 1. Moi j'ai choisi:

:004290EA 59 pop ecx Ke j'ai remplacé par :004290EA 58 pop eax

Tu relaNces le prog & C good! Ya pus de ENregistered daNs la barre d'écraN!
That's all Folk!!!

J'espère Ke t'auras appris qque chose en lisaNt ce texte.

Allez @+


Hello D.LiriUm TrèS MinCe,

Très jolie présentation, mais il me semble l'avoir déjà vu quelque part…
Joli style également…

Ton texte est intéressant, mais je crois qu'il y a encore moyen de s'amuser un peu avec ce programme…

Le patch que tu proposes supprime bien le "Unregistered" dans le bandeau d'écran. Il lève également des fonctions limitées, par contre les Items Register du menu
Help, et du sous-menu About sont encore présentes.

Refaisons ensemble un tour d'horizon des "Bugs":

Infection:

· Boite d'enregistrement avec un seul champ pour l'entrée d'un sérial, sans limitation de longueur
· Un item "Register" dans le menu Help, et dans le sous-menu About
· Fonctions différentes entre la version shareware, et la Full version:
 

> The Registered Version enables batch processing ie compressing multiple files at one time.
> The Registered Version enables MagiCompression.
> The Trial Version writes a small invisible advertisement into the JPEG file.
(Compressed with JPEG Optimizer 3.05, qui n'apparaît plus ensuite)

· Time limit, n'empéchant pas le programme de fonctionner, mais ajoutant le nombre de jours de "retard" dans l'acquittement de la contribution due, dans le bandeau d'écran.
· Et bien sur le checksum…

Commençons par le sérial.

Concernant les codes universels, il peut se présenter de nombreux cas de figure:
 

· le sérial est en toute lettres dans les String Data Références (rare)
· le bon sérial est codé (ou non) et comparé avec celui entré
· le code entré est comparé bit à bit avec les bonnes valeurs
· etc…

Pour délimiter la zone de recherche, je procède comme toi en posant un bpx hmemcpy, et en cherchant l'adresse où la boite "code invalide" va apparaître…
Puis je recommence en traçant
doucement, pour arriver à ceci:

:00428F33 83F806     cmp eax, 00000006            > une comparaison avec 6 ?
:00428F36 751B        jne 00428F53                > et si le flag Z =0 -> eax=0
:00428F38 837DF800    cmp dword ptr [ebp-08], 00000000
:00428F3C 7405        je 00428F43                 > edx pointera vers 0047E1F3
:00428F3E 8B55F8      mov edx, dword ptr [ebp-08]
:00428F41 EB05        jmp 00428F48                > va pousser edx sur la pile
:00428F43 BAF3E14700  mov edx, 0047E1F3
:00428F48 52          push edx                    > edx poussé sur la pile
:00428F49 E8FE0B0000  call 00429B4C               > ??????
:00428F4E 59          pop ecx                     > dépile edx
:00428F4F 84C0        test al, al                 > test al en sortie de call
:00428F51 7504        jne 00428F57                > si al= 0
:00428F53 33C0        xor eax, eax                > eax = 0
:00428F55 EB05        jmp 00428F5C                > va vers ????
:00428F57 B801000000  mov eax, 00000001           > sinon eax = 1

Dans cette portion du code, le cmp eax, 06 peut déjà attirer l'attention, et je crois que tu as eu de la chance en entrant un code 123456 dont le nombre de caractères correspondait justement à celui attendu…
Ensuite les xor eax,eax, jmp 00428F5C, mov eax, 01 m'ont également mis en alerte: Cela ressemble à un très classique "drapeau code OK" -> call/test/jump

Comme tu l'a trouvé, le call 00429B4C est à visiter:

Mais l'une des parties du listing SoftIce qui m'a intéressé est juste un peu plus haut que la tienne:

:00429B85 83F846                  cmp eax, 00000046
:00429B88 7547                    jne 00429BD1
:00429B8A 0FBE4301                movsx eax, byte ptr [ebx+01]
:00429B8E 50                      push eax
:00429B8F E8B0580400              call 0046F444
:00429B94 59                      pop ecx
:00429B95 83F859                  cmp eax, 00000059
:00429B98 7537                    jne 00429BD1
:00429B9A 0FBE5302                movsx edx, byte ptr [ebx+02]
:00429B9E 83FA39                  cmp edx, 00000039
:00429BA1 752E                    jne 00429BD1
:00429BA3 0FBE4B03                movsx ecx, byte ptr [ebx+03]
:00429BA7 83F932                  cmp ecx, 00000032
:00429BAA 7525                    jne 00429BD1
:00429BAC 0FBE4304                movsx eax, byte ptr [ebx+04]
:00429BB0 83F838                  cmp eax, 00000038
:00429BB3 751C                    jne 00429BD1
:00429BB5 0FBE5305                movsx edx, byte ptr [ebx+05]
:00429BB9 83FA31                  cmp edx, 00000031
:00429BBC 7513                    jne 00429BD1
:00429BBE C705884848001443FC69    mov dword ptr [00484888], 69FC4314
:00429BC8 E80FAAFDFF              call 004045DC
:00429BCD B001                    mov al, 01
:00429BCF EB1B                    jmp 00429BEC

Le sérial devant comporter 6 caractères, il y a justement des [ebx+XX] allant de 1 à 5, avec à chaque fois une comparaison avec une valeur fixe et différente, soit 46h, 59h, 39h, 32h, 38h, 31h, et systématiquement un branchement en cas d'égalité fausse vers 00429BD1, puis un mov al,01.
Je crois qu'il n'en faut pas plus…
A aller trop vite, tu es passé sur la routine de comparaison du sérial, caractère par caractère. Ce qui nous donne 46 hexa = F Ascii 59 hexa = Y Ascii etc… pour obtenir YF9281.
Entre ce bon sérial, et te voilà enregistré.

Revenons un peu au début de ce call.
Dés l'entrée de celui ci, tu trouves:

:00429B59 8A10    mov dl, byte ptr [eax]    > 1er caract du sérial dans dl
:00429B5B 8813    mov byte ptr [ebx], dl    > met dl dans EBX
:00429B5D 8A4801  mov cl, byte ptr [eax+01] > second caract dans cl
:00429B60 884B01  mov byte ptr [ebx+01], cl > met cl dans EBX+1
:00429B63 8A5002  mov dl, byte ptr [eax+02] > etc...
:00429B66 885302  mov byte ptr [ebx+02], dl
:00429B69 8A4803  mov cl, byte ptr [eax+03]
:00429B6C 884B03  mov byte ptr [ebx+03], cl
:00429B6F 8A5004  mov dl, byte ptr [eax+04]
:00429B72 885304  mov byte ptr [ebx+04], dl
:00429B75 8A4005  mov al, byte ptr [eax+05]
:00429B78 884305  mov byte ptr [ebx+05], al
:00429B7B 0FBE0B  movsx ecx, byte ptr [ebx] > met le contenu de EBX dans ecx

Soit un (très indiscret, et très laborieux) transvasement du code de l' adresse pointée par EAX dans celle pointée par EBX, puis dans un call suivant:

:0042BB3A 83FA06                  cmp edx, 00000006       > 6 caractères?
:0042BB3D 7CF6                    jl 0042BB35
:0042BB3F 0FBE0B                  movsx ecx, byte ptr [ebx]
:0042BB42 83F93A                  cmp ecx, 0000003A       > 3a = :
:0042BB45 7548                    jne 0042BB8F            > vers code invalide
:0042BB47 0FBE4301                movsx eax, byte ptr [ebx+01]
:0042BB4B 83F83D                  cmp eax, 0000003D
:0042BB4E 753F                    jne 0042BB8F
:0042BB50 0FBE5302                movsx edx, byte ptr [ebx+02]
:0042BB54 83FA55                  cmp edx, 00000055
:0042BB57 7536                    jne 0042BB8F
:0042BB59 0FBE4B03                movsx ecx, byte ptr [ebx+03]
:0042BB5D 83F959                  cmp ecx, 00000059
:0042BB60 752D                    jne 0042BB8F
:0042BB62 0FBE4304                movsx eax, byte ptr [ebx+04]
:0042BB66 83F859                  cmp eax, 00000059
:0042BB69 7524                    jne 0042BB8F
:0042BB6B 0FBE5305                movsx edx, byte ptr [ebx+05]
:0042BB6F 83FA5F                  cmp edx, 0000005F
:0042BB72 751B                    jne 0042BB8F
:0042BB74 C705884848001443FC69    mov dword ptr [00484888], 69FC4314 > Hey
:0042BB7E C605F447480001          mov byte ptr [004847F4], 01        > Ho Ho !
:0042BB85 E8528AFDFF              call 004045DC
:0042BB8A B001                    mov al, 01
:0042BB8C 5B                      pop ebx
:0042BB8D 5D                      pop ebp
:0042BB8E C3                      ret

Exactement le même type de routine que celle que nous venons déjà de voir, et qui "produit" cette fois-ci un code de ce type: :=UYY_
Par contre, si tu rentres ce code, tu n'obtiendras que la boite "code invalide". Je doute portant que ces lignes ne servent à rien.

:0042BB2D 59                      pop ecx
:0042BB2E 884301                  mov byte ptr [ebx+01], al
:0042BB31 33D2                    xor edx, edx
:0042BB33 8BC3                    mov eax, ebx
:0042BB35 80306D                  xor byte ptr [eax], 6D
:0042BB38 42                      inc edx
:0042BB39 40                      inc eax
:0042BB3A 83FA06                  cmp edx, 00000006
:0042BB3D 7CF6                    jl 0042BB35

En regardant juste au dessus, un étrange Xor [eax],6D pourrait bien ressembler à un principe de cryptage …
Fais un "d ebx", et tu verras le sérial que tu as entré, puis trace doucement avec F10, et tu vas voir ton code se faire crypter: 123456 va devenir \_^YX[, pour ensuite être comparé comme on l'a déjà vu.
Ce type de cryptage peut facilement être "retourné" puisqu'un"1 xor 6D" va donner \, un "\ xor 6D" va donner 1. Il suffit donc d'entrer le code calculé (soit :=UYY_) et de regarder par un "d edx" le bon sérial apparaître (soit WP8442). Mais pourquoi celui ci a-t-il été crypté? Il y a certainement une raison…
Bref! Nous voici avec deux bons sérials à entrer, et qui vont s'inscrire dans la base de registre en [HKEY_CURRENT_USER\Software\XA Tech\JpegOpt].
Ainsi, pour revenir à la version Unregistered, il suffit de se placer sur Code=WP8442 et de supprimer le contenu de Code.

LE Flag Utilisateur Enregistré

Le bandeau - Unregistered est affiché, ou non, après le contrôle de la validité du code qui se trouve dans la base de registre. Le programme récupère le code qui s'y trouve (ou ne s'y trouve pas) par RegQueryValueExA, et si un code y est bien présent, le rapatrie dans EDI:

* Reference To: ADVAPI32.RegQueryValueExA, Ord:0000h
                                  |
:0045B527 E8BCAE0100              Call 004763E8
:0045B52C 85C0                    test eax, eax

L'affichage se fait ensuite, et par un des ShowWindow que j'avais vu dans la liste des fonctions importées, comme j'en aurais la confirmation en posant un bpx sur cette API (break, F12 -> @004503CE). La modification que tu as apportée en 00429BDA (le JE à changer en JNE) permet au programme de fonctionner pleinement, et sans aucune limitation. Le flag utilisateur, ou son équivalent, est donc placé après ce jump et au plus tard avant l'ouverture d'un fichier, puisque dans sa version shareware l'icône-bitmap "auto" est (et reste) grisée, alors que dans la version enregistrée (ou patchée) l'icône devient active. Le plus probable est que ce flag est mis en place dans la foulée de la validation du sérial.

:004042C5 E896490400  call 00448C60
:004042CA 837DF400    cmp dword ptr [ebp-0C], 00000000 > récupère le contenu de code dans la
                                                       > BdR et si code est non vide c'est ok
:004042CE 7405        je 004042D5 > reg/unreg
:004042D0 8B4DF4      mov ecx, dword ptr [ebp-0C]
:004042D3 EB05        jmp 004042DA
:004042D5 B9E8844700              mov ecx, 004784E8
:004042DA 51                      push ecx
:004042DB E86C580200              call 00429B4C > contrôle du code
:004042E0 59                      pop ecx
:004042E1 84C0                    test al, al   > contrôle validité du code
:004042E3 0F85E8010000            jne 004044D1  > vers Version Enregistrée
:004042E9 66C7853CFFFFFFA001      mov word ptr [ebp+FFFFFF3C], 01A0
:004042F2 33C0                    xor eax, eax
:004042F4 89856CFFFFFF            mov dword ptr [ebp+FFFFFF6C], eax
:004042FA 8D956CFFFFFF            lea edx, dword ptr [ebp+FFFFFF6C]
:00404300 FF8548FFFFFF            inc dword ptr [ebp+FFFFFF48]
:00404306 8B3DF8404800            mov edi, dword ptr [004840F8]
:0040430C 8BC7                    mov eax, edi
:0040430E E855DC0300              call 00441F68
:00404313 8D956CFFFFFF            lea edx, dword ptr [ebp+FFFFFF6C]
:00404319 52                      push edx

* Possible StringData Ref from Data Obj ->" - Unregistered"


Pour le contrôle du code, avant le test "- unregistered", on retrouve un call déjà connu

:00429BB5 0FBE5305                movsx edx, byte ptr [ebx+05]
:00429BB9 83FA31                  cmp edx, 00000031
:00429BBC 7513                    jne 00429BD1
:00429BBE C705884848001443FC69    mov dword ptr [00484888], 69FC4314 (!)
:00429BC8 E80FAAFDFF              call 004045DC
:00429BCD B001                    mov al, 01
:00429BCF EB1B                    jmp 00429BEC

C'est celui qui a servi à la validation du sérial entré dans la boite d'enregistrement, et qui permet de confirmer que la modification réalisée va bien servir à lancer le programme en version complète. Il n'en reste pas moins qu'il doit y avoir un autre test de l'état utilisateur enregistré puisque dans la Full Version, les items du menu Help ne comptent plus les "Register", et qu'il n'y aura plus d'appels au call 00429B4C, celui ci n'étant sollicité que deux fois (validation du sérial, et contrôle du code utilisateur).

Ce drapeau utilisateur, il m'avait semblé en apercevoir dans les 2 routines de contrôle du code, à la fin de la validation des sérials:

:0042BB74 C705884848001443FC69    mov dword ptr [00484888], 69FC4314
:0042BB7E C605F447480001          mov byte ptr [004847F4], 01
:0042BB85 E8528AFDFF              call 004045DC
:0042BB8A B001                    mov al, 01

Par contre entre ces deux routines de validation du code, celle ci dispose en plus d'un mov dword ptr [004847F4],01. Il s'agit de la version avec sérial crypté. Ce Flag ne servira qu'un seule fois, et en mettant tout une série d'autres drapeaux à 01 dans le call suivant. On se perd ensuite dans les méandres des call indirects… Mais il y a fort à parier que ce sérial crypté ouvre plus d'opportunités que son petit frère…

Suivant votre état utilisateur, [00484888] vaudra 9603BCEB dans la version Unregistered, et 69FC4314 dans l'autre cas, et servira au moment de l'utilisation des fonctions désactivées.


Les Fonctions désactivées

La full version autorise la multi-sélection, l'accès à la touche "Auto", et ne rajoute aucune signature aux fichiers JPEG qui sont créés. Dans ces trois cas, il faut bien que le programme sache s'il est enregistré ou non. Nous avons déjà vu quel est ce fameux Flag Registered.

[00484888] est tout d'abord mis à 9603BCEB en 0042C473, puis le programme ira contrôler l'état utilisateur (via le call 00429B4C), et pourra remplacer cette valeur par 69FC4314,suivant le statut reg/unreg.

Par deux fois, ensuite, il ferra encore un contrôle, en 00429BE0 et 004046AF, à chaque fois pour vérifier lequel des deux sérials a été entré

:00429BD1 53                   push ebx
:00429BD2 E8391F0000           call 0042BB10  > contrôle du code crypté
:00429BD7 59                   pop ecx
:00429BD8 84C0                 test al, al    > Al modifié
:00429BDA 7404                 je 00429BE0
:00429BDC B001                 mov al, 01     > flag code oK
:00429BDE EB0C                 jmp 00429BEC
:00429BE0 C70588484800EBBC0396 mov dword ptr [00484888], 9603BCEB > Unreg

En plaçant systématiquement 69FC4314 dans les mov dword ptr [00484888], tu pourras disposer de toutes les fonctions du programme, mais "- Unregistered" et les Items Register n'auront pas disparus pour autant…

Il y a un autre drapeau utilisateur Reg/Unreg qui se trouve placé dans la routine Time expired:
mov byte ptr [00484864], 01 en 004044CA.
En faisant en sorte qu'il ne soit jamais égal à 01, tu pourras disposer de toutes les fonctions du programme, et ce bien plus facilement que dans le cas vu ci dessus, puisqu'il n'y aura qu'une seule petite modification à faire en changeant le 01 en 00…


La Time Limit

Il semble ( seul le
Vrai temps qui passe pourrait le confirmer) que la Time Limit ne serve qu'à indiquer le nombre de jours passés, au delà de la période d'essai, mais sans conséquence apparente…
Par un bpx GetLocalTime (classique mais efficace), comme le confirme les fonctions importées, tu vas pouvoir arriver dans la routine suivante (le premier Call après l'arrivée dans les codes de programme):

:0047347F 8B7510   mov esi, dword ptr [ebp+10] > le jour
:00473482 8B5D0C   mov ebx, dword ptr [ebp+0C] > le mois - 1 (!)
:00473485 8B7D08   mov edi, dword ptr [ebp+08] > 99

Si tu modifies la date à ce niveau, tu pourras faire croire ce que tu veux à Jpeg Optimizer:

Par exemple en remplaçant le mov ebx, dword ptr [ebp+0C] par un mov ebx, 0B le mois courant sera perpétuellement celui de Novembre, et en bloquant l'année sur 99, terminé le temps qui passe…
En faisant quand même attention à respecter le nombre d'octets…

Tu peux aussi intervenir au niveau de l'affichage du nombre de jours d'utilisation au delà de la période limite des 30 jours. En recherchant dans les String Data References, tu trouveras cette ref:

· Possible StringData Ref from Data Obj ->" for %d days"
  Attention au drapeau  -> mov byte ptr [00484864], 01	


Et un peu au-dessus:

:004043A3 E8ACF20600    call 00473654      > appel GetLocalTime
:004043A8 59            pop ecx
:004043A9 898524FFFFFF  mov dword ptr [ebp+FFFFFF24], eax
:004043AF 8B8524FFFFFF  mov eax, dword ptr [ebp+FFFFFF24]
:004043B5 2BC6          sub eax, esi       > esi = date instal
:004043B7 B980510100    mov ecx, 00015180
:004043BC 99            cdq
:004043BD F7F9          idiv ecx
:004043BF 83F81E        cmp eax, 0000001E  > 1E= 30 jours
:004043C2 0F8E09010000  jle 004044D1       > évite "for %d days"

En modifiant le saut, Unregistered s'affichera seul sans l'indication des jours, et le drapeau [00484864] ne sera jamais mis à 01.

Les Items Register.

Comme supposé, les 2 items Register n'apparaissent plus dans la version enregistrée, et le bouton Register de la boite About est grisé.
Au regard de ce que nous avons découvert de ce programme, il est possible d'imaginer que la routine qui fait disparaître les Items disgracieux se situe dans la zone Post-contrôle du sérial.
Le fait que cette même routine serve aussi bien au test de l'état Reg/Unreg qu'à la validation du sérial entré me laisse également soupçonner qu'à l'origine, toutes versions confondues, les items "Register" sont crées, puis effacées lors du passage dans cette routine si tu es Regged.

Quelles sont les fonctions importées que Wdasm nous donne, et qui correspondraient à des manipulations sur des menus et des items:

CreateMenu        création d'un menu vide (initialisation)
CreatePopopMenu   création d'un menu Popup vide (initialisation)
DeleteMenu        efface les sous-menus associés
DestroyMenu       devine...
DrawMenuBar       là aussi...
EnableMenuItem    sert à activer, désactiver, ou griser un item
InsertMenuA       création d'un menu
InsertMenuItemA   création d'un item de menu
RemoveMenu        efface un item de menu

Evidemment c'est DeleteMenu et RemoveMenu qui vont m'intéresser en premier….
Pour en savoir un peu plus, j'ai commencé par me caler à la fin de la validation du sérial:

:0042BB7E C605F447480001          mov byte ptr [004847F4], 01
:0042BB85 E8528AFDFF              call 004045DC
:0042BB8A B001                    mov al, 01

Et le call 004045DC commence à m'intéresser sérieusement!
Juste avant de tracer dessus, activons un Bpx DeleteMenu et un Bpx RemoveMenu.

POP!

Qu'est qu'il y a dans ce call:

* Referenced by a CALL at Addresses:
|:00429BC8   , :0042BB85   
|
:004045DC A1F8404800    mov eax, dword ptr [004840F8]
:004045E1 33D2          xor edx, edx
:004045E3 8B8048020000  mov eax, dword ptr [eax+00000248]
:004045E9 E81A5D0500    call 0045A308   > break sur RemoveMenu  pour "register"
etc...
:0040462F 8B81B8020000  mov eax, dword ptr [ecx+000002B8]
:00404635 E8CE5C0500    call 0045A308   > break sur RemoveMenu pour "registered version benefits"
:0040463A 8B0DF8404800  mov ecx, dword ptr [004840F8]
:00404640 B201          mov dl, 01
:00404642 8B81E8020000  mov eax, dword ptr [ecx+000002E8]
:00404648 E8EB5B0500    call 0045A238
:0040464D 8B0DF8404800  mov ecx, dword ptr [004840F8]
:00404653 B201          mov dl, 01
:00404655 8B81EC020000  mov eax, dword ptr [ecx+000002EC]
:0040465B E8D85B0500    call 0045A238
:00404660 C3            ret

C'est bien ça…
Et voici où ca nous mènes:

* Reference To: USER32.RemoveMenu, Ord:0000h
                                  |
:0045A004 E871CA0100    Call 00476A7A

Conclusion, si on veut bénéficier d'un soft ayant TOUTES les apparences d'un programme Full Version, il faut impérativement atterrir en 0042BB7E ou en 0042BB74, et donc détourner ce saut :

:0042BB3F 0FBE0B        movsx ecx, byte ptr [ebx]
:0042BB42 83F93A        cmp ecx, 0000003A
:0042BB45 7548          jne 0042BB8F                   > celui ci
:0042BB47 0FBE4301      movsx eax, byte ptr [ebx+01]

Mais un 7548 JNE 0042BB8F qui doit être changé en EB2D JMP 0042BB74, va engendrer une différence de (75+48 =) 189d - (EB+2D =) 280d = +91d de différence dans le poids des octets...


Le Checksum

Jpeg Optimizer utilise des call indirect (du genre call [eax+40]) de façon très fréquente, si bien que le prog, depuis l'entry point, est une véritable horreur à tracer. Pour essayer de mettre la main sur le routine de calcul du poids des octets du programme, j'ai du tracer pendant plus d'une heure et demi avant de décider d'abandonner. On parle de la patience qu'il faut avoir, mais là…
Mon idée première avait été de partir de la String Data Ref "Abnormal Program Termination" en 00471B14, mais au premier call indirecte j'ai bien été obligé d'arrêter, après être remonté jusqu'en 004677E8. En partant de l'Entry Point, j'ai baissé les bras en 004312F2 alors que les 2 versions (enregistrée et non-enregistrée) passaient encore toutes deux par cette adresse. Le calcul du checksum se trouve donc obligatoirement entre 004312F2 et 004677E8.

La solution que tu as utilisée, à défaut d'être élégante, permet au moins de résoudre le problème posé par le checksum, et dans la mesure où tu sais à quel endroit tu disposes de place pour équilibrer le poids des octets modifiés, à défaut de mieux, c'est déjà ça…

Par contre, pour la modification que j'envisage de faire, il ne s'agit plus d'équilibrer 01 au poids des octets, mais 91d, soit 5Bh!
Reste à trouver 5B dans la routine code invalide qui acceptera de se faire modifier en 00…

Et

017F:004290C3  2BF9                SUB       EDI,ECX
017F:004290C5  8DB5BCFEFFFF        LEA       ESI,[EBP-0144]
017F:004290CB  87F7                XCHG      ESI,EDI
017F:004290CD  8BD1                MOV       EDX,ECX

va devenir:

017F:004290C3  2BF9                SUB       EDI,ECX
017F:004290C5  8DB00CFEFFFF        LEA       ESI,[EAX-01F4]
017F:004290CB  87F7                XCHG      ESI,EDI
017F:004290CD  8BD1                MOV       EDX,ECX


Voilà, cher D.LiriUm TrèS MinCe, je ne prétend pas que ma solution est meilleurs que la tienne, bien loin de là, et même au contraire, mais tout ceci ne démontre qu'une chose:

Il y a plusieurs façon de renverser une protection, et qu'il est toujours intéressant de faire le tour d'un sujet, sans sauter aux conclusions trop hâtives...

Il est à préciser quand même que le programme vérifie en 004042CA la présence d'un code dans la base de registre pour le contrôler et le valider dans les lignes suivantes, et quand l'absence de tout code (ce qui sera le cas avec ce patch), il se rend directement, ou presque, dans la routine de validation du code crypté sans refaire de contrôle sur la présence d'un éventuel sérial dans le BdR!
Il aurait suffit d'un JE 004042E9 au lieu d'un JE 004042D5 pour rendre inopérante la modification proposée! (soit en l'absence d'un code dans la BDR, Jumper directement à la routine "Unregistered").

Bonne journée

Christal