CIBLE


Sheet Stylist v2.0

INFECTIONS


Nagscreen
Boite d’enregistrement
Unregistered dans le titre...
Compression shrinker v3.4

OUTILS


Softice 4.01
W32Dasm v8.93
Deshrink v1.6
ProcDump32 v1.6.2
R!SC's Process Patcher v1.2i


HOWTO




Je cherchais un prog avec une compression shrinker pour voir de quoi elle avait l'air et MrPhilex ma conseillé Sheet Stylist v2.0. Ma fois cette compression /encryption est assez banale. J'ai mis approximativement 8-10 mn à cracker ce prog. Mais, Mrphilex m'a demandé après le crack pour ce prog. J'ai dit ok, mais j'avais tout jeté, donc il faut tout refaire. Il m'a un peu après demandé si je voulais bien faire un tut: ben, ya pas de problème que j'y ai dit. Donc voilà l'origine de ce tut (hehe): great dedicace to MrPhilex :) .
Comme je l'ai dit j'ai trouvée cette protection assez banale: donc ce tut n'aura rien de spécial. Je vais donc en profiter pour récapituler les principales manières d'arriver à cracker un prog compressé.
 

Bon avant de parler de compression on va regarder comment on pourrais cracker ce prog. On à au démarrage un nag avec register qui affiche une belle boite d'enregistrement : la tentation est trop forte, on attaque par là :).
On met son nom (LuTiN NoIR), et un serial bidon(nant) : 123456789, et on fait surgir soft-ice (ctrl+d). Là on met un point d'arrêt sur la fonction hmemcpy (pour saisir le texte) : bpx hmemcpy et on quitte softice (F5). On clique sur ok et là softice réapparait. On remonte les fonctions (F12) jusqu'à arriver dans Sheet Style, et la on continue de remonter les fonctions (il y a des ret pas loin ce qui veux dire que ca se passe ailleurs), au bout d'un moment on arrive là :
 

:0047105C 55                      push ebp
:0047105D 8BEC                    mov ebp, esp
:0047105F 6A00                    push 00000000
:00471061 6A00                    push 00000000
:00471063 53                      push ebx
:00471064 8BD8                    mov ebx, eax
:00471066 33C0                    xor eax, eax
:00471068 55                      push ebp
:00471069 682B114700              push 0047112B
:0047106E 64FF30                  push dword ptr fs:[eax]
:00471071 648920                  mov dword ptr fs:[eax], esp
:00471074 C683DC02000000          mov byte ptr [ebx+000002DC], 00
:0047107B 8D55FC                  lea edx, dword ptr [ebp-04]
:0047107E 8B83D0020000            mov eax, dword ptr [ebx+000002D0]
:00471084 E8B321FCFF              call 0043323C
:00471089 8B45FC                  mov eax, dword ptr [ebp-04]          <-- on arrive là
:0047108C 50                      push eax
:0047108D 8D55F8                  lea edx, dword ptr [ebp-08]
:00471090 8B83CC020000            mov eax, dword ptr [ebx+000002CC]
:00471096 E8A121FCFF              call 0043323C
:0047109B 8B45F8                  mov eax, dword ptr [ebp-08]
:0047109E 5A                      pop edx
:0047109F E8F8F5FFFF              call 0047069C
:004710A4 84C0                    test al, al                         <-- al = 0 ?
:004710A6 7453                    je 004710FB                         <-- oui on saute
:004710A8 C683DC02000001          mov byte ptr [ebx+000002DC], 01
:004710AF 8D55FC                  lea edx, dword ptr [ebp-04]
:004710B2 8B83D0020000            mov eax, dword ptr [ebx+000002D0]
:004710B8 E87F21FCFF              call 0043323C
:004710BD 8B45FC                  mov eax, dword ptr [ebp-04]
:004710C0 50                      push eax
:004710C1 8D55F8                  lea edx, dword ptr [ebp-08]
:004710C4 8B83CC020000            mov eax, dword ptr [ebx+000002CC]
:004710CA E86D21FCFF              call 0043323C
:004710CF 8B55F8                  mov edx, dword ptr [ebp-08]
:004710D2 B840114700              mov eax, 00471140
:004710D7 59                      pop ecx
:004710D8 E8FBF9FFFF              call 00470AD8
:004710DD 6A00                    push 00000000
:004710DF 668B0D50114700          mov cx, word ptr [00471150]
:004710E6 B202                    mov dl, 02
:004710E8 B85C114700              mov eax, 0047115C
:004710ED E87681FEFF              call 00459268
:004710F2 8BC3                    mov eax, ebx
:004710F4 E84FB6FDFF              call 0044C748
:004710F9 EB15                    jmp 00471110

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004710A6(C)
|
:004710FB 6A00                    push 00000000                     <--et on attérit là
:004710FD 668B0D50114700          mov cx, word ptr [00471150]
:00471104 B201                    mov dl, 01
:00471106 B8C0114700              mov eax, 004711C0
:0047110B E85881FEFF              call 00459268                     <-- message bad serial

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004710F9(U)
|
:00471110 33C0                    xor eax, eax
:00471112 5A                      pop edx
:00471113 59                      pop ecx
:00471114 59                      pop ecx
:00471115 648910                  mov dword ptr fs:[eax], edx
:00471118 6832114700              push 00471132

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00471130(U)
|
:0047111D 8D45F8                  lea eax, dword ptr [ebp-08]
:00471120 BA02000000              mov edx, 00000002
:00471125 E8022CF9FF              call 00403D2C
:0047112A C3                      ret
 

