Crackme V3.0 de Cruehead
By Christal
Histoire d'un crackme insoluble?
"Cracked by: Now " "CrackMe v3.0 " "CRACKME3.KEY" "DLG_ABOUT" "Good work cracker!" "MENU" "No need to disasm the code!" Le crackme semblait attendre une KeyFile (CRACKME3.KEY) dans laquelle devrait se trouver normalement un nom qui serait ensuite utilisé pour être affiché dans la boite de message "Cracked by: ". //******************** Program Entry Point ******** :00401000 6A00 push 00000000 * Reference To: KERNEL32.GetModuleHandleA, Ord:0000h :00401002 Call 00401484 > call GetModuleHandleA :00401007 mov dword ptr [004020E9], eax > récupère l'ImageBase :0040100C mov dword ptr [004020F9], 00 > initialise @ F9 = 0 :00401016 push 00000000 > hTemplateFile :00401018 push 00000080 > dwFlagsAndAttributes :0040101D push 00000003 > dwCreationDistribution :0040101F push 00000000 > lpSecurityAttributes :00401021 push 00000003 > dwShareMode :00401023 push C0000000 > dwDesiredAccess * Possible StringData Ref from Data Obj ->"CRACKME3.KEY" :00401028 push 004020D7 > lpFileName * Reference To: KERNEL32.CreateFileA, Ord:0000h :0040102D Call 004014A8 > call CreateFileA :00401032 cmp eax, FFFFFFFF > fichier trouvé? :00401035 jne 00401043 > alors saute La fonction CreateFile ouvre un objet (ici CRACKME3.KEY) et retourne le handle qui permettra d'accéder à la KeyFile (l'objet). HANDLE CreateFile( LPCTSTR lpFileName, // pointe vers le nom du fichier (CRACKME3.KEY) DWORD dwDesiredAccess, // mode accès (read-write) DWORD dwShareMode, // share mode LPSECURITY_ATTRIBUTES lpSecurityAttributes,// pointe vers les attributs de fichier DWORD dwCreationDistribution,// how to create DWORD dwFlagsAndAttributes, // attributs de fichier HANDLE hTemplateFile // handle du fichier avec les attributs à copier ); Si le fichier est trouvé, la valeur retournée est un handle qui permettra l'ouverture du fichier spécifié, et EAX contiendra le nombre de lettres correspondant à la taille du nom du fichier. Dans le cas contraire EAX vaudra -1. :00401043 mov dword ptr [004020F5], eax > stock nb de lettres :00401048 mov eax, 00000012 > eax= 18d :0040104D mov ebx, 00402008 > initialise EBX= @ de stockage du texte :00401052 push 00000000 > pas de structure datas :00401054 push 004021A0 > @ de stockage du nb d'octets lus :00401059 push eax > 18 caractères à lire :0040105A push ebx > adresse du buffer pointé par EBX :0040105B push dword ptr [004020F5] > handle du fichier à lire * Reference To: KERNEL32.ReadFile, Ord:0000h :00401061 Call 00401496 > call ReadFile :00401066 cmp dword ptr [004021A0], 12 > comparaison si le nombre de > caractères contenu dans le > fichier est égal à 18d :0040106D jne 00401037 > sinon Goto Bad Boy La fonction ReadFile va lire le contenu du fichier concerné, à partir de la position indiquée par un pointeur. Après lecture, le pointeur contiendra le nombre de caractères qui restaient à lire dans le fichier. Ici, l'adresse d''EBX va pointer sur l'adresse dans laquelle se trouveront les caractères à lire dans le fichier CRACKME3.KEY. BOOL ReadFile( HANDLE hFile, // handle du fichier à lire LPVOID lpBuffer, // adresse du buffer qui recevra les datas DWORD nNumberOfBytesToRead, // nombre d'octets à lire LPDWORD lpNumberOfBytesRead,// adresse du nombre d'octets à lire LPOVERLAPPED lpOverlapped // adresse de la structure pour les datas ); :0040106F push 00402008 > pousse l'adresse du buffer :00401074 call 00401311 > manipulation :00401079 xor dword ptr [004020F9], 12345678 > opération logique :00401083 add esp, 00000004 > rétablie la pile :00401086 push 00402008 > pousse l'adresse du buffer :0040108B call 0040133C > charge les 4 derniers caractères :00401090 add esp, 00000004 > rétablie la pile :00401093 cmp eax, dword ptr [004020F9] > comparaison :00401099 sete al > si egalité alors AL = 1 :0040109C push eax > sauvegarde la valeur de EAX sur la pile :0040109D test al, al > test si AL = 1 :0040109F je 00401037 > sinon Bad Boy Voyons ce que nous avons dans le call manipulateur: :00401311 xor ecx, ecx > mise à zéro de ECX :00401313 xor eax, eax > et de EAX :00401315 mov esi, dword ptr [esp+04] > Charge le texte trouvé dans le fichier :00401319 mov bl, 41 > BL initialisé à 41 (lettre "A") :0040131B mov al, byte ptr [esi] > AL = une lettre du texte trouvé :0040131D xor al, bl > Xor AL avec BL :0040131F mov byte ptr [esi], al > remplace la lettre lue par celle XORée :00401321 inc esi > passe à la lettre suivante :00401322 inc bl > BL = "B", puis "C" etc... :00401324 add dword ptr [004020F9], eax > Ajoute le résultat du XOR dans @ F9 :0040132A cmp al, 00 > contrôle si différent de 00 :0040132C je 00401335 > auquel cas saute en Bad Boy :0040132E inc cl > incrémente CL :00401330 cmp bl, 4F > compare si BL = "N" :00401333 jne 0040131B > sinon boucle :00401335 mov dword ptr [00402149], ecx > place le nb de caractères XORé dans @ 149 :0040133B ret > fin Si par hasard le texte que vous avez entré dans le fichier CRACVKME3.KEY
est "ABCDEFGHIJKLMNOPQR", le A XOR A donnera 00, et vous serez éjecté en 0040132C. Par contre si aucune lettre XORée
par BL ne se trouve être identique, les 14 première lettres seront XORées par A à N.
Arrivé à la lettre N, le programme sortira de sa boucle (en 00401333). A chaque XOR, le résultat
est ajouté au résultat précédemment trouvé (en 00401324 et dans l'adresse [004020F9])
et finalement le nombre de caractères traités sera stocké dans [00402149]. Le principe est
donc le suivant: :0040133C mov esi, dword ptr [esp+04] > ESI pointe sur la chaine XORée :00401340 add esi, 0000000E > ESI pointe sur le 14ème caractère :00401343 mov eax, dword ptr [esi] > EAX charge les 4 derniers caractères :00401345 ret Le rôle de cette routine va être de pointer sur les 4 derniers caractères,
ceux qui n'avaient pas été touchés, et en charger la valeur ASCII dans EAX. Si par exemple
ces caractères étaient EFGH, EAX vaudrait 48674645. En entrant des caractères au clavier, peut être... |
Bonne Journée