Keygenner M*a*l*w*a*r*e*b*y*t*e*s Anti-Malware v1.50

Introduction:


Just for fun.


Les outils:



I: Démarrage:


Alors commençons, la première chose que j'ai l'habitude de faire est d'analyser l'exécutable principal (mbam.exe) avec un détecteur de packers du genre PEiD pour avoir un bref résumé de quoi il en retourne.


1


L'exe ne semble pas packé et PEiD détecte que l'application a été codée en visual basic 6. Voyons maintenant ce que peut nous dire le plugin Krypto ANALyzer, s’il peut détecter quelque chose d’intéressant.


1

KANAL trouve un peu de crypto, pas grand-chose... on verra bien.


II: Trouver la routine d'enregistrement:


Ok, maintenant chargeons la cible dans Ollydbg, on arrive sur l'OEP en 00402D6C comme indiqué sur la capture d'écran de PEiD:


00402D6C . 68 24364000 PUSH 00403624 ; ASCII "VB5!6&*"
00402D71 . E8 EEFFFFFF CALL ; Jump to MSVBVM60.ThunRTMain

Le string «VB5!6&*» ainsi que la présence de MSVBVM60 confirme que l'application ait été codée en Visual Basic 6.
Lancez totalement l'application dans le debugger (F9), une fois lancée, cliquez sur le bouton [Enregistrer] en bas.
Entrez n'importe quoi puis appuyez sur Enregistrer.


1

Nous obtenons le message:


1

N'appuyez pas sur OK, revenez dans Ollydbg et cliquez sur le bouton pause (F12)
Ensuite, allez dans le menu 'Debug' et cliquez sur «execute till user code» (ou bien simplement Alt+F9)


1


Revenez sur le message d'erreur et appuyez sur OK


1

Le debogueur break, en remontant le code, on s'aperçoit de MSVBVM60.rtcMsgBox juste au-dessus, puis un peu plus haut un JMP, on clique pour se positionner sur la ligne du dessous, olly nous indique que le saut provient de 00477B54


1

Un clique droit et on suit le jump


1

On se retrouve donc en 00477B54, on remarque la présence d'une procédure suivie d'un test, et en fonction du résultat nous amène sur la messagebox, ou pas.


1

Remontons toute la procédure principale pour y placer un breakpoint avec F2, tracer cette procédure depuis le début nous permettra d'y voir plus claire sur le déroulement des événements dans cette partie du code.


1

Si on se pose sur l'instruction PUSH EBP, la fenêtre de dump nous dit que l'on vient de l'adresse: 00405B78, éventuellement on va y jeter un oeil.


1

Il semblerait que l'on soit remonté un peu trop haut, donc notre bp en 00477990 est parfait.


III: Comprendre la routine d'enregistrement:


Maintenant que l'on a notre breakpoint placé en début de routine, relançons totalement l'exécutable avec F9. On appuie à nouveau sur le bouton 'Enregister' et.. Le débogueur break.
On trace le code avec F8, nous ne verrons rien de vraiment intéressant jusqu'à ce que nous atteignions à nouveau notre saut sur la MessageBox. On obverse quand même que notre ID Produit et passé en majuscule via rtcUpperCaseBstr.

1

Appuyez sur F7 (Step into) pour entrer dans la routine, puis continuez avec Step over (F8) une fois à l'intérieur.


1

La première chose que nous rencontrons c'est une vérification de conformité du sérial:


1

La fonction InStr() permet de tester si un texte contient une chaîne de caractères spécifiée:
InStr(DebutDeRecherche, LeTextePrincipal, LaChaineRecherchee, TypeDeComparaison)
Dans notre cas, il recherche le tiret («2D» en hexadécimal) qui est observable avant la série de InStr (PUSH 00414C10)

1

Un total de 3 vérifications, avec un tiret obligatoire en position 5, 10, et 15.
C'est-à-dire que notre sérial doit avoir la forme: XXXX-XXXX-XXXX-XXXX
Si on réessaye avec 1337-1337-1337-1337 par exemple, nous passons la vérification de conformité sans soucis.