Là c'est on ne peut plus simple : en 4710A6 il y a un saut conditionnel qui nous envoie sur sur le message d'erreur. Donc il y a 99,99 % de chance que la fonction qui précéde en 47109F serve à vérifier si le serial est bon. On va allez voir ce qui s'y passe. On met un point d'arrêt en 47109F (bpx 47109F), on relance l'enregistrement, et softice break: on est en 47109F. Là on rentre dans le call (F8) et on à ceci :
 

:0047069C 55                      push ebp
:0047069D 8BEC                    mov ebp, esp
:0047069F 83C4F4                  add esp, FFFFFFF4
:004706A2 53                      push ebx
:004706A3 33C9                    xor ecx, ecx
:004706A5 894DF4                  mov dword ptr [ebp-0C], ecx
:004706A8 8955F8                  mov dword ptr [ebp-08], edx
:004706AB 8945FC                  mov dword ptr [ebp-04], eax
:004706AE 8B45FC                  mov eax, dword ptr [ebp-04]
:004706B1 E8823AF9FF              call 00404138
:004706B6 8B45F8                  mov eax, dword ptr [ebp-08]
:004706B9 E87A3AF9FF              call 00404138
:004706BE 33C0                    xor eax, eax
:004706C0 55                      push ebp
:004706C1 6800074700              push 00470700
:004706C6 64FF30                  push dword ptr fs:[eax]
:004706C9 648920                  mov dword ptr fs:[eax], esp
:004706CC 8D55F4                  lea edx, dword ptr [ebp-0C]
:004706CF 8B45FC                  mov eax, dword ptr [ebp-04]
:004706D2 E835FEFFFF              call 0047050C
:004706D7 8B45F4                  mov eax, dword ptr [ebp-0C]     <-- met bon serial dans eax
:004706DA 8B55F8                  mov edx, dword ptr [ebp-08]     <-- met pas bon serial dans edx
:004706DD E8B239F9FF              call 00404094                   <-- compare
:004706E2 0F94C3                  sete bl
:004706E5 33C0                    xor eax, eax
:004706E7 5A                      pop edx
:004706E8 59                      pop ecx
:004706E9 59                      pop ecx
:004706EA 648910                  mov dword ptr fs:[eax], edx
:004706ED 6807074700              push 00470707

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00470705(U)
|
:004706F2 8D45F4                  lea eax, dword ptr [ebp-0C]
:004706F5 BA03000000              mov edx, 00000003
:004706FA E82D36F9FF              call 00403D2C
:004706FF C3                      ret

