. ..: Smart 5 by ajax - A tutorial by DEATH of Execution :.. . `------------------------------------------------------' Introduction ------------- I made this tutor because I didn't see any other tutorial considering this crackme in Eternal Bliss's site (crackmes.cjb.net or surf.to/crackmes) . I have cracked this crackme long time ago, so I'll just recrack it.. :) Greetings ---------- I'd like to greet Eternal for having such a wonderful crackme site ;) Tools ------ - Notice I will use Turbo Debugger, that's because I am hearing MP3's right now and I don't want Soft-ICE to stop'em ;) - Ajax Smart 5 ;) Start ------ Ok.. Load up the crackme in TD. First you see a jump.. Not interesting :) The jump brings us to an INT 3h which is the debugger's breakpoint interrupt.. We'll just ignore it.. Now the crackme prints the 'Enter password' string: mov dx, 103h ; that's the string to print mov ah, 9h ; PRINT STRING service int 21h ; do'em Now the crackme will ask for the password: mov dx, 131h ; Entered Password buffer mov ah, 0Ah ; GET STRING FROM KEYBOARD service int 21h ; get'em So.. in the memory view window, we GoTo ds:133h .. Why? String buffer structure is like this: Name Type Position -------------------------------------------------------- Maximum_Characters db 0 Character_Count db 1 Buffer db Maximum_Characters 2 Check out what's the Maximum_Characters.. It's 5 (+1 for Carriege Return). By the way, we see the buffer overwrites the code before the GET STRING code.. Now the crackme will move the buffer position to bx: mov bx, 131h Now.. A call.. We trace into it, what do we see? 32-bit Registers! No panic.. Just go to the Registers window, right mouse click on it, and choose 32-Bit Registers option (if it's not already turned on). Here's the procedure: mov eax, 0D12345h ; eax = 0D12345h (hardcoded) mov cx, 10h ; ecx = 64 times for loop loop1: xor ax, 2h ; eax gets xored by 2 inc ax ; eax++ cwde ; convert word to double word with eax loop loop1 ; till ecx = 0 dec eax ; eax-- ret ; return from call This just calculates another value for eax.. Seems that ajax wanted to confuse us thinking it's an important code instead of just putting a 'mov eax, 2354h'. Another call.. here's the procedure: mov cx, 0Ah ; ecx = 10 times for loop loop1: xor eax, ebx ; this xors eax (2354h) by ebx (131h) loop loop1 ; loop tha loop ret ; return from call Ok.. First, let me say that if you XOR a value twice by the same number, the value will be the same.. :) Since 10 is an even number, eax will stay 2354h.. Another routine to confuse us.. Another call, this time it's an important call, that calculates the checksum for the password: mov cx, 0Ah ; ecx = 10 times for loop loop1: xor eax, ebx ; xors eax by ebx (131h) shr eax, 1 ; eax gets divided by 2 loop loop1 ; loopah and eax, 2Ah ; eax (0E7h) ANDed with 2Ah sub eax, [bx] ; eax (22h) gets subtracted by double ; word of the first four bytes of ; the entered password buffer ; (which are the character_max, ; character count, and two ; first characters of password) sub eax, [bx + 1] ; eax gets subtracted by double ; word of the entered password buffer ; (which are the character count, and ; three first characters of password) sub eax, [bx + 2] ; eax gets subtracted by double ; word of the entered password buffer ; (which are the first four characters ; of the entered password) sub eax, [bx + 3] ; eax gets subtracted by double ; word of the entered password buffer ; (which are four characters of the ; entered password starting from the ; second character) sub eax, [bx + 4] ; eax gets subtracted by double ; word of the entered password buffer ; (which are three last characters of ; the entered password + carriege ; return byte (0Ah)) sub eax, [bx + 5] ; eax gets subtracted by double ; word of the entered password buffer ; (which are last two characters of the ; entered password + carriege return ; byte (0Ah) + hardcoded byte '!') rol eax, 1 ; eax gets rotated left by 1 inc eax ; eax++ ret ; return from call Phew.. Read it until you get it.. After the call, ax (lower word of eax) gets compared with an hardcoded value of 0B4E3h and if it's equal, then we have succeeded to crack it :) So how do we get a valid password? We have two options: 1> Reverse the checksum (might take a little brain-effort) 2> Brute (easier.. 5 characters + 16-bit checksum.. fast too) This time I have chosen the second option since I am having a little headache.. Brute forcer code ------------------ Ok.. here's my source of the bruteforcer, of course you could make it better and use it on other crackmes, but it's good for Smart 5.. It's good for us :) --cut here-- ; Solve to ajax's Smart 5 crackme ; (c)1999 by DEATH of Execution ; ; Brute force attack ; ------------------- ; This crackme needed only 5 printable characters and had a 16bit checksum ; value, so I realized it wouldn't take much long before I could crack it.. ; Phun, eh? ; ; This will crack for printable chars. ; .model tiny .386p .code org 100h start: lea ebx, passbuf mov byte ptr ch1, ' ' - 1 ch1loop: mov byte ptr ch2, ' ' - 1 mov byte ptr ch3, ' ' - 1 mov byte ptr ch4, ' ' - 1 mov byte ptr ch5, ' ' - 1 inc byte ptr ch1 cmp byte ptr ch1, '~' + 1 jae nofound ch2loop: mov al, '.' int 29h mov byte ptr ch3, ' ' - 1 mov byte ptr ch4, ' ' - 1 mov byte ptr ch5, ' ' - 1 inc byte ptr ch2 cmp byte ptr ch2, '~' + 1 jae ch1loop ch3loop: mov byte ptr ch4, ' ' - 1 mov byte ptr ch5, ' ' - 1 inc byte ptr ch3 cmp byte ptr ch3, '~' + 1 jae ch2loop ch4loop: mov byte ptr ch5, ' ' - 1 inc byte ptr ch4 cmp byte ptr ch4, '~' + 1 jae ch3loop ch5loop: inc byte ptr ch5 cmp byte ptr ch5, '~' + 1 jae ch4loop mov eax, 22h ; magic value sub eax, [ebx] sub eax, [ebx + 1] sub eax, [ebx + 2] sub eax, [ebx + 3] sub eax, [ebx + 4] sub eax, [ebx + 5] rol eax, 1 inc eax cmp ax, 0B4E3h ; checksum value jne ch5loop mov byte ptr endtext, 0Ah mov ah, 9 lea dx, ch1 int 21h mov byte ptr endtext, '!' jmp ch5loop nofound: int 20h passbuf db 06h ; Maximum chars db 05h ; entered chars ch1 db ? ch2 db ? ch3 db ? ch4 db ? ch5 db ? endtext db '!' ; hardcoded db 0Dh db '$' end start --stop cutting here-- I threw the output to file, and tried to 'fish' readable words of passwords.. I have found a good password: 'Sorry' .. Tried it, it worked.. Now go ahead and crack Smart 6.. Hope this tut was good :) - DEATH of Execution in 1999