1

Suivant!
Continuons en step over avec F8 et notre nouveau fake sérial, maintenant le programme va vérifier si «l'ID de produit» est également conforme.


1

Ici, nous avons l'API «__vbaStrLike» exportée par msvbvm60.dll
Il vérifie si le premier caractère de l'ID produit correspond à un chiffre entre 1 et 9
Sinon, il quitte la routine via le saut conditionnel.
Donc le premier caractère doit être un numérique compris entre 1 et 9 inclus (et pas de «0» bien sûr)
Après ça le programme va continuer à utiliser cette api pour tester le reste individuellement.
En 2ème position, le caractère doit être une lettre entre A-Z inclus.:

1

En 3ème position, c'est aussi une lettre entre A-Z inclus. :

1

En 4ème position, il demande un chiffre entre 1-9 inclus.:

1

En 5ème et dernière position, il demande aussi un chiffre entre 1-9 inclus. :

1

Voilà, un ID de produit conforme peu être: 1AB23, on peut donc réessayer, mais cette fois-ci avec:
Product ID: 1AB23
Serial: 1337-1337-1337-1337

Super, les sauts ne sont pas pris, bon continuons.

Après avoir compris le format correct de l'ID Produit ainsi que le format du sérial attendu, on voit encore deux sauts qui nous font quitter la routine si on les prend (facile à reconnaître, ça saute toujours à la même ligne depuis tout à l'heure si quelque chose ne va pas)


1

Alors, entrons dans la première routine avec (F7) pour voir ce qu'il veut cette fois.

1

Hey! on a là, un keygen check!
Le programme vérifie si lors de la validation vous avez utilisé un keygen.
Il regarde la liste des processus pour détecter s’il y a un «keygen.exe» en cours d'exécution. Il regarde également le handle pour détecter 'CRUDE' (un groupe de cracking)


1

Donc, si vous utilisez un keygen, ne le nommez pas "keygen.exe" où il n'acceptera pas vos clés.
Voyons maintenant ce qui se passe dans la seconde procédure.
Avant d'entrer, vous pouvez voir votre ID Produit dans EAX.

1

F7.
On arrive sur une routine de liste noire d'ID Produits

1

Les ID Produits en liste noire sont stockés dans «mbamcore.dll», vous sauterez dessus lorsque vous atteindrez «JMP EAX»
Office Jesus de la team iNFECTiON a rédigé un court article sur la recherche d'ID produit dans la liste noire, alors passons cette partie. Si vous voulez aller plus en profondeur dans la liste noire, allez jeter un oeil à son papier.
En continuant, nous atteignons enfin la partie calcul du sérial.

1

Voici l'appel du début de la procédure MD5 (qui prend simplement notre ID produit et va le hacher en MD5):

1

Après nous entrerons dans une boucle:

1

Le MOV EAX 1 avant la boucle initialise le nombre de boucles.
Il y a total de 16 boucles: MOV ECX 10 (16 en hexadécimal)
Ensuite il y a une comparaison entre EAX (le compteur) et ECX (le nombre maximum de boucles)
En dessous JG (Jump if Greater) décidera si nous continuons la boucle ou si c'est terminé. (16 boucles atteintes)
La fin du loop se situe en 004775C2, à chaque bouclage, notre hash MD5 est décomposé:

MOV EDX, DWORD Prend le hash MD5
IMUL EAX EAX 2: eax contiendra le nombre de boucles que nous avons fait, puis multiplie eax par 2
MOV ECX,2: Le nombre de caractères saisis (toujours deux)
SUB EAX, 1 est la pour déterminer où nous allons commencer à saisir nos deux caractères.
1x2 = 2, 2-1 = 1 donc nous commençons à saisir à partir du 1er caractère (on et dans la première boucle)
Et enfin, CALL EBX appellera l'API pour récupérer nos deux caractères (rtcMidCharBstr)

1

Après avoir récupéré nos deux caractères, il appellera StrMove et StrCat pour créer la chaîne «&H2e»

1

