Tutorial n° 2


Advanced Excel 95 Password Recovery

Par Freud



Date : 30 mars 2000
Logiciel : Advanced Excel 95 Password Recovery
Distributeur :
Elcom Ltd
Protection : Code CCA, Anti-SoftIce, Limitations, vérification sections et intégrité and last but not least multi-compression/cryptage.

Outils : PESniff, ProcDump, Softice ,Hiew, Wdasm

Pour me contacter : French_Freud@Hotmail.com

I.Avant-Propos

'lo all,
Me voilà de retour pour mon 2ième tutorial. Je vais m'efforcer dans celui-ci d'aller à l'essentiel, en essayant d'être tout de même assez précis. Ce n'est pas évident d'allier les deux. En tout cas, j'aurais beaucoup de choses à dire à propos de ce logiciel et sa protection mais faute de temps j'abrégerais certains points qui me semble les plus évident. A mon avis la manière dont j'ai procédé est hautement criticable et si vous avez une solution plus élégante de faire les choses, n'hésitez pas à m'en faire part.

II.Au lancement du logiciel...

Comme à chaque fois que je désire cracker un logiciel je le lance pour pouvoir voir de quels symptôme il souffre...normal non ? Cette fois là quelle ne fut pas ma surprise en voyant une belle petite dialogue box (belle???) affichant fièrement "Debugger Detected !". Ok très bien...autant vous le dire tout de suite je n'ai pas éliminé ce bug étant donné que celui-ci n'empêche aucunement le programme de fonctionner en utilisation normale (c'est à dire sans Soft-Ice).
Pour rectifier ce problème, j'ai tout simplement utilisé FrogIce (et encore un merci à Frog's Print) qui permet de "fooler" cette protection.
Me voilà donc dans le soft, on peut y voir le résultat des bugs : dans la barre de la fenêtre Windows à côté de "Advanced Excel 95 Password Recovery" on peut lire "UNREG", quand on essait d'ouvrir un fichier Excel 95 protégé par mot de passe de plus de 4 caractères, on obtient le message suivant "The password has been found, but it contains 4 symbols and so cannot be shown in evaluation version. Please register.". Ennuyeux, vous trouvez pas ?.
Pour enregistrer ce soft, il faut entrer un code d'enregistrement. Tapons un code au hasard, par exemple Freud, une message s'affiche : "The code you've entered is invalid".
Essayons de désassembler le logiciel avec Wdasm...grrr!! Pas de résultat !! mais quelques infos bien utiles tout de même à relever (Entry_Point
: 00424001):


+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object  **************
Program Entry Point = 00424001 (ae95pr.exe File Offset:00024001)


Number of Objects = 0008 (dec), Imagebase = 00400000h
.text    RVA: 00001000 Offset: 00000400 Size: 00003000 Flags: C0000040
.idata   RVA: 00007000 Offset: 00003400 Size: 00000600 Flags: C0000040
.data    RVA: 00008000 Offset: 00003A00 Size: 00000800 Flags: C0000040
.bss     RVA: 00009000 Offset: 00000000 Size: 00002400 Flags: C0000040
.reloc   RVA: 0000C000 Offset: 00004200 Size: 00000000 Flags: C0000040
.rsrc    RVA: 0000D000 Offset: 00004200 Size: 00014C00 Flags: C0000040
aspr     RVA: 00024000 Offset: 00018E00 Size: 00011800 Flags: C0000040 > EP
.rsrc    RVA: 00036000 Offset: 0002A600 Size: 00000000 Flags: C0000040

On remarque de suite que ce qui empêche Wdasm de désassembler et le loader de Soft-Ice de stopper à l'entry_point (première instruction exécutée) sont les caractéristiques des sections (toutes à C0000040). Si on essait de changer les caractéristiques de la section .text en E0000020 pour rendre le code Readable, Writeable et Executable, On a aucune String Reference avec Wdasm. Le logiciel est bel et bien compressé/crypté, j'ai alors essayé de trouvé le compresseur/crypteur avec PEsniff mais sans aucun résultat *sigh*. J'ai mêle essayé File Analyser un très bon soft que je recommande vivement. On a affaire à une "ready made protection" comme dirait notre ami Christal. Au fait, je l'ai pas signalé plus haut mais en plus quand change les caractéristiques de section, au lancement du proggy on a droit à un beau message "File corrupted!".On a droit aussi à ce message qu'en on patche un endroit de la mémoire ce qui signifie que le proggy vérifie son intégrité...Y'a du boulot...