Bon là en 4706D7 il met le bon serial dans eax, puis le mauvais dans edx et compare les deux. C'est là que j'ai décidé de cracker le soft. Et oui que ce paserait-il si il comparait les deux mêmes serial, et bien ça devrait faire croire qu'on a le bon mot de passe. Regardons voir: lorsque l'on est en 4706DA (ou avant) on tape sous softice a 4706DA et on met mov edx, dword ptr [ebp-0C] , comme cela il va comparé le vrai serial au vrai serial (:) ). Une fois les modifs effectuées, on quitte softice et là oh miracle on est un utilisateur enregistré. Le seul problème c'est que lorsque l'on quitte le prog et qu'on le relance on ne l'est plus. Un obstacle ? non !!!
Les programmes qui utilisent des compresions/encryptions commerciales ont en général une "sécurité" bien faible. Et Sheet Style n'échappe pas à la règle. Les programmeurs se sont surement pas foulés à faire une autre routine pour vérifier que le sérial entré est le bon au début du prog. Mettons donc un point d'arrêt en 4706DA, et relancons le prog et comme par miracle softicebreak, il suffit de refaire la modifs et le soft nous croit enregistré. De plus le prog utilise cette routine à chaque affiche de unregistered. Donc pour cracker le soft il suffit de faire :

:004706DA 8B55F8                  mov edx, dword ptr [ebp-08]

qu'on remplace par :

:004706DA 8B55F4                  mov edx, dword ptr [ebp-0c]

En fait il faut juste mettre en 4706DC : F4 et le tour est joué. Ya plus qu'à.

Maintenant on va s'attaquer à la compression en 4 étapes: crack d'un exe décompressé, crack en mémoire, autre façcon d'avoir un exe décompressé, et hard patching.
 

I Crack d'un exe décompressé.