Après il effectue un HexToInt dans une procédure, on obtiendra 2E dans EAX, qui sera stocké plus tard dans EDI. Il effectue un 'AND' avec 2E (dans EDI) et 8000001F (en hard)

1

On obtient "0E" dans EDI
Continuons avec F8 (step over), il ajoutera +1 dans EDI (ADD EDI, 1)
EDI = "0F"
Ensuite, on passe sur la chaîne: 0123456789ABCDEFGHJKLMNPQRTUVWXY
Et appellera EBX pour récupérer le caractère qui est en position 15 dans cette chaîne (0F = 15 en hexadécimal)
Le caractère saisi sera donc: "E"
Le caractère saisi et pointé dans EAX, qui est visible dans le dump hexadécimal

1

À la fin il incrémente eax de +1 (boucle terminée), puis il prend le saut de fin (JMP) et réessaye de faire une boucle.
Quand tout est fait (16 boucles effectuées), il prendra le JG (Jump if Greater) dont nous avons parlé au début après l'appel de la routine de hachage MD5.
Cela nous mènera ici, ou l'on peut observer un sérial

1

Ce sont juste tous nos caractères créés par le calcul.
1AB23: 2e69ae201966977628d24d08fceb5b5f, c'est a dire en décomposé:

2e 69 ae 20 19 66 97 76 28 d2 4d 08 fc eb 5b 5f
E 9 E 0 R 6 P N 8 J D 8 V B U Y

Sur cette capture d'écran, la chaîne obtenue «E9E0R6PN8JD8VBUY» est passée en minuscules avec l'api rtcLowerCaseBstr.
Ensuite, notre faux sérial (1337-1337-1337-1337) apparaît et tous les tirets disparaissent via l'api rtcReplace (rappelez-vous le PUSH 00414C10) notre faux sérial deviendra «1337133713371337»
Ensuite, l'API rtcLowerCaseBstr est à nouveau appelée, mais cette fois pour notre faux sérial.
À la fin, notre faux sérial et la chaîne calculée sont comparés à vbaStrCmp, puis on saute sur la messagebox 'mauvais sérial' car les deux chaines ne sont pas identiques

1

Nous sommes, arrivé à la fin de cet algorithme, qui n'est pas vraiment compliqué au final.

IV: Faire un keygen:


Maintenant, il n'y a plus qu'à. Voici donc ma solution en assembleur.

kg.asm:

.386
.model flat, stdcall
option casemap :none

include keygen.inc
include md5.asm

.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke DialogBoxParam, hInstance, IDD_MAIN, 0, offset DlgProc, 0
invoke ExitProcess, eax
invoke InitCommonControls

DlgProc proc uses esi edi hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
mov eax,uMsg

