Cracker du Visual Basic
(méthodes de comparaison et breakpoints)
mise à jour: le 28.juin.1999 Dans la mesure ou je suis un débutant, cet essai peut présenter des
erreurs. Disons que c'est une base de départ qui demande à être corrigée et complétée,
par vous ou par moi même. Il existe assez peu d'écrit sur Visual Basic en Français. Celui ci
est un mélange de notions apprises grâce à de fameux crackers comme Razzia, Eternal Bliss,
Sth... , et d'un peu de pratique personnel. Ces lignes ont été écrites bien après Cracks et Stratégies,
si bien que vous retrouverez de nombreuses répétitions dont vous voudrez bien m'excuser. Méthode de comparaisons: En Visual Basic, il y a plus de 8 méthodes disponibles pour qu'un auteur
contrôle la validité d'un sérial correct avec le code que vous avez pu entrer. J'en mentionne
seulement 8 parce qu'elles sont les plus faciles, et les plus utilisables dans notre quête. Les trois plus
courantes sont: 1- Comparaison de chaînes: Dans ce type de comparaison, une chaîne "sérial correct"
est comparée avec le code que vous avez entré dans le champ de la boite d'enregistrement. Les Strings Datas consistent en une séquence de caractères continus
qui représentent les caractères eux-mêmes au lieu de leur valeur numérique. Une chaînes
(string) peut inclure des lettres, des chiffres, des espaces, et des ponctuations. Le source en VB sera: If "sérial correct" = "sérial entré" then
--> comparaison directe de 2 chaînes C'est la forme la plus simple et la plus basic de comparaison utilisée par
des schémas de protection. Il est facile de provoquer un break dans SoftIce, quand un auteur utilise cette
fonction. _vbastrcomp ou _vbastrcmp ß pour STRing COMpare à noter: si vous crackez un programme VB6, vous devrez rajouter msvbm60!
Devant les deux breakpoints: bpx msvbm60! _vbastrcomp et msvbm60! _vbastrcmp la combinaison à rechercher donnera: 56 57 7C 24 10 8B 74 24 0C 8B 4C 24 14 33 C0 F3 66 A7 Dans cette méthode, 2 variables (Variant Data Type) sont utilisées
pour être comparées par deux autres. Variant Data Type est une Data Type spéciale qui peut contenir des caractères
numériques, des chaînes, des dates, aussi bien que des caractères définis par l'auteur,
et les valeurs Vide et Nulle. Les Variant Data Type sont codées sur 16 bits. Un exemple de code source possible donnerait: End If _vbavartsteq ß pour VARiant TeST Equal Pour les programme VB, il faudra toujours rajouter devant msvbm60!: soit un bpx msvbm60! _vbavartsteq Deux variables sont utilisées pour être comparées par une autre.
Elles sont codées sur 4 bits, et ne contiennent que des caractères de type numérique. Une exemple de code source pourrait être: End If Il n'y a pas de breakpoint spécifique pour ce type de méthode parce
que ces comparaisons se font dans l'exécutable, et non pas dans une Dll VB. Elles varient d'un programme
à l'autre. Il est, malgré tout, possible de se référer à l'annexe 1, en fin de cet essai. 4- Les comparaisons de Singles: Cette méthode utilise 2 variables du genre Single Data Type (Word) qui sont
comparées avec 2 autres. Elles sont de type numérique de -3.402 823 E 38 à +3.402 823 E 38.
Il arrive parfois, dans la routine de calcul du bon sérial, que le nom que vous avez entré apparaisse
dans l'une de ces Single Datas, codé sur 16 bits. Un exemple: Il n'y a pas de breakpoint spécifique pour ce type de méthode parce
que ces comparaisons se font dans l'exécutable, et pas dans une Dll VB, et qu'elles varient d'un programme
à l'autre. Il est, malgré tout, possible de se référer à l'annexe 1, en fin de cet essai. 5- Les comparaisons de Doubles: Cette méthode utilisent 2 variables de Double data (Dword) avec 2 autres. Ce type de Data, codés en 32 bits, est très similaire au fonctionnement
des Single Datas. Elles contiennent des valeurs de type numérique de - 1.797 693 134 862 32 E 308 à
+ 1.797 693 134 862 32 E 308 Cette méthode utilise 2 variables entières (Integer Data Type), pour
être comparées avec deux autres. Le codage se fait sur 2 bits, de -32 768 à +32 768, pour des
caractères numériques uniquement. Un code source possible serait: Là encore, il n'y a pas de breakpoints spécifiques. 7- Comparaison de Bytes: Cette méthode utilise 2 variable Byte Data Type pour être comparées
avec 2 autres. Elles sont codées sur 8 bits, de 0 à 255, et non signées. Seul des caractères
de type numérique sont utilisés dans ce genre de comparaison Le source possible: Cette méthode utilise deux variable du genre Currency Data Type, pour être
comparée avec deux autres. Le source est sur le même principe que les précédents. Cela veut-il dire qu'avec ces 8 approches, il est possible de marquer un point
d'arrêt dans chaque type de comparaison? Le réponse est NON. Et cela parce qu'au delà de ces 8 comparaisons,
il y a moyen des les combiner entres elles, Currency avec String, Variant avec Long, etc... Par contre, on peut créer un tableau de ce type:
String
Variant
Long
Currency
Single
Double
Integer
Byte
J
V
SD
SC
SS
SD
SD
SD
J
V
V
V
V
V
V
J
_vbaFpCmpCy
Sin to D
CD
CD
CD
J
_vbaFpCmpCy
_vbaFpCmpCy
_vbaFpCmpCy
_vbaFpCmpCy
J
CD
CD
CD
J
CD
CD
J
CD
J
De là, vous réalisez qu'utiliser SoftIce, sans autres outils, peut
se révéler un travail monstrueux. Et c'est toujours grâce à Numega, que vous pourrez
disposer de l'outil approprié: SmatCheck. (voir Annexe
1) Il n'en reste pas moins que, si vous vous en sentez le courage, les breakpoints
possibles, et les plus courants, sont: Manipulation de Data:
Je vais essayer de vous donner un aperçu de ce qu'il est possible de faire
en utilisant SmartCheck et SoftIce ensemble: Par exemple, si vous avez posé un bpx _vbafreestr, il peut y avoir plusieurs
d'entre eux utilisés après votre clic sur le bouton "register" . Si votre breakpoint spécifique
est indiqué comme étant le 10ème dans smartcheck, vous aurez à appuyer 9 fois sur F5, pour arriver à celui qui
vous intéresse.
Chaque version de Visual Basic a ses particularités. Dans le cas de VB 5,
il est assez facile de trouver le bon sérial: Audio List Maker vous accueille gentiment par un jolie musique, lance l’écran
de l’application, et une icône va se loger dans la barre des taches de Winmachin. Premier réflexe: regarder s’il n’y a pas de boite d’enregistrement. Elle
est accessible via le menu "?" : Il faut y entrer un nom, et 4 séries de 4 chiffres dans 4 espaces respectifs. L’entrée en matière que je préfère , dans le cas de
ces boites de dialogue, est de commencer en Live Approach, en posant un BPX Hmemcpy dans SoftIce. Aussitôt
dit, Aussitôt fait ! Après le break en Hmemcpy, une série de F12 vous amènes en
MSVBM50.dll, l'une des Dll VB5. MSVBM50, utilise, des API Windows du genre MultiByteToWideChar lors de la comparaison
de chaînes de caractères alphanumériques. Posez un bpx MultiByteToWideChar dans Softice, et relancez le programme. Vous allez
vous retrouver dans cette API. Quelques F12 pour en sortir, et retour à MSVBM50.dll : En descendant de quelques lignes, vous allez tomber sur 7B33150C Mov eax, ebp. Commencez
par poser un breakpoint dessus en appuyant sur F9, ou en double cliquant sur la ligne, puis faite un " d
ebp ". Vous verrez votre nom apparaître dans la fenêtre des Data sous la forme
VB (Wide Form): 017F:004373B2 63 00 68 00 72 00 69 00-73 00 74 00 61 00 6C 00 c.h.r.i.s.t.a.l . Et ça ne loupe pratiquement jamais ! Pour ne plus être ennuyé par les précédents points d’arrêt,
désamorcez les (BD), sauf le dernier. Si vous aimez la sécurité, vous pouvez poser un BPR sur la longueur
de votre nom, en tapant : Bpr 004373B2 004373C2 rw Ou la première adresse est celle relevée dans la fenêtre des
datas, et la seconde celle qui correspond à la dernière lettre de votre nom : 00x004373B2 +
00x0F = 00x004373C2. A partir de maintenant, Soft-Ice marquera un arrêt à chaque consultation de votre
nom en mémoire et sur toute sa longueur. Et vous relancez par F5. Au break suivant sur mov eax, ebp, un " d ebp "
va vous livrer le contenu de votre première série de 4 chiffres, vous pouvez encore poser un bpr
dessus, ainsi que sur les trois autres séries qui vont suivre. Suivant les cas, ces breakpoints_on_memory
peuvent se révéler utiles pour trouver l’écho du bon code, ou une comparaison avec le votre,
en interrogeant les registres à chaque break. En l’occurrence, pour Audio Liste Maker, vous pouvez vous
en dispenser, seul le bpx mov eax, ebp va être nécessaire. Désormais, à chaque break dans SoftIce, vous allez interroger le registre
ebp, et regarder plus ou moins 10 lignes au dessus et en dessous du retour que vous obtiendrez dans la fenêtre
des Datas, et vous finirez par y voir le bon sérial : Pour finir, le programme écrit votre nom et votre code dans la base de registre
en : Hkey_Local_Machine\enum\Software\Classses\Mia\AudioListeMaker\V1.52.1016. Name "christal" REGGED "ALM7-7185-0751-9X2K" Cette "méthode" marche couramment pour les programmes VB5. il y
a une autre adresse intéressante dans MSVBM50.dll, en 7B1D20F5: Suivant le type de comparaison que fera
l'auteur, vous avez des chances d'y trouvez le bon sérial à l'occasion de l'un des nombreux breaks
que le programme y fera.
Je vous encourage à lire les essais de razzia, concernant les programmes
en VB4. Il existe deux sortes de programmes VB4: ceux écrits en 16 bits, et ceux
en 32 bits. Comme dans VB5, le bpx MultiByteToWideChar est sollicité dans une majorité
de cas, et la méthode vue en annexe 2 tient la route, mais à la différence près que
le bon sérial peut se trouver dans la fonction suivante: La clé est sauvée sous sa forme héxadécimale, et placée
en mémoire. Si vous tapez un BPM dessus, vous verrez qu'elle sera comparée dans VB4 dll avec une
autre valeur: Il arrive parfois qu'un programme utilise un chemin légèrement différent
pour comparer le code d'enregistrement, avec celui que vous avez entré: Comparaison dans VB40032.Dll:
Bien souvent, vous trouverez un test du genre: If g0032=1 then "version enregistrée",
sinon "version shareware". Voici la solution de drjulo@hotmail.com pour arriver à shunter la protection, à partir d'une boite de dialogue: Pour finir, les comparaisons entre chaînes de caractères sont souvent
faites de la façon suivante: Comparaison dans VB300.Dll:
Avant propos:
GoTo Code_Ok
Else
GoTo Code_invalide
End If
Breakpoint à poser:
2- Comparaison de variables:Dim correct As Variant, entered As Variant défini "correct" et "entered" comme des variables
correct = code valide met le bon sérial dans correct
entered = Text1.text met votre sérial_entré dans entered
if correct = entered Then compare les variables
GoTo code_ok
Else
GoTo code_invalide
Breakpoint à poser:
3- Comparaison de longueur de variables:Dim correct As Long, entered As Long défini "correct" et "entered"
correct = 12345 met le bon sérial dans "correct"
entered = Text1.Text met le code entré dans "entered"
If entered = correct compare la long des 2 variables
GoTo code_ok
Else
GoT0 code_invalide
Passons à 5 autres méthodes de comparaison:Dim correct As Single, entered As Single --> défini "correct" et "entered" comme des Single
correct = Code valide --> met le bon sérial dans "correct"
entered = Text1.Text --> met le sérial entré dans "entered"
If correct = entered Then --> compare les 2 variables crées à l'occasion
GoTo code_ok
Else
GoT0 code_invalide
End If
Dim correct As Double, entered As Double --> défini "correct" et "entered" comme des Double
correct = Code valide --> met le bon sérial dans "correct"
entered = Text1.Text --> met le sérial entré dans "entered"
If correct = entered Then --> compare les 2 variables crées à l'occasion
GoTo code_ok
Else
GoT0 code_invalide
End If
6- Comparaison d'entiers:Dim correct As Integer, entered As Integer --> défini "correct" et "entered" comme entiers
correct = Code valide --> met le bon sérial dans "correct"
entered = Text1.Text --> met le sérial entré dans "entered"
If correct = entered Then --> compare les 2 variables crées à l'occasion
GoTo code_ok
Else
GoT0 code_invalide
End If
Dim correct As Byte, entered As Byte --> défini "correct" et "entered" comme des Bytes
correct = Code valide --> met le bon sérial dans "correct"
entered = Text1.Text --> met le sérial entré dans "entered"
If correct = entered Then --> compare les 2 variables crées à l'occasion
GoTo code_ok
Else
GoT0 code_invalide
End If
8- Comparaison des Currency:
String
Variant
Long
Currency
Single
Double
Integer
Byte
V= Comparaison de Variant
SD = String convertie en Double avant comparaison
SC = String convertie en Currency avant comparaison
SS = String convertie en Single avant comparaison
Sin to D = Single convertie en Double avant comparaison
CD = Comparaison directe
_vbaFpCmpCy Floating point CoMpare CurrencY
String en Byte ou Integer : _vbai2str
String en Long: _vbai4str
String en Single: _vbar4str
String en Double: _vba8str
String en Currency: VarCyFromStr
Integer en String: VarBstrFromI2
String vers la mémoire: _vbaStrCopy
Variant vers la mémoire: _vbaVarCopy ou _vbaVarMove
Addition de variables: _vbavaradd
Soustraction de variables _vbavarsub
Multiplication de varaibles _vbavarmul
Division de variables _vbavaridiv
Boucle For... Next: _vbavarfornext
Saisie d'un caractère dans une chaine: _vbastrvarval
etc...
Annexe 1:
La meilleure chance de cracker du visual basic, est de disposer de SmartCheck.
Vous aurez à apprendre à l'utiliser, et à comprendre ce qu'il vous donne comme informations.
Annexe 2:
Le cas des programmes VB5
Prennons le cas de Audio List Maker:
MSVBM50.Dll :
Call [KERNEL32!MultiByteToWideChar]
Mov ebx, eax à vous serez ici
Cmp esi, FFFFFFFF
Jne 0F738BCF
Dec ebx
Push ebx
Push 00
Call dword ptr [0F7BC918]
Mov ebp, eax
Test ebp, ebp
Jz 0F74B23D
Inc ebx
Push ebx
Push ebp
Pop esi
Push edi
Push 00
Push 00
Call [KERNEL32!MultiByteToWideChar]
Mov eax, ebp à mais c'est ici que ca se passe
Pop edi
Push esi
0167:004659F0 36 00 00 A0 26 00 00 00-41 00 4C 00 4D 00 37 00 6...&...A.L.M.7.
0167:00465A00 2D 00 37 00 31 00 38 00-35 00 2D 00 30 00 37 00 -.7.1.8.5.-.0.7.
0167:00465A10 35 00 31 00 2D 00 39 00-58 00 32 00 4B 00 00 00 5.1.-.9.X.2.K...
* Reference To: OLEAUT32.SysAllocStringByteLen, Ord:0096h
|
:7B1D20C4 FF1598191D7B Call dword ptr [7B1D1998]
:7B1D20CA 85C0 test eax, eax
:7B1D20CC 0F84AFFF0500 je 7B232081
:7B1D20D2 8BF8 mov edi, eax
:7B1D20D4 8BCB mov ecx, ebx
:7B1D20D6 C1E902 shr ecx, 02
:7B1D20D9 F3 repz à
à partir de cette adresse,vous commencerez
:7B1D20DA A5 movsd à trouver les premières traces du bon code
:7B1D20DB 8BCB mov ecx, ebx
:7B1D20DD 83E103 and ecx, 00000003
:7B1D20E0 F3 repz
:7B1D20E1 A4 movsb
:7B1D20E2 8D3C18 lea edi, dword ptr [eax+ebx]
:7B1D20E5 8B742414 mov esi, dword ptr [esp+14]
:7B1D20E9 8BCD mov ecx, ebp
:7B1D20EB C1E902 shr ecx, 02
:7B1D20EE F3 repz
:7B1D20EF A5 movsd
:7B1D20F0 8BCD mov ecx, ebp
:7B1D20F2 83E103 and ecx, 00000003
:7B1D20F5 F3 repz --> adresse où le sérial complet sera lu dans edi
:7B1D20F6 A4 movsb
:7B1D20F7 5D pop ebp
:7B1D20F8 5F pop edi
:7B1D20F9 5E pop esi
:7B1D20FA 5B pop ebx
:7B1D20FB C20800 ret 0008
Annexe 3:
Le cas des programmes VB4( listing de OLEAUT32.DLL)
:6534B6B3 395C240C cmp [esp + 0C], ebx boucle qui tourne
:6534B6B7 7E14 jle 6534B6CD à l'intérieure de la
:6534B6B9 33C9 xor ecx, ecx chaine de caractères.
:6534B6BB 8D0492 lea eax, [edx + 4*edx] A la fin edx aura la
:6534B6BE 8A0E mov cl , [esi] valeur hexa de la
:6534B6C0 46 inc esi chaîne
:6534B6C1 4F dec edi
:6534B6C2 FF4C240C dec [esp + 0C]
:6534B6C6 8D1441 lea edx, [ecx + 2*eax]
:6534B6C9 85FF test edi, edi
:6534B6CB 7FE6 jg 6534B6B3
:6534B6CD 85FF test edi, edi
:6534B6CF 7F4A jg 6534B71B
.............
.............
:6534B6F2 8910 mov [eax], edx edx est sauvé
:6534B6F4 33C0 xor eax, eax
:6534B6F6 83C424 add esp, 00000024
:6534B6F9 C21000 ret 0010
:0F7A2CE1 5A pop edx --> charge edx
:0F7A2CE2 58 pop eax --> charge eax
:0F7A2CE3 2BC2 sub eax, edx --> soustrait l'une à l'autre
:0F7A2CE5 83F801 cmp eax, 00000001
:0F7A2CE8 1BC0 sbb eax, eax
:0F7A2CEA 50 push eax
:0F7A2CEB 0FB706 movzx word ptr eax, [esi]
:0F7A2CEE 83C602 add esi, 00000002
:0F7A2CF1 FF2445F4997B0F jmp dword ptr [2*eax + 0F7B99F4]
:0F7A2CF8 E8BB000000 call 0F7A2DB8
C'est une autre forme de comparaison, par un jeu de soustraction entre la valeur
des registres edx et eax. L'un d'eux aura la valeur que vous avez entré, et l'autre le numéro de
série correct.
Comparaison dans VB40016.Dll:: 8BF8 MOV DI,AX
: 8EC2 MOV ES,DX
: 1E PUSH DS
: C5760E LDS SI,[BP+0E]
: 33C0 XOR AX,AX
: F3A6 REPZ CMPSB --> la comparaison se fait ici
: 7405 JZ 2667 entre ds:si et es:di
: 1BC0 SBB AX,AX
: 1DFFFF SBB AX,FFFF
:0F79B348 56 push esi
:0F79B349 57 push edi
:0F79B34A 8B7C2410 mov edi, [esp + 10] à es:edi ->votre code
:0F79B34E 8B74240C mov esi, [esp + 0C] à esi -> bon sérial
:0F79B352 8B4C2414 mov ecx, [esp + 14]
:0F79B356 33C0 xor eax, eax
:0F79B358 F366A7 repz cmpsw -> comparaison
:0F79B35B 7405 je 0F79B362
:0F79B35D 1BC0 sbb eax, eax
:0F79B35F 83D8FF sbb eax, FFFFFFFF
:0F79B362 5F pop edi
:0F79B363 5E pop esi
:0F79B364 C20C00 ret 000C
Annexe 4:
Dans la majorité des cas, le texte de ces messages apparaît dans la traduction du code hexadécimale.
De plus les propriétés de chaque objet (boutons, boites de texte, ...), et les routines se trouvent bien séparés
par rapport au programme.
Voici répertorié dans ce tableau quelque traduction du code Visual Basic :
Test entre un objet " Texte " et une variable string C31168 Si =
C3117A Si <>
Test entre deux variables de type " string " 1A00F6 Si =
1A00FF Si <>
Début d'une routine 4B49 juste après 0E5B0E
Fin d'une routine 0E5B0E
Voici un petit exemple qui illustre les tests entre Texte et variable.
Crack de CompKino :
Installez-vous confortablement et lancez un première fois CompKino pour voir ce qui se passe dedans !
Bien ! On nous demande un code dans un objet " Texte ".
Il y aura sûrement un test entre cet objet et une variable comportant le bon code.
Lorsqu'on entre un mauvais code, une barre apparaît vous disant " Invalid activation code ".
Allons voir tout ça dans le listing hexadécimale.
En Visual Basic, les chaînes de caractères (messages) sont visibles dans le listing ASCII.
Cherchons le message " Invalid activation code " en respectant la case (les majuscules).
000019E0 0000 0000 0000 0000 0000 0000 0000 0000 ................
000019F0 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001A00 4B49 E537 B00E A84C 0100 4C00 094C 0BC0 KI.7...L..L..L..
00001A10 6C2B 3000 C311 6844 B734 7E01 3549 9A38 l+0...zD.4~.5I.8
00001A20 1000 2400 0A00 4272 6176 6F21 2121 2020 ..$...Bravo! ! !
00001A30 0000 C311 ED37 B00E A84C 0100 4C00 094C .....7...L..L..L
00001A40 0BC0 B877 144C 5200 3549 ED37 B00E A84C ...w.LR.5I.7...L
00001A50 0100 4C00 094C 0BC0 9A38 0600 5E00 0000 ..L..L...8..^...
00001A60 0000 C311 6844 B734 C000 1F49 B167 ED37 ....zD.4...I.g.7
00001A70 B00E A84C 0100 4C00 C34F 6737 614B 8800 ...L..L..Og7aK..
00001A80 0000 584B 1300 0000 FC4F 0100 6A37 1F49 ..XK.....O..j7.I
00001A90 9A38 1C00 9600 1700 456E 7465 7220 796F .8......Enter yo
00001AA0 7572 206E 616D 6520 706C 6561 7365 2100 ur name please!.
...
00001BE0 E201 1800 496E 7661 6C69 6420 6163 7469 ....Invalid acti
00001BF0 7661 7469 6F6E 2063 6F64 6521 0000 C311 vation code!....
...
00001C90 7221 0000 C311 144C 5200 3549 EC35 4B49..r!.....LR.5I.5KI
00001CA0 EC35 4B49 D965 5E0E 5B0E 4B49 502B 4400...5KI.e^.[.KIP+D.
En remontant, nous cherchons le début de la routine et plus bas la fin pour voir le domaine d'étude.
Remarquez les nombreux messages qui font penser à une certaine boite demandant un mot de passe!
C'est donc là-dedans que se trouve le problème.
Ce que nous cherchons est plutôt un test entre un objet Texte et une Variable.
Nous trouvons deux Codes (C31168).
Si on regarde bien l'un est avant " bravo " l'autre après.
En réfléchissant un peu on se dit que " bravo " intervient lorsque le mot de passe entré est juste.
Donc le test s'effectue avant. C'est donc le premier que l'on remplacera par un C3117A.
Le deuxième teste est pour le deuxième objet Texte qui va tester la présence d'un nom.
Si vous n'avez pas inscrit de nom, alors vous tombez sur " Enter your name please ".
En remplaçant ce test par C3117A vous ne devrez plus entrer de nom sinon vous
retomberiez sur la même phrase.
Relancez le soft, entrez un mot de passe bidon et un nom
(si vous n'avez pas changé le deuxième test).
Le logiciel est maintenant dans sa version enregistrée.
: 8BCA mov cx, dx
: F3A6 repz cmpsb ß les 2 codes sont comparés
: 7401 je 8CB6 dans ds:si et es:di
: 9F lahf
: 92 xchg ax,dx
: 8D5E08 lea bx, [bp+08]
: E80E06 call 92CB
Bonne Journée