|
Hi everybody ! Bein vi, me revoili, de quoi allons-nous parler aujourd'hui
? D'un bête programme ininteressant, mais alors vraiment sans aucun
intérêt (enfin tout du moins pour moi), un truc de bidouille
audio. Le seul truc qui m'a brancher dans ce logiciel c'est la protection,
et à ce propos j'aimerai remercier 3 personnes pour ce tut :
- Xose qui, sans le savoir, m'a eclairé le chemin.
- Ethan, qui à eu une idée géniale sur FruityLoop
(allez choper le tut sur mon site).
- Razzia, grâce à son tut "crippled programs" j'ai pu
mener à bien ma "mission" ;)
Tu peux trouver Awave sur le CD Pro PCTeam N° 44, rubrique sharewares ... ou http://hem.passagen.se/fmj/fmjsoft.html
Le proggy n'a même pas besoin d'être installé, tu peux le lancer en direct.
Quand tu l'execute la première fois, tu as le classique nag-screen
de démarrage à 3 balles :(
Tu as également quelques fonctions désactivées,
mais apparemment pas de limitation dans le temps.
|
Bein là si tu y arrives, tu es très très fort !!! la version distribuée sur le CD PCteam est crypted, alors IDA te donneras que dalle, et Wdasm encore moins !!!
Solution de secours : ProcDump v1.4 ... pô de bol, le code de compression n'est pas reconnu :(
Bein, quand c'est comme ca, tu es plutôt mal barré ... il te reste quoi ?
Ton cerveau banane !!!!
Voilà mon raisonnement :
" Bon, ok, ce programme fait iech, tu peux pas le patcher sur disque,
tu vas pas faire un patcher mémoire pour un programme à 2
balles, cracke le déja en mémoire, et pis après on
trouvera une solution adéquate"... Alors avec mes petites mains,
j'ai lançé ProcDump v1.4 pour dumper le process sur le disque.
J'expliqe la procédure pour les durs de la feuilles qui n'ont pas
encore utilisé ProcDump (shame on U !) :
- Lance ton programme Awave
- Lance ProcDump
- Clique avec le bouton droit sur le process Awave (dans ProcDump,
hein, on s'était bien compris ? ;)
- Clique sur Dump Full
- Donne un nom bidon, genre awave_dump.exe
- Desassemble le tout avec IDA
- Profite aussi pour desassembler le code d'Awave compresser, ca va
être utile
Et là, on peut déja avoir une base pour bosser correctement, l'objectif étant de patcher en mémoire sous Sice le prg.
A partir de ce moment, je te conseille de lire le tut de Ethan sur FruityLoop,
au risque de ne pas tout comprendre ...
|
Lorsque tu desassemble le code d'Awave avec IDA, tu te retrouve içi :
¦CODE:004403C6 start
proc near
¦CODE:004403C6
jnz short $+2
¦CODE:004403C8
jmp loc_0_4DF000
¦CODE:004403C8 start
endp
Alors pourquoi içi et pas ailleurs ??? pourquoi pas en 00401000 comme la plupart des EntryPoint dans les prog Win 32 ? Et bien, tout simplement, toujours avec ProcDump, lance un PE Editor, et selectionne ton programme Awave.exe, ProcDump te donne comme Entry Point 000403C6 avec comme Image Base 00400000, soit un entry point égal à 000403C6+00400000 = 004403C6.
Mais bon, continuons :
Un jmp en loc_0_04DF000 t'amène içi :
.data:004DF000 loc_0_4DF000:
; CODE XREF: start+2j
.data:004DF000
pusha
.data:004DF001
call $+5
.data:004DF006
pop ebp
.data:004DF007
sub ebp, offset unk_0_4398AE
.data:004DF00D
mov eax, offset unk_0_4398A8
.data:004DF012
add eax, ebp
.data:004DF014
sub eax, dword ptr ss:unk_0_439D18[ebp]
.data:004DF01A
mov dword ptr ss:aI2v[ebp], eax
.data:004DF020
cmp byte ptr ss:a9josNlq[ebp], 0
.data:004DF027
jnz short loc_0_4DF03E
.data:004DF029
inc byte ptr ss:a9josNlq[ebp]
.data:004DF02F
call sub_0_4DF051
.data:004DF034
call sub_0_4DF2AC
.data:004DF039
call sub_0_4DF348
.data:004DF03E
.data:004DF03E loc_0_4DF03E:
; CODE XREF: .data:004DF027j
.data:004DF03E
mov eax, dword ptr ss:(a9josNlq+2)[ebp]
.data:004DF044
add eax, dword ptr ss:aI2v[ebp]
.data:004DF04A
mov [esp+1Ch], eax
.data:004DF04E
popa
.data:004DF04F
jmp eax
Voilà une chose bizarre, que Ethan nous avait déja fai
remarqué dans FruityLoop, un jmp eax louche ... on va vite être
fixé, lance le loader de Soft-Ice, puis lance Awave, problème,
le loader ne te rend pas la main, pô grave, place un BPX dialogboxparamA,
de tel sorte que Sice te rende la main lorsque le programme affichera son
nag-screen, une fois que tu seras sous Sice, fait un F12 pour sortir de
l'API dialogboxparamA, tu te trouveras dans le code de Awave, fais maintenant
un "u 004DF04F", Sice t'affichera le code que tu vois plus haut, c kewl,
place maintenant un "bpm 004df04f x" et relance ton programme (n'oublie
pas si tu veux pas être embeté de supprimer le breakpoint
sur dialogboxparamA).
Logiquement, après avoir relancé le loader tu te trouvera
à l'adresse 004DF04F, et eax contiendra la valeur 00401000, nous
savons maintenant ou se situe notre point d'entrée dans le programme.
Reste maintenant à trouver les bytes à patcher pour faire
croire à Awave que nous sommes enregistré. Maintenant nous
allons voir des choses plus "classiques" :
|
IDA nous est hyper utile à ce niveau, Wdasm ne comprends rien
à ce qui se passe, je suis sur qu'en bidouillant un peu nous aurions
pu arranger ca, mais bon, utilisons ce merveilleux outil qu'est IDA, tout
d'abord n'oublie pas que cette fois, nous desassemblons l'exe dumpé
par ProcDump.
Lorsque tu as lançé Awave et que tu avais posé
un bpx sur DialogboxparamA tu as surement noté l'adresse de l'appel,
non ? si c'est le cas, tu te trouvera içi :
CODE:00405A7A loc_0_405A7A:
; CODE XREF: sub_0_4059C8+18j
CODE:00405A7A
push 0
CODE:00405A7C
push offset loc_0_405698
CODE:00405A81
push ebx
CODE:00405A82
push 22h
CODE:00405A84
mov eax, ds:dword_0_4B2B28
CODE:00405A89
push eax
CODE:00405A8A
call sub_0_48B6AE
<-
Appel de DialogBoxparamA
CODE:00405A8F
CODE:00405A8F loc_0_405A8F:
; CODE XREF: sub_0_4059C8+9Fj
CODE:00405A8F
; sub_0_4059C8+B0j
CODE:00405A8F
pop edi
CODE:00405A90
pop esi
CODE:00405A91
pop ebx
CODE:00405A92
mov esp, ebp
CODE:00405A94
pop ebp
CODE:00405A95
retn 4
CODE:00405A95 sub_0_4059C8 endp
Cette routine est appelée en sub_0_4059C8+18 zyva pour voir :
CODE:004059D1
mov ebx, [ebp+arg_0]
CODE:004059D4
push offset unk_0_48DAA7
CODE:004059D9
call sub_0_409258 <-
Call bizarre
CODE:004059DE
test al, al <- Test encore
plus bizarre
CODE:004059E0
jz loc_0_405A7A <-
Le saut provient d'içi
CODE:004059E6
mov [ebp+var_50], 28h
CODE:004059ED
xor eax, eax
Donc première conclusion, l'affichage de la boite de dialogue provient de du call en sub_0_409258, rentrons à l'intérieur de cette routine (double clic sur l'appel à la fonction), nous arrivons içi :
CODE:00409258
push ebp
CODE:00409259
mov ebp, esp
CODE:0040925B
push ebx
CODE:0040925C
push esi
.
. Code blabla ...
.
CODE:00409297
push esi
CODE:00409298
call sub_0_401304 (içi sub_0_401304 = 00401305)
CODE:0040929D
test eax, eax <- eax=0 ?
CODE:0040929F
setz al <- Position al à
01 si eax=0
CODE:004092A2
and eax, 1 <- et logique
entre eax et 01, donc eax=01 si eax=00 à la sortie du call
CODE:004092A5
CODE:004092A5 loc_0_4092A5:
CODE:004092A5
pop edi
CODE:004092A6
pop esi
CODE:004092A7
pop ebx
CODE:004092A8
pop ebp
CODE:004092A9
retn 4
CODE:004092A9 sub_0_409258 endp
En fait, al est testé à la sortie de cette fonction, or
al provient du code en 004092a2, qui lui-même prend la valeur dans
le call sub_0_401304.
On va faire l'essai sous Sice de placer un "bpm 00401305 x", histoire
de voir si le retour de cette fonction est important ...
Effectivement, lors du démarrage du programme, tu as du breaker plusieurs fois sur cette fonction, par F12 tu es sorti de la fonction, et à chaque fois eax est différent de 0 (genre eax=888 ou autres), et si tu forces EAX à 0, tu pourras remarquer que ton programme est enregistré. J'en déduis donc que la fonction commençant en 00401305 détermine si nous sommes enregistrés ou non, il suffit donc de patcher dans cette fonction, plus exactement, je serais de patcher à cet endroit :
CODE:004013E6
mov eax, ebx <- IçI,
le programme fixe eax avec la valeur en ebx
et ebx est le résultat d'enregistrement
CODE:004013E8
CODE:004013E8 loc_0_4013E8:
CODE:004013E8
pop esi
CODE:004013E9
pop ebx
CODE:004013EA
mov esp, ebp
CODE:004013EC
pop ebp
CODE:004013ED
retn 14h
Le code en 004013E6 est toujours executé, il nous est façile de patcher cet endroit et de remplacer
mov eax, ebx
par
xor eax,eax
de cette façon eax sera toujours égal à 0 ...
Patche en mémoire sous Sice, tape "A 004013E6" et tape le code
suivant : "XOR EAX,EAX", lançe ton programme et voilà !!!
le programme fonctionn à merveille, met toi sur about, pas de problème,
met toi sur les fonctions désactivées, pas de problèmes,
va sur le menu "options -> program setup" et boum ! le programme se termine
net, sans messages d'erreurs, sans rien ... alors après analyse,
j'en ai déduis qu'apparemment le programme aurait un bogue :
En effet, si tu n'es pas enregistré le setup fonctionne à
merveille, sinon, si tu es enregistré, ca kill le process, pourquoi
??? je ne sais pas, la seule chose que j'ai constaté c'est la différence
du code lors du retour des précedentes fonctions, on avait quelque
chose comme ca (cf plus haut) :
CODE:0040929D
test eax, eax <- eax=0 ?
CODE:0040929F
setnz al <- Position al à
01 si eax=0
CODE:004092A2
and eax, 1 <- et logique
entre eax et 01, donc eax=01 si eax=00 à la sortie du call
or là, pour le "setup program" on a quelque chose comme ca :
CODE:0040929D
test eax, eax <- eax=0 ?
CODE:0040929F
setz al <- Position al à
01 si eax=01
CODE:004092A2
and eax, 1 <- et logique
entre eax et 01, donc eax=01 si eax=01 à la sortie du call
Ce qui est assez étrange, si le programme est enregistré, il se considère comme non enregistré !!! Je pense que c'est un bogue, mais si quelqu'un à une idée ...
Enfin bref, nous allons modifier ce setnz en setz, nous aurons donc 2 patchs à appliquer, je les résumes :
un patche en 004013E6 de ce type :
8BC3 MOV EAX, EBX
en
33C0 XOR EAX, EAX
et un patche en 0040929F de ce type :
0F94C0 SETZ AL
en
0F95C0 SETNZ AL
Problème : comment patcher le programme sachant que le fichier
est compressé/crypté ??? Le truc serait de patcher le programme
en mémoire juste avant le fameux saut "JMP EAX" ...
|
Arrivé à ce niveau, il est nécessaire de savoir
comment fonctionne (vaguement ;) le format PE ...
Il faut savoir que ton programme est divisé en sections, et
chaque section possède une entrée dans le PE Header, ca veut
dire que notre code de décryptage possède une section dans
le PE Header, ProcDump nous permet de savoir les détails de cette
section :
|
|
|
|
|
.data | 00002000 | 000DF000 | 00001400 | 00050A00 |
La taille virtuelle de notre code est 2000, ce qui veut dire qu'en RAM,
la mémoire allouée pour notre code est de taille 0x2000 octets,
ce qui toujours un multiple de la page (en particulier içi 0x1000),
en effet, la mémoire allouée doit toujours être multiple
de l'offset virtuel de la section CODE.
L'offset virtuel de notre code est de 000DF000, additionné à
l'image de base (00400000), ca nous donne une adresse virtuelle de 004DF000
(et comme par hasard, cette adresse nous mène droit vers l'EIP du
programme).
La taille sur disque (Raw Size) est de 0x1400, ce qui veut dire que
le code n'utilise que 0x1400 octets dans le fichier .exe.
L'offset sur disque (Raw Offset) est de 00050A00, autrement dit le
code s'étale sur le disque de l'offset 0050A00 jusqu'a (0050A00+1400)=0051E00.
Si la taille doit toujours être un multiple, ca veut dire que le système lors de la compilation d'un programme doit "boucher" les trous pour obtenir la taille exigée, ca doit faire de la place libre ca non ??? limite qu'on pourrait exploiter non ??? vous me voyez venir ? ;)
Je te conseille de regarder après les informations de versions,
tu trouveras tout plein de "00" à remplir ;) de plus fais bien gaffe
avec ce genre de technique, il faut prendre en considération deux
points très importants :
- Toujours bien vérifier que le code que tu va écrire
fait toujours parti de la section dans laquelle tu veux rajouter ton code
- Cherche des endroits avec pleins de zéros, je sais c'est
aléatoire, mais j'ai constaté que l'écrasement de
certaines données, même si elles sont totalement inutiles
et situées à des endroits "insolites" peuvent être
utilisées dans un programme.
Apparemment l'adresse virtuelle 004DFBB7 me parait être un endroit approprié, apparemment nous sommes arrivés à la fin du code. Il ne nous reste plus qu'a taper notre code tout beau sous Hiew, maintenant vient la partie du calcul de l'offset sur le disque :
Offset sur le disque = (00DFBB7 - offset virtuel) + Raw Offset
soit (00DFBB7-00DF000) + 00050A00 = 000515B7
Nous plaçerons donc Hiew en 000515B7 et nous allons écrire le code suivant :
mov [esp+1Ch], eax
popa <- Pourquoi ce code ??? tout simplement
parce que nous avons besoin de plus de 2 octets en 004DF04F pour effectuer
notre saut dans cette partie du code ...donc nous allons écraser
le code avant 004DF04F pour le placer içi, ce qui revient au même.
push eax
; sauvegarde du registre eax
mov edi, 004013E6 ; on
place l'adresse des premiers patches en edi
mov eax, C033
; eax = C033
stosw
; [edi] = eax
mov edi, 004092A0 ; edi
= adresse du 2eme patche
mov ax,95
; eax = 95
stosb
; [edi] = ax
pop eax
jmp eax
Et voilà, occupons nous maintenant du point d'entrée içi :
.data:004DF04A
mov [esp+1Ch], eax
.data:004DF04E
popa
.data:004DF04F
jmp eax
Et remplaçons ce code par celui-çi :
jmp 004DFBB7
L'adresse du jmp eax se trouve en (00DF04F-00DF000)+50A00
soit 00050A4F, or le jmp 004DFBB7 occupe plus de 2 octets, nous allons
donc écraser le code en 004DF04A (le code présent n'a pas
d'importance puisque nous l'avons ajouté dans notre routine perso),
l'adresse 004DF04A sous Hiew correspond à 00050A4A, rajoutons donc
jmp 004DFBB7.
et voilà, relançer votre programme, et normalement vous devriez avoir un programme enregistré qui se patche lui-même !!! ;)
Voilà une technique qui peut être
intéressante en cas d'absolue nécessité, et oui, ProcDump
ne peut quelque fois pas tout décompacter, et il peut être
utile de patcher en mémoire, en cas de vérif' checksum par
exemple ...
|
C'est fini, j'espère avoir été
clair, pour ceux qui en désire plus, je leur conseille d'aller sur
mon site :
Tu y trouveras de nombreux liens sur d'autres sites de cracking (all in french ;), avec les forums de +Frog's Print (notre maître à tous) et celui de la Main Rouge, ou de nombreux 'tits gars se réjouiront de t'aider. Pour ma part malheureusement, je n'aurais pas le temps de te répondre, faute de temps, je préfère te prévenir afin que tu ne te vexe pas si je ne répond pas ;)
Et maintenant les GreetZ :
Tout le monde ... sauf les cons ...
ils se reconnaitront ;)
Mais spécial dédicace quand
même à :
+ORC
+Fravia
+Frog's Print
+Spath
All Ozer +HCU Students
Artex
Psyché
Pass Partout
Xose
Acid Flag
Nody
Elraizer
The_Iceman
MacroBio
Acid Nitric
Alsindor
Votan
BlueWin
Lïou-jungle
Enkil
Simon tête creuse
sfm
Ethan
[BamA]
Jordan_Jr
Tous les membres de fusion
[Jacques Chirac/CC]
[Jean Gabin/CC]
Tous les membres de [CC]
Cyberghost
TaZ
Jozio
The Ben
Koba Yashi/Rico
Razzia
Anonymous/MisterX
MovAx1st
Le_Magicien
La_crapule
Hug's 2000
Et tous mes potes que je n'ai pas cités
(oubli involontaire) et tous ceux avec qui j'ai passé des semaines
et des semaines à apprendre l'art du cracking, tous mes potes du
Forum de +FP et de la Main Rouge, merci à vous tous ...
RDV A dieu.