III.Commençons par trouver comment devenir un "registered user" et supprimons le message "File Corrupted!"...

Comme dans la plupart des logiciels compressé/crypté, en général le crack en lui même est très simple à réaliser, le plus dur étant de réussir à patcher ce programme surtout s'il est multi-compressé avec du code CCA c'est à ce moment là qu'on "s'amuse" vraiment !!
C'est le cas pour AExcel 95 Password Recovery, il est très simple à cracker mais plus dur à patcher. Voyons ça

Marche à suivre (The rule of thumb) :

1. Rentrer un code bidon (Par ex : 123456789)
2. CTRL-D, pop de retour dans Soft-Ice, taper BPX Hmemcpy
3. Valider la saisie
4. pop de retour dans Soft-Ice, quelques F12 (combien? attendez je le fais et je reviens dans 2 secondes pour vous dire...9 pour être précis) on se trouve alors ici dans le code :

:00402BDA A15CB34000    mov eax, dword ptr [0040B35C] 
:00402BDF 0500020000    add eax, 00000200 <--- Notre code bidon 
:00402BE4 E8D4FCFFFF    call 004028BD     <--- Test code ok?
:00402BE9 85C0          test eax, eax
:00402BEB 7507          jne 00402BF4      <--- saut good boy/bad boy

Comme on peut le voir la vérification du code entré se fait dans le CALL 004028BD. Si on modifie simplement le saut en 00402BEB, on est toujours Bad Boy, étrange...En fait pas tant que cela c'est juste que le proggy dans le CALL met à un 1 une adresse mémoire, il va donc falloir modifier le CALL. En plus c'est plus efficace car si le programme y fait appel à d'autres endroits notre crack fonctionnera toujours...voyons ce que ce CALL a dans le ventre :


:004028BD 53                      push ebx 
...
:004028C6 89C6                    mov esi, eax
:004028C8 E8033F0000              call 004067D0
:004028CD 89C1                    mov ecx, eax
:004028CF 83F806                  cmp eax, 00000006 <--- Notre code > 6
:004028D2 7D07                    jge 004028DB
:004028D4 31C0                    xor eax, eax
:004028D6 E9FE000000              jmp 004029D9 <--- Bad boy code < 6  
:004028DB BF02000000              mov edi, 00000002
:004028E0 99                      cdq
:004028E1 F7FF                    idiv edi
:004028E3 85D2                    test edx, edx
:004028E5 75ED                    jne 004028D4 <--- Bad boy 
...
:00402921 E83A400000              call 00406960
:00402926 85C0                    test eax, eax
:00402928 75AA                    jne 004028D4 <--- Bad boy
...
:00402953 E811FFFFFF               call 00402869
:00402958 85C0                    test eax, eax
:0040295A 0F8479000000            je 004029D9 <--- Bad boy
:00402960 833D68B3400000          cmp dword ptr [0040B368], 00000000 
:00402967 756B                    jne 004029D4 <--- Bad boy
...
:004029CA C70568B3400001000000    mov dword ptr [0040B368], 00000001 <-- GB
:004029D4 B801000000              mov eax, 00000001 <--- Good Boy
:004029D9 C9                      leave
:004029DA 5F                      pop edi
:004029DB 5E                      pop esi
:004029DC 5A                      pop edx
:004029DD 59                      pop ecx
:004029DE 5B                      pop ebx
:004029DF C3                      ret

En analysant ce CALL, on voit bien qu'il faut que le programme passe par l'adresse :004029CA pour que le flag utilisateur soit mis à 1. Y'a plus qu'a viré tous les Jxx et compagnie qui saute au dela de l'adresse :004029CA. On trouve quatre Jxx qui foute le bordel aux adresses :004028E5, :00402928, :0040295A, :00402967. Notre patch aura donc l'allure suivante :