.if eax == WM_INITDIALOG
invoke LoadIcon,hInstance,200
invoke SendMessage, hWnd, WM_SETICON, 1, eax
mov Rndm,'XYL'
invoke GetTickCount
add Rndm,eax
.elseif eax == WM_LBUTTONDOWN
invoke SendMessage,hWnd,WM_NCLBUTTONDOWN,HTCAPTION,NULL
.elseif eax == WM_COMMAND
mov eax,wParam
.if eax == IDB_EXIT
invoke SendMessage, hWnd, WM_CLOSE, 0, 0
.elseif eax == IDB_GENERATE
mov eax,Rndm
mov esi,offset Base10
mov edi,offset ID
mov ecx,10
xor edx,edx
idiv ecx
mov al,byte ptr [esi+edx]
stosb
invoke GetTickCount
add Rndm,eax
mov eax,Rndm
mov esi,offset Base26
mov ecx,26
xor edx,edx
idiv ecx
mov al,byte ptr [esi+edx]
stosb
invoke GetTickCount
add Rndm,eax
mov eax,Rndm
mov esi,offset Base26
mov ecx,26
xor edx,edx
idiv ecx
mov al,byte ptr [esi+edx]
stosb
invoke GetTickCount
add Rndm,eax
mov eax,Rndm
mov esi,offset Base10
mov ecx,10
xor edx,edx
idiv ecx
mov al,byte ptr [esi+edx]
stosb
invoke GetTickCount
add Rndm,eax
mov eax,Rndm
mov esi,offset Base10
mov ecx,10
xor edx,edx
idiv ecx
mov al,byte ptr [esi+edx]
stosb
invoke GetTickCount
add Rndm,eax
invoke MD5Init
invoke MD5Update,addr ID,5
invoke MD5Final
mov esi,offset MD5Digest
mov edi,offset Serial
mov ecx,4
xor eax,eax
.repeat
lodsb
and eax,8000001Fh
mov al,byte ptr [eax+Base32]
stosb
dec ecx
.until ecx == 0
invoke lstrcat,addr Serial,addr Tab
mov esi,offset MD5Digest+4
mov edi,offset Serial+4+1
mov ecx,4
xor eax,eax
.repeat
lodsb
and eax,8000001Fh
mov al,byte ptr [eax+Base32]
stosb
dec ecx
.until ecx == 0
invoke lstrcat,addr Serial,addr Tab
mov esi,offset MD5Digest+4+4
mov edi,offset Serial+4+4+1+1
mov ecx,4
xor eax,eax
.repeat
lodsb
and eax,8000001Fh
mov al,byte ptr [eax+Base32]
stosb
dec ecx
.until ecx == 0
invoke lstrcat,addr Serial,addr Tab
mov esi,offset MD5Digest+4+4+4
mov edi,offset Serial+4+4+4+1+1+1
mov ecx,4
xor eax,eax
.repeat
lodsb
and eax,8000001Fh
mov al,byte ptr [eax+Base32]
stosb
dec ecx
.until ecx == 0
invoke SetDlgItemText,hWnd,IDC_NAME,addr ID
invoke SetDlgItemText,hWnd,IDC_SERIAL,addr Serial
invoke RtlZeroMemory,addr ID,sizeof ID
invoke RtlZeroMemory,addr Serial,sizeof Serial
.endif
.elseif eax == WM_CLOSE
invoke EndDialog, hWnd, 0
.endif
xor eax,eax
ret
DlgProc endp
end start

Keygen.inc:

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\comctl32.inc
include \masm32\include\shlwapi.inc
include \masm32\include\winmm.inc
include \masm32\macros\macros.asm

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comctl32.lib
includelib \masm32\lib\shlwapi.lib
includelib \masm32\lib\winmm.lib

DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD

.code
HexToChar Proc HexValue:DWORD,CharValue:DWORD,HexLength:DWORD
mov esi,[ebp+8]
mov edi,[ebp+0Ch]
mov ecx,[ebp+10h]
@HexToChar:
lodsb
mov ah, al
and ah, 0fh
shr al, 4
add al, '0'
add ah, '0'
.if al > '9'
add al, 'A'-'9'-1
.endif
.if ah > '9'
add ah, 'A'-'9'-1
.endif
stosw
loopd @HexToChar
Ret
HexToChar endp

.const
IDD_MAIN equ 1000
IDC_NAME equ 1012
IDC_SERIAL equ 1013
IDB_GENERATE equ 1016
IDB_EXIT equ 1017

.data
Base32 db "0123456789ABCDEFGHJKLMNPQRTUVWXY",0
Base10 db "0123456789",0
Base26 db "ABCDEFGHIJKLMNOPQRSTUVWXYZ",0
Tab db "-",0
Rndm dd 0,0

.data?
hInstance dd ?
pData dd ?
SizeRes dd ?
hResource dd ?
ID db 10h dup(?)
Serial db 20h dup(?)

md5.asm:

.data?
MD5HashBuf db 64 dup(?)
MD5Digest dd 4 dup(?)
MD5Len dd ?
MD5Index dd ?

.code
MD5FF macro dwA, dwB, dwC, dwD, locX, rolS, constAC
mov edi,dwC
xor edi,dwD
and edi,dwB
xor edi,dwD
add dwA,[locX]
lea dwA,[edi+dwA+constAC]
rol dwA,rolS
add dwA,dwB
endm