On ne peut pas patcher directement le prog car il est compressé avec shrinker 3.4 (c'est écrit dedans). Pour avoir un fichier executable non compressé du prog on va utiliser un outil merveilleux : deshrink v1.6. Donc on l'utilise et on obtient un executable non compressé. Il suffit alors de le désassemblé avec W32dasm, d'aller à l'adresse 4706DA, de noter l'offset, puis avec un éditeur hexa on fait les modifications. Et voilà un prog cracké.
 

II Crack en mémoire

Comme le prog est compressé il va être obligé de se décompressé en mémoire pour pouvoir s'éxécuter. Donc on peut le patcher en mémoire. Pour cela on va utiliser R!SC's Process Patcher qui va nous créer un loader pour le prog et qui va le patcher en mémoire. Voilà le script :

T=2000:                      <-- temps pour patcher
F=SheetStylist.exe:       <-- nom du prog
O=loader_shit.exe:       <-- nom du loader
P=4706dc/f8/f4:           <-- patch à faire
$

Voilà une deuxième méthode pour cracker ce soft.

III_Manual unpacking + hard patching

Voilà la partie vraiment intéressante : cracker directement l'exe compressé. Pour ce faire il faut trouver où le prog donne la main au prog décompressé en mémoire. Il va falloir tracer avec softice depuis le début du prog avec le symbol loader.
Bon en général quand on lance un prog compressé avec symbol loader S-I ne break pas, et il faut faire quelques modifs: soit modifier les sections, soit utiliser le merveilleux prog de Teeji qui permet de forcer le break sur l'entry point, soit d'utiliser une méthode décrite par Psyché qui consiste à mettre dans le fichier un CC sur eop (int 3, puis bint 3 sous softice). Et c'est cette dernière que je voulais utilisée ici mais il se trouve que quand on lance Sheet Style avec symbol loader et bien softice break. Bon on trace délicatement (f10) et on arrive ici :
 

015F:0059B5D0  FF7510              PUSH      DWORD PTR [EBP+10]
015F:0059B5D3  FF750C              PUSH      DWORD PTR [EBP+0C]
015F:0059B5D6  56                  PUSH      ESI
015F:0059B5D7  E806000000          CALL      0059B5E2      <-- affiche le prog
 

bon là il faut rentrer en 59b5d7 et on a cela :

015F:0059B636  0F848D000000        JZ        0059B6C9                (NO JUMP)
015F:0059B63C  833DC461590000      CMP       DWORD PTR [005961C4],00
015F:0059B643  7526                JNZ       0059B66B                (NO JUMP)
015F:0059B645  833D1486590000      CMP       DWORD PTR [00598614],00
015F:0059B64C  741D                JZ        0059B66B                (NO JUMP)
015F:0059B64E  A114865900          MOV       EAX,[00598614]                       <-- met 105518 dans eax
015F:0059B653  030528875900        ADD       EAX,[00598728]                       <-- met 505518 dans eax
015F:0059B659  8945DC              MOV       [EBP-24],EAX
015F:0059B65C  FF7510              PUSH      DWORD PTR [EBP+10]
015F:0059B65F  FF750C              PUSH      DWORD PTR [EBP+0C]
015F:0059B662  FF7508              PUSH      DWORD PTR [EBP+08]
015F:0059B665  FF55DC              CALL      [EBP-24]               <-- affiche le prog

Donc en 59B64E il y a l'adresse du début du prog en mémoire dans eax. Je le sais car vu la différence au niveau des adresses ca peut qu'être cela, de plus en rentrant dans le call en 59B665, il affiche le prog pas à pas. Ensuite il met eax dans Ebp-04 puis il fait un call [ebp-04] en 59b665: c'est là qu'il va vers le début du prog décompressé en mémoire.
Donc là on peut faire notre manual unapcking, c'est à dire que l'on peut récupérer tout le prog en mémoire pour en avoir un prog décompressé et executable. Pour cela on remplace en 59b665, sous softice on tape a 59b665 et on met jmp eip. Le prog va tourner en boucle sur la même adresse. Là on quitte softice, on lance procdump, on selectionne le prog dans les task et on fait un dump full et on n'a même pas besoin de corriger l'entrypoint. Maintenant même technique de crack que le I.

Passant maintenant au hard patching. Le but et de forcer le prog à changer ce qu'il y a à l'adresse 4706da juste avant qu'il passe au prog décompressé en mémoire.
Donc en 59b659 on peut très bien faire notre patch comme ceci :

mov byte ptr [004706DA], F8
jmp eax

Car eax contient EOP du prog. On aurait pu mettre le patch  avant mais bon laissons donc la gestions d'erreur et utilisons donc eax. Sauf que là le patch ne fonctionnerait pas car à ce moment précis l'adresse 4706da est invalide : le code ne s'y trouve pas. Le programmeur aurait-il été plus futé que ce que j'avais cru ? faut croire. Posons donc un mouchard à cette adresse, on saura quand le prog va y écrire : bpm 004706DA w . softice break, on remonte le code et on arrive là :

015F:0050551B  83C4EC              ADD       ESP,-14
015F:0050551E  53                  PUSH      EBX
015F:0050551F  56                  PUSH      ESI
015F:00505520  57                  PUSH      EDI
015F:00505521  33C0                XOR       EAX,EAX
015F:00505523  8945F0              MOV       [EBP-10],EAX
015F:00505526  8945EC              MOV       [EBP-14],EAX
015F:00505529  B8D0505000          MOV       EAX,005050D0
015F:0050552E  E88D14F0FF          CALL      004069C0           <-- décompresse la zone
015F:00505533  33C0                XOR       EAX,EAX
015F:00505535  55                  PUSH      EBP
015F:00505536  6817575000          PUSH      00505717
015F:0050553B  64FF30              PUSH      DWORD PTR FS:[EAX]
015F:0050553E  648920              MOV       FS:[EAX],ESP
015F:00505541  33D2                XOR       EDX,EDX
015F:00505543  55                  PUSH      EBP
 

En fait c'est dès le début du prog qu'il décompresse la zone qui nous intéresse en 50552E. Donc il faut faire un patch après en 505533 qui ferait notre crack. En gros voilà ce qu'il faut faire :

1 un patch au niveau du saut vers le prog décompressé, qui ferait un 2ème patch
2 ce 2ème patch serait un saut vers une zone du programme, pour faire le patch de la zone à cracker.

Pour cela il faut trouver de la place libre dans le prog. On prend son héditeur hexa, on va à la fin du prog et on trouve plein de place libre:

 000B29D0:  EB 08 F9 31-A8 E5 84 7C-95 AD 10 CE-39 0B 20 9B  ë ù1¨å„|•­ Î9  ›
 000B29E0:  70 97 F5 2F-97 FD A7 11-F2 7F E8 F8-6F 00 00 00  p—õ/—ý§ òèøo
 000B29F0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595000:  FF FF FF FF-EE A0 59 00-01 A1 59 00-00 00 00 00  ÿÿÿÿî Y  ¡Y
.00595010:  FF FF FF FF-A4 B6 59 00-B7 B6 59 00-00 00 00 00  ÿÿÿÿ¤¶Y ·¶Y
.00595020:  53 48 52 49-4E 4B 33 34-2E 4C 44 52-00 00 00 00  SHRINK34.LDR
.00595030:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595040:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595050:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595060:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595070:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595080:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595090:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.005950A0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.005950B0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.005950C0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.005950D0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.005950E0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.005950F0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595100:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595110:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595120:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00
.00595130:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00

Donc on peut mettre le patch en 595030 : voilà son allure :

015F:0050552E  E88D14F0FF          CALL      004069C0
015F:00505533  E9F8FA0800          JMP       00595030   <-- va vers patch
015F:00505538  90                  NOP                  <-- équilibre le code
015F:00505539  90                  NOP
015F:0050553A  90                  NOP
015F:0050553B  64FF30              PUSH      DWORD PTR FS:[EAX]
015F:0050553E  648920              MOV       FS:[EAX],ESP

Et voilà en 595030 :

015F:00595030  C605DC064700F4      MOV       BYTE PTR [004706DC],F4     <-- patch
015F:00595037  33C0                XOR       EAX,EAX                    <-- on restaure
015F:00595039  55                  PUSH      EBP                        <-- ce que le saut à détruit
015F:0059503A  6817575000          PUSH      00505717
015F:0059503F  E9F704F7FF          JMP       0050553B                   <-- et on retourne dans le prog
 

Maintenant il faut mettre le patch à l'endroit où le prog saute en mémoire pour qu'il créer le second patch qui va servir au troisième. Bon là on va faire des sacrifices :

015F:0059B636  0F848D000000        JZ        0059B6C9
015F:0059B63C  833DC461590000      CMP       DWORD PTR [005961C4],00
015F:0059B643  7526                JNZ       0059B66B
015F:0059B645  833D1486590000      CMP       DWORD PTR [00598614],00
015F:0059B64C  741D                JZ        0059B66B
015F:0059B64E  A114865900          MOV       EAX,[00598614]                <------------------
015F:0059B653  030528875900        ADD       EAX,[00598728]
015F:0059B659  8945DC              MOV       [EBP-24],EAX
015F:0059B65C  FF7510              PUSH      DWORD PTR [EBP+10]             cette zone devrait suffir
015F:0059B65F  FF750C              PUSH      DWORD PTR [EBP+0C]
015F:0059B662  FF7508              PUSH      DWORD PTR [EBP+08]
015F:0059B665  FF55DC              CALL      [EBP-24]                      <-----------------

On fait notre patch sous softice et ca donne cela :

015F:0059B636  0F848D000000        JZ        0059B6C9
015F:0059B63C  833DC461590000      CMP       DWORD PTR [005961C4],00
015F:0059B643  7526                JNZ       0059B66B
015F:0059B645  833D1486590000      CMP       DWORD PTR [00598614],00
015F:0059B64C  741D                JZ        0059B66B
015F:0059B64E  C70533555000E9F8FA08MOV       DWORD PTR [00505533],08FAF8E9      <-- créer patch 2
015F:0059B658  C7053755500000909090MOV       DWORD PTR [00505537],90909000
015F:0059B662  E9B19EF6FF          JMP       00505518                           <-- va vers début du prog en mémoire

Maintenant il ne reste plus qu'à effectuer les changements avec un éditeur hexa pour ce dernier truc ainsi que pour ce que l'on a rajouté à la fin du prog et le tour est joué :) .
 

Voilà ce petit tut est fini, si vous avez des questions : city_of_bitch@caramail.com

Amicalement
LuTiN NoIR
 

PS: Greetz to : Christal, Teeji (thanks for help me), and ............................. MrPhilex (hehe)