MOV BYTE PTR [004028E5],74
MOV BYTE PTR [00402928],74
MOV BYTE PTR [0040295B],85
MOV BYTE PTR [00402967],74

Passons maintenant à la suppression du message
"File corrupted!". J'ai procéder de la manière suivante : je me suis dit que le programme lorsqu'il vérifiait les sections devait obligatoirement accepter au fichier AE95PR, par conséquent j'ai poser un BPX approprier à ce genre de situation soit un BPX ReadFile.
Le programme a donné la main à SoftIce dès l'ouverture, mais comptons combien de fois SoftIce reprend la main avant l'affichage "File corrupted". J'ai compter 5 breaks avant l'affichage ennuyeux donc au 5ième break on va trace le programme jusqu'à temps qu'un call nous affiche "File corrupted!". Pour ma part après 5 F12, pour revenir dans AE95PR, je suis tombé sur le call suivant en tracant un peu :

:006C06B2 8B5303      MOV EDX,[EBX+03]
:006C06B5 E816F9FFFF  CALL 06BFFD0 <--- Affiche le nag "File corrupted"
:006C06BA 8B45F8      MOV EAX,[EBP-08]

En regardant un peu plus haut dans le code on peut voir ceci :

:006C067C 3B45F4      CMP EAX,[EBP-0C]
:006C067F 7439        JZ 006C06BA

Tiens donc, si eax et la valeur [EBP-0C] sont égals (JZ) on saute juste après le CALL qui affiche le Nag en :006C06BA. Vous avez compris que pour éliminer le nag il suffit de changer JZ à l'adresse :006C067F en JNZ and that will do the trick as usual !. Il faut donc rajouter à notre patch précédant l'instruction MOV BYTE PTR [006C067F],75 pour virer le nag.

Voilà que maintenant on sait quel endroit du programme patcher, il va falloir trouver comment patcher ce proggy vu qu'évidemment on ne retrouve nulle part les Jxx à patcher dans le programme sur le disque étant donné que le soft est multi-compressé/crypté.


Maintenant qu'on a l'endroit à modifier, Comment patcher le programme compressé ?

En règle générale, les programmes compressés fonctionnent de cette manière : Quand on lance le soft, voila en gros se qui se passe :

