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)