MD5GG macro dwA, dwB, dwC, dwD, locX, rolS, constAC
mov edi,dwC
xor edi,dwB
and edi,dwD
xor edi,dwC
add dwA,[locX]
lea dwA,[edi+dwA+constAC]
rol dwA,rolS
add dwA,dwB
endm

MD5HH macro dwA, dwB, dwC, dwD, locX, rolS, constAC
mov edi,dwC
xor edi,dwD
xor edi,dwB
add dwA,[locX]
lea dwA,[dwA+edi+constAC]
rol dwA,rolS
add dwA,dwB
endm

MD5II macro dwA, dwB, dwC, dwD, locX, rolS, constAC
mov edi,dwD
xor edi,-1
or edi,dwB
xor edi,dwC
add dwA,[locX]
lea dwA,[edi+dwA+constAC]
rol dwA,rolS
add dwA,dwB
endm

align dword
MD5Transform proc
pushad
mov esi,offset MD5Digest
mov edi,offset MD5HashBuf
mov eax,[esi+0*4]
mov ebx,[esi+1*4]
mov ecx,[esi+2*4]
mov ebp,edi
mov edx,[esi+3*4]
;==============================================================
MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 0*4], 7, 0D76AA478H
MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 1*4], 12, 0E8C7B756H
MD5FF ecx, edx, eax, ebx, dword ptr [ebp+ 2*4], 17, 0242070DBH
MD5FF ebx, ecx, edx, eax, dword ptr [ebp+ 3*4], 22, 0C1BDCEEEH
MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 4*4], 7, 0F57C0FAFH
MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 5*4], 12, 04787C62AH
MD5FF ecx, edx, eax, ebx, dword ptr [ebp+ 6*4], 17, 0A8304613H
MD5FF ebx, ecx, edx, eax, dword ptr [ebp+ 7*4], 22, 0FD469501H
MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 8*4], 7, 0698098D8H
MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 9*4], 12, 08B44F7AFH
MD5FF ecx, edx, eax, ebx, dword ptr [ebp+10*4], 17, 0FFFF5BB1H
MD5FF ebx, ecx, edx, eax, dword ptr [ebp+11*4], 22, 0895CD7BEH
MD5FF eax, ebx, ecx, edx, dword ptr [ebp+12*4], 7, 06B901122H
MD5FF edx, eax, ebx, ecx, dword ptr [ebp+13*4], 12, 0FD987193H
MD5FF ecx, edx, eax, ebx, dword ptr [ebp+14*4], 17, 0A679438EH
MD5FF ebx, ecx, edx, eax, dword ptr [ebp+15*4], 22, 049B40821H
;==============================================================
MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 1*4], 5, 0F61E2562H
MD5GG edx, eax, ebx, ecx, dword ptr [ebp+ 6*4], 9, 0C040B340H
MD5GG ecx, edx, eax, ebx, dword ptr [ebp+11*4], 14, 0265E5A51H
MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 0*4], 20, 0E9B6C7AAH
MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 5*4], 5, 0D62F105DH
MD5GG edx, eax, ebx, ecx, dword ptr [ebp+10*4], 9, 002441453H
MD5GG ecx, edx, eax, ebx, dword ptr [ebp+15*4], 14, 0D8A1E681H
MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 4*4], 20, 0E7D3FBC8H
MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 9*4], 5, 021E1CDE6H
MD5GG edx, eax, ebx, ecx, dword ptr [ebp+14*4], 9, 0C33707D6H
MD5GG ecx, edx, eax, ebx, dword ptr [ebp+ 3*4], 14, 0F4D50D87H
MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 8*4], 20, 0455A14EDH
MD5GG eax, ebx, ecx, edx, dword ptr [ebp+13*4], 5, 0A9E3E905H
MD5GG edx, eax, ebx, ecx, dword ptr [ebp+ 2*4], 9, 0FCEFA3F8H
MD5GG ecx, edx, eax, ebx, dword ptr [ebp+ 7*4], 14, 0676F02D9H
MD5GG ebx, ecx, edx, eax, dword ptr [ebp+12*4], 20, 08D2A4C8AH
;==============================================================
MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 5*4], 4, 0FFFA3942H
MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 8*4], 11, 08771F681H
MD5HH ecx, edx, eax, ebx, dword ptr [ebp+11*4], 16, 06D9D6122H
MD5HH ebx, ecx, edx, eax, dword ptr [ebp+14*4], 23, 0FDE5380CH
MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 1*4], 4, 0A4BEEA44H
MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 4*4], 11, 04BDECFA9H
MD5HH ecx, edx, eax, ebx, dword ptr [ebp+ 7*4], 16, 0F6BB4B60H
MD5HH ebx, ecx, edx, eax, dword ptr [ebp+10*4], 23, 0BEBFBC70H
MD5HH eax, ebx, ecx, edx, dword ptr [ebp+13*4], 4, 0289B7EC6H
MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 0*4], 11, 0EAA127FAH
MD5HH ecx, edx, eax, ebx, dword ptr [ebp+ 3*4], 16, 0D4EF3085H
MD5HH ebx, ecx, edx, eax, dword ptr [ebp+ 6*4], 23, 004881D05H
MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 9*4], 4, 0D9D4D039H
MD5HH edx, eax, ebx, ecx, dword ptr [ebp+12*4], 11, 0E6DB99E5H
MD5HH ecx, edx, eax, ebx, dword ptr [ebp+15*4], 16, 01FA27CF8H
MD5HH ebx, ecx, edx, eax, dword ptr [ebp+ 2*4], 23, 0C4AC5665H
;==============================================================
MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 0*4], 6, 0F4292244H
MD5II edx, eax, ebx, ecx, dword ptr [ebp+ 7*4], 10, 0432AFF97H
MD5II ecx, edx, eax, ebx, dword ptr [ebp+14*4], 15, 0AB9423A7H
MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 5*4], 21, 0FC93A039H
MD5II eax, ebx, ecx, edx, dword ptr [ebp+12*4], 6, 0655B59C3H
MD5II edx, eax, ebx, ecx, dword ptr [ebp+ 3*4], 10, 08F0CCC92H
MD5II ecx, edx, eax, ebx, dword ptr [ebp+10*4], 15, 0FFEFF47DH
MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 1*4], 21, 085845DD1H
MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 8*4], 6, 06FA87E4FH
MD5II edx, eax, ebx, ecx, dword ptr [ebp+15*4], 10, 0FE2CE6E0H
MD5II ecx, edx, eax, ebx, dword ptr [ebp+ 6*4], 15, 0A3014314H
MD5II ebx, ecx, edx, eax, dword ptr [ebp+13*4], 21, 04E0811A1H
MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 4*4], 6, 0F7537E82H
MD5II edx, eax, ebx, ecx, dword ptr [ebp+11*4], 10, 0BD3AF235H
MD5II ecx, edx, eax, ebx, dword ptr [ebp+ 2*4], 15, 02AD7D2BBH
MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 9*4], 21, 0EB86D391H
;==============================================================
add [esi+0*4],eax ; update digest
add [esi+1*4],ebx
add [esi+2*4],ecx
add [esi+3*4],edx
popad
retn
MD5Transform endp