1. En tout premier, le décompresseur ou loader (qui n'est pas compresse lui!! et heureusement) va décompressé le prog en mémoire.
2. Le loader redonne la main au programme décompressé dans sa totalité.

Notre but a nous est de patcher le programme decompressé en mémoire. L'unique facon pour nous d'agir se situe lorsque tout le programme a ete decompresse c'est a dire lorsque le loader va rendre la main au programme decompresse.

Cependant malheuresement pour nous, AE95PR ne fonctionne pas comme ca. En effet, la Ready Made Protection se décompresse morceaux par morceaux en mémoire, ce qui fait que lorsque un loader a fini de décompresser une partie, il saute vers cette partie qui continue à décompressé le fichier et ainsi de suite entre temps on peut avoir des Anti-SoftIce (ASI) ou des vérifications de section...ca vous rappelle rien?
La philosophie qu'on va adopter pour réduire à néans cette protection va donc être la suivante :
Poser un BPM sur la première adresse de notre patch c'est à dire en :004028E5, si bien que lorsque cette partie va être décompressé/décrypté on va le savoir. On note alors l'adresse A1 ou se situe cette décompression/décryption. De même on continue en posant un BPM A1 ainsi pareil on voit ou est décompressé cette partie et ainsi de suite jusqu'à d'arriver au bout de code présent dans le fichier AE95PR et qu'on va pouvoir par conséquent patcher!! Pour résumer, on va donc à chaque fois qu'une décompression est fini prendre la main pour modifier le code décrypté/décompressé de façon a pouvoir avoir la main une fois dans ce code fraîchement décompressé/décrypté. On arrête quand le code qui nous intéresse est décompressé/décrypté. Je sais pas si je me fais bien comprendre...Voilà un schéma qui montre la situation :

:Adresse A0 ---> Code présent dans AE95PR (donc patchable) qui décompresse un bout de code en A1
JMP Notre_Routine1
|
|
|
|
V
:Adresse A1 ---> Code non présent dansAE95PR qui décompresse un autre bout de code en A2.
JMP Notre_Routine2
|
|
|
|
V
:Adresse A2 ---> Code qui décompresse le code qui nous intéresse.
JMP Notre_Routine3

:Notre_Routine1 ---> Modifie A1 en écrivant un JMP Notre_Routine2
:Notre_Routine2 ---> Modifie A2 en écrivant un JMP Notre_Routine3
:Notre_Routine3 ---> Effectue le patch!!

Je dois avouer que si vous avez compris vous êtes balèse car j'ai vraiment du mal à exprimer ma pensée mais je pense que le gros de l'idée y est donc réfléchissez un peu et ca devrait être bon.

La méthode vous l'avez, maintenant il faut l'appliquer à notre cas. Dans ce qui va suivre je vais simplement expliquer le patchage pour supprimer le nag
File corrupted!. La marche à suivre pour le patchage pour devenir un "registered user" est la même. A la fin de ce tut, je mettrai quand tout de même la version intégrale du patch final.

On sait que ce que l'on veut modifier se trouve à l'adresse :006C067F. On va donc poser un BPM sur cette adresse pour que SI nous redonne la main quand le programme écrira des données à cette endroit. Action !. SI breaks en
:006CF3C7 regarder : (A noter qu'il break qu'une fois)

:006CF3C7 F3A5 		REPZ MOVSD <--- Caractéristique d'une décryption/décompression
:006CF3C9 8BC8 		MOV ECX,EAX
:006CF3CB 83E103    	AND ECX,03
:006CF3CE F3A4 		REPZ MOVSB

Si vous me suivez encore...je l'espère, il va falloir placer un JMP Notre_Routine3, après la décompression de la zone qui nous interesse c'est à dire en :006CF3C9. En plus ca tombe bien car il nous faut 5 octets pour placer le JMP cela va donc supprimer le MOV ECX,EAX et le AND ECX,03 qu'il ne faudra pas oublier de remettre dans notre nouvelle routine. Notre routine3 aura donc l'allure suivante :

MOV ECX,EAX AND ECX,03 <--- Instructions écrasées MOV BYTE PTR [006C067F],75 <--- Pour supprimer le nag "File corrupted" JMP 006CF3CE <--- Retour aux instructions normales

Bien, vous allez me dire mais ou va t-on écrire cette routine dans le vrai fichier?? J'opte souvent pour placer mes patchs en fin de sections. Ici, j'ai choisi de mettre mes patchs à la fin de la section aspr (en :00435690 par exemple), vous pouvez aller y faire un tour vous verrez qu'il y a une incroyable série 00, on peut donc y loger nos patchs. Avant, j'ai vérifie que le soft n'écrivait rien à cette endroit en posant un BPM par précaution.

Bon, ce n'est pas terminé pour autant,il faut maintenant trouver dans quel endroit du programme est décompressé le code commencant à l'adresse :006CF3CF, afin qu'on prenne le contrôle a ce moment. Comme auparavant même méthode, on pose un BPM sur cette adresse. Pop ! SoftIce nous prend la main et nous indique l'adresse
:006CF0EB, let's see :

:006CF0E5 8BB539294400    MOV ESI,[EBP+00442939]
:006CF0EB F3A4            REPZ MOVSB <--- Caractéristique d'une décryption/décompression
:006CF0ED 8B8539294400    MOV EAX,[EBP+00442939]

On voit que le code en :006CF3CF, est décompressé en :006CF0EB, on va donc prendre la main après cette décompression en :006CF0ED pour mettre à la place un JMP Notre_Routine2. Notre routine2 va être chargé d'écrire le JMP notre_routine3 en :006CF3C9. elle aura l'allure suivante :

MOV EAX,[EBP+00442939] <--- Instruction écrasée
MOV [006CF3C9],JMP Notre_Routine3
JMP retour au programme normal

Et on continue de plus belle à savoir trouver l'endroit ou est décompressé le code présent en :006CF0EB en utilisant toujours la même technique (BPM 006CF0EB). Cette fois on arrive ici :

:0042430E F2C1F902   REPNZ SAR ECX,02
:00424312 F3A5       REPZ MOVSD <--- Caractéristique d'une décryption/décompression
:00424314 83C328     ADD EBX,28

Bingo !! Si vous regardez bien les adresses, elles correspondent à des adresses présentes dans le fichier AE95PR, on a donc bientot fini. Il va falloir mettre un JMP Notre_Routine1 après le REPZ MOSD en :00424312. Notre_Routine1 va s'occuper d'écrire un JMP Notre_Routine2 en :006CF0ED. Elle aura l'allure suivante :

Instructions éffacés
MOV [006CF0ED],JMP Notre_Routine2
retour au programme normal

Voilà c'est fini, pour pouvoir écrire le patch, il faut le réaliser en live sous Soft-Ice pour connaître les bonnes adresses des JUMP ainsi que le codage des instructions.


IV. Le patch, l'intégral !!

Je ne sais pas si c'est une bonne idée de donner le patch complet mais peut-être qu'il pourra éclairer certaines lanternes...Entrez ce patch sous Hiew aux adresses indiquées :

Offset 1923F
90 90 90 90 90 90 ---> Vire une instruction génante qui effacait le Jump notre_routine1

Offset 192DF
E9 AC 11 01 00 ---> Ecrit le JMP Notre_Routine1

Offset 2A490
C7 05 ED F0 6C 00 E9 CE 65 D6 ---> Ecrit le JMP Notre_Routine2
66 C7 05 F1 F0 6C 00 FF 90 ---> Ecrit le JMP Notre_Routine2
68 01 F0 6C 00 --> Ins. effacée
C9 90 --> Retour prog normal (RET)

Offset 2A4C0
8B 85 39 29 44 00 --> Ins. effacée
C7 05 C9 F3 6C 00 E9 32 63 D6 ---> Ecrit le JMP Notre_Routine3
C6 05 CD F3 6C 00 FF ---> Ecrit le JMP Notre_Routine3
E9 16 9A 29 00 ---> Retour prog normal.

Offset 2A500
C6 05 7F 06 6C 00 75 ---> Patch pour virée le nag
8B C8 ---> Ins. effacée
83 E1 03 ---> Ins. effacée
C7 05 91 26 6B 00 E9 BA 30 D8 ---> Ecrit le JMP Notre_Routine4
C6 05 95 26 6B 00 FF ---> Ecrit le JMP Notre_Routine4
E9 AC 9C 29 00 ---> retour prog normal.

Offset 2A550
80 3D E5 28 40 00 74 ---> La partie est t-elle décompréssé ?
75 1C ---> si oui pas de jmp.
C6 05 E5 28 40 00 74 ---> Patch pour être "registered user"
C6 05 28 29 40 00 74 ---> ""
C6 05 5B 29 40 00 85 ---> ""
C6 05 67 29 40 00 74 ---> ""
89 C1 ---> Ins. effacée
83 E1 03 ---> Ins. effacée
E9 17 CF 27 00 ---> jump de retour programme normal.
90 ---> Byte pour équilibrer

V. Conclusion

En conclusion, comme à l'habitude mes remerciements iront à Christal qui entretenir si bien la scène du craking francais, merci. Je voulais aussi saluer au passage Brénuche, président de l'IRIP ainsi que toutes les personnes qui font avancer les choses (en réalisant des tutorials par exemple).

Au passage, si vous trouvez des absurdites,des erreurs dans ce tut (ce qui est loin d'être impossible) ou que vous avez une remarque a faire, n'hesitez surtout pas a prendre contact avec moi (
French_Freud@Hotmail.com).

Don't give up the fight

Freud

Le mot de la fin : "Il ne faut jamais cracher au visage d'un homme, sauf quand sa moustache est en feu !!"