MD5BURN macro
xor eax,eax
mov MD5Index,eax
mov edi,Offset MD5HashBuf
mov ecx,(sizeof MD5HashBuf)/4
rep stosd
endm

align dword
MD5Init proc uses edi
xor eax, eax
mov MD5Len,eax
MD5BURN
mov eax,offset MD5Digest
mov dword ptr [eax+0*4],067452301h
mov dword ptr [eax+1*4],0EFCDAB89h
mov dword ptr [eax+2*4],098BADCFEh
mov dword ptr [eax+3*4],010325476h
ret
MD5Init endp

align dword
MD5Update proc uses esi edi ebx lpBuffer:dword, dwBufLen:dword
mov ebx,dwBufLen
mov esi,lpBuffer
add MD5Len,ebx
.while ebx
mov eax,MD5Index
mov ecx,64
sub ecx,eax
lea edi,[MD5HashBuf+eax]
.if ecx <= ebx
sub ebx,ecx
rep movsb
call MD5Transform
MD5BURN
.else
mov ecx,ebx
rep movsb
add MD5Index,ebx
.break
.endif
.endw
ret
MD5Update endp

align dword
MD5Final proc uses esi edi
mov ecx, MD5Index
mov byte ptr [MD5HashBuf+ecx],80h
.if ecx >= 56
call MD5Transform
MD5BURN
.endif
mov eax,MD5Len
xor edx,edx
shld edx,eax,3
shl eax,3
mov dword ptr [MD5HashBuf+56],eax
mov dword ptr [MD5HashBuf+60],edx
call MD5Transform
mov eax,offset MD5Digest
ret
MD5Final endp

whatever.rc:

;This Resource Script was generated by WinAsm Studio.

#define IDD_MAIN 1000
#define IDB_EXIT 1017
#define IDC_NAME 1012
#define IDB_GENERATE 1016
#define IDC_LIC 1013
#define IDC_STATIC1009 1009
#define IDC_STATIC1010 1010

IDD_MAIN DIALOGEX 10,10,171,57
CAPTION "MBAM v1.50 kg"
FONT 8,"Tahoma"
STYLE 0x90c80804
EXSTYLE 0x00000000
BEGIN
CONTROL "ID:",IDC_STATIC1009,"Static",0x50000000,7,6,14,10,0x00000000
CONTROL "Serial:",IDC_STATIC1010,"Static",0x50000000,7,22,23,10,0x00000000
CONTROL "",IDC_NAME,"Edit",0x50010080,33,3,127,13,0x00020000
CONTROL "",IDC_LIC,"Edit",0x50010000,33,18,127,13,0x00020000
CONTROL "Generate",IDB_GENERATE,"Button",0x50010001,7,37,47,13,0x00000000
CONTROL "Exit",IDB_EXIT,"Button",0x50010000,123,37,37,13,0x00000000
END

make.bat:

@echo off
\masm32\bin\rc /v whatever.rc
\masm32\bin\cvtres.exe /machine:ix86 whatever.res
\masm32\bin\ml.exe /c /coff kg.asm
\masm32\bin\link.exe /SUBSYSTEM:WINDOWS /OUT:Keygen.exe kg.obj whatever.res
del whatever.res
del whatever.obj
del kg.obj
pause

Une fois compilé, ça ressemble à ça:

1

Et ça pèse que 5,00 Ko!

V: Patching:


Maintenant qu'on a créé un keygen fonctionnel, patché, l'application n'a pas vraiment d'importance, on va juste appeler cela un bonus :)
Donc on sait que AX a besoin d'être à 1 pour ne pas atterrir sur la MessageBox mauvais sérial.
Remplaçons donc au début de notre routine de sérial check:

PUSH EBP
MOV EBP

Par:

MOV AX,1
RETN

1


On sauvegarde les modifications, et voilà, mais on a pas totalement fini.
Une fois enregistré, le programme vous créera une clé de registre de votre nom et numéro de série.
Histoire de faire plus propre on va donc ajouter une clé registre avec ce que l'on souhaite voir afficher pour notre licence pirate.

patch.reg:

REGEDIT4

[HKEY_LOCAL_MACHINE\SOFTWARE\Malwarebytes' Anti-Malware]
"ID"="Xylitol"
"Key"="Patched!"

Voila, maintenant c'est fini :)


VI: Conclusion:


Au final cette application est un bon exercice pour s'initier au cracking d'application développée en VB6. On a pu voir des apis VBA, les apis de msvbvm60, comment ça fonctionnait.. Mais aussi de la gestion de sérial, leur algorithme MD5+Custom, une routine de check pour vérifier que l'utilisateur n'est pas un pirate, ainsi qu'une blacklist.
Tous les développeurs n'en font pas autant au niveau de leur système de licence.

Kudos aussi aux développeurs du soft qui ont ajouté une détection "Dont.Steal.Our.Software" sur la version scène de mon keygen.

1




Xylitol, 31/12/2010




Copyright (C)- xtx Team (2021)

XHTML valide 1.1 CSS Valide !