Вы находитесь на странице: 1из 5

Cruehead CrackMe v1.0/v2.0/v3.0 - Tutorial Cruehead CrackMe v1.0/v2.0 & v3.0 - CrackMe Archive (180k).

I always recommend that you try your hand at these CrackMe's, this example by Cr uehead will introduce the simplest concept of encryption, specifically the logic operation XOR. So start up the CrackMe and insert some details into the dialog boxes and >bpx Hmemcpy or GetDlgItemTextA, just start stepping with F10 or use F 12 to reach the following code (you'll go through User & Kernel32): :00401223 :00401226 :00401228 :0040122D :00401232 :00401233 :00401238 :0040123D :00401240 :00401241 :00401243 CMP EAX,00000000 JE 004011E6 <-- No jump. PUSH 0040218E <-- Name entered. CALL 0040137E <-- Function to trace. PUSH EAX <-- Save XOR result of name on stack. PUSH 0040217E <-- Serial # entered. CALL 004013D8 <-- Function to trace. ADD ESP,04 <-- Stack Tidy. POP EAX CMP EAX,EBX <-- Compare. JZ 0040124C <-- Jump_good_code.

So its very easy to see how this scheme can be beaten, however the purpose of a CrackMe is to fully investigate how the protection works. So lets have a trace o f 0040137E & 004013D8. :0040137E :00401382 :00401383 :00401385 :00401387 :00401389 :0040138B :0040138D :0040138F :00401391 :00401392 :00401394 :00401399 :0040139A MOV ESI,[ESP+04] <-- Name entered. PUSH ESI <-- Stack it. MOV AL,[ESI] <-- AL = 1st letter of name. TEST AL,AL <-- Was it 0. JZ 0040139C <-- Jump_if_it_was. CMP AL,41 <-- Compare it with 41 or 'A'. JB 004013AC <-- Jump_below_'A'. CMP AL,5A <-- Compare it with 5A or 'Z'. JNB 00401394 <-- Jump_if_not_below_'Z'. INC ESI <-- Name counter. JMP 00401383 <-- Repeat test. CALL 004013D2 <-- Jump here if below 'Z'. INC ESI <-- Name counter. JMP 00401383 <-- Repeat test.

So this portion of code will check whether all of the names characters were inde ed letters between A and Z, if the letter is lower case the CALL at 00401394 is executed, that consists of the classic SUB AL,20 i.e. uppercasing routine. So at the end our name is completely uppercased, we continue (still inside CALL 00401 37E) with a CALL to function 004013C2. :004013C2 :004013C4 :004013C6 :004013C8 :004013CA :004013CC :004013CE :004013CF XOR EDI,EDI <-- EDI=0. XOR EBX,EBX <-- EBX=0. MOV BL, BYTE PTR [ESI] <-- Pointer to name. TEST BL,BL <-- End_of_name_check. JZ 004013D1 <-- Jump_loop_finished. ADD EDI,EBX <-- Add value to EDI which was zero. INC ESI <-- Counter. JMP 004013C6 <-- Loop_again.

So this function will sum up all of the letters in your name and place the resul t in EDI. In my case: CRACKZ = 43 + 52 + 41 + 43 + 4B + 5A = 19Eh.

At the end, we have our critical operation: :004013A2 XOR EDI,00005678 <-- XOR total of name characters. :004013A8 MOV EAX,EDI <-- Move it to EAX. In my case the result of this XOR operation is 57E6h, you should then see that t his result is saved away on the stack. Now lets trace 004013D8: :004013D8 :004013DA :004013DC :004013DE :004013E2 :004013E4 :004013E6 :004013E8 :004013EA :004013ED :004013F0 :004013F2 :004013F3 :004013F5 :004013FB XOR EAX,EAX <-- EAX=0. XOR EDI,EDI <-- EDI=0. XOR EBX,EBX <-- EBX=0. MOV ESI,[ESP+04] <-- Serial # entered. MOV AL,0A <-- AL=10. MOV BL, BYTE PTR [ESI] <-- Pointer to ESI. TEST BL,BL <-- Check. JZ 004013F5 <-- Finished_loop. SUB BL,30 IMUL EDI,EAX ADD EDI,EBX <-- EDI used for result storage (again). INC ESI <-- Name counter. JMP 004013E2 <-- Repeat. XOR EDI,00001234 <-- Critical XOR. MOV EBX,EDI <-- Place it in EBX and return for the compare.

Again we have a loop operation, this time upon our entered serial #, actually al l this does is convert our decimal number into HEX, so with 123456 I get the res ult 1e240h which is then XOR-ed with 00001234 to give 1f074h. So for a correct s erial # this result must actually equal 57e6h (the result obtained from the name ). So lets work out my good code: 57E6h XOR 1234h = 45D2h = 17874 XOR - Notes Just a side note for those of you unfamiliar with logic operations, below I've g iven you the XOR gate truth table, where a and b are inputs and x is the result obtained by XORing them: a 0 0 1 1 b 0 1 0 1 x 0 1 1 0

So let me show you how I calculated my result: 5 7 E 6 = (binary) 0101 0111 1110 0110 1 2 3 4 = (binary) 0001 0010 0011 0100 > Result of XOR = 0100 0101 1101 0010 = 45D2h = 17874 decimal. Cruehead CrackMe v2.0 - Tutorial Another Cruehead CrackMe (this time v2.0), which yet again demonstrates the use of the XOR logic operation. Launch the CrackMe and enter a password, I used Crac kZ, as with CrackMe v1.0 you should easily trace to the following code, just >bp x GetDlgItemTextA or Hmemcpy and step (the pattern is almost identical to CrackM e v1.0):

:00401228 :0040122D :00401232 :00401237 :0040123C :0040123F :00401241

PUSH 0040217E <-- Password entered pushed to stack. CALL 00401365 <-- Trace this. PUSH 0040217E <-- Result of XOR-ing password entered. CALL 004013B8 <-- Trace this. (Compare XOR results). ADD ESP,04 <-- Tidy stack. TEST CL,CL <-- CX-low test for 0. JZ 0040124A <-- Jump_good_password.

Tracing the first part of 00401365 will take you through the same uppercasing ro utine which we saw in CrackMe v1.0. At address 00401390 each character in our en tered password will be XOR-ed with the string Messing_in_bytes, this should imme diately tell you that our good password must be the same length as the XOR key i .e. 16. The result of Xor-ing our entered password is then placed at address 004 0217E before being compared with the correct XOR result in function 004013B8. So you should be able to read from the data window the desired XOR result which we should get when we XOR the correct password with Messing_in_bytes. Therefore you should deduce that to work out the correct password we need to XOR Messing_i n_bytes with the desired result which we read from EDI in function call 004013B8 . I've shown the method below. Messing_in_bytes = 4D 65 73 73 69 6E 67 5F 69 6E 5F 62 79 74 65 73 Correct password XOR result = 1F 2C 37 36 3B 3D 28 19 3D 26 1A 31 2D 3B 37 3E So the first letter of the good password would be: 4D XOR 1F 0100 1101 <-- 4D 0001 1111 <-- 1F 0101 0010 <-- 52 = R If you continue to XOR the remaining 15 characters you'll find that the good pas sword is RIDERSOFTHESTORM and as we know the program will uppercase the password before XOR-ing, it is not case-sensitive. Cruehead CrackMe v3.0 - Tutorial Welcome to what would seem to be the final Cruehead CrackMe. This CrackMe presen ts a different challenge to the previous versions in that our task is to create a working keyfile for the program. The first thing you should find out is that t he name of our missing file is crackme3.key, use a file monitoring tool or just disassemble if you want to verify this. So lets create an empty crackme3.key file. Now we need to use SoftICE to interce pt the reading of the key file, you can use ReadFile however I strongly recommen d CreateFileA which is used unsurprisingly for creating and opening files (check the disassembly also). So lets >bpx CreateFileA and launch the CrackMe. You sho uld break on this code: :00401032 :00401035 :00401043 :00401048 :0040104D :00401052 . :00401054 :00401059 :0040105A CMP EAX,-01 <-- If EAX is returned -1 then the file doesn't exist. JNZ 00401043 <-- Jump_crackme3.key_exists. MOV [004020F5],EAX MOV EAX,00000012 <-- Number of bytes to read from file. MOV EBX,00402008 PUSH 00 <-- Now the program is pushing all the parameters for ReadFile PUSH 004021A0 PUSH EAX PUSH EBX

:0040105B :00401061 :00401066 :0040106D

PUSH DWORD PTR [004020F5] CALL KERNEL32!ReadFile <-- API call to read file. CMP DWORD PTR [004021A0],12 <-- Compare for 12h (18 decimal). JNZ 00401037 <-- Jump_crackme3.key_was_wrong_length.

Now lets modify our key file so that it is 18 bytes in length, it will now pass the 2 validity checks above. After the length check you should proceed to trace CALL 00401311: :00401315 :00401319 :0040131B :0040131D :0040131F :00401321 :00401322 :00401324 :0040132A :0040132C :0040132E :00401330 :00401333 :00401335 MOV ESI,[ESP+04] <-- ESI holds crackme3.key contents. MOV BL,41 <-- BX-low moved to 41h. MOV AL,[ESI] <-- AX-low moved to byte from crackme3.key. XOR AL,BL <-- XOR. MOV [ESI], AL <-- Save XOR result. INC ESI <-- Increment ESI to next byte. INC BL <-- Increment BL from 41h to 42h for next byte. ADD DWORD PTR [004020F9], EAX <-- checksum. CMP AL,00 <-- Finished decrypting. JZ 00401335 <-- Jump_finished_decrypt. INC CL <-- Increment CX-low. CMP BL,4F <-- Is BX-low 4F. (i.e. 4F-41 = 14). JNZ 0040131B <-- Loop_again_if_not. MOV [00402149],ECX

After this simple decryption you'll return from the function at this code: :00401079 XOR DWORD PTR [004020F9],12345678 <-- Sum of decrypted bytes XORed wit h 12345678. :0040108B CALL 0040133C <-- Last 4 bytes of keyfile. :00401093 CMP EAX, [004020F9] <-- Compare. :00401099 SETE AL <-- Set AX-low to 1 if the compare was good. :0040109C PUSH EAX :0040109D TEST AL,AL <-- Test AX=low for 0. :0040109F JZ 00401037 <-- No_jump_and_we've_cracked_it. Now that we have examined the code lets start to construct our valid keyfile, in this case for the name CrackZ. We know that the first 14 bytes determine the na me and that it works on a simple character by character XOR starting with 41h. S o for CrackZ our keyfile must look like the following: CrackZ = 43 72 65 63 6B 5A XOR with: 41 42 43 44 45 46 Result: 02 30 22 27 2E 1C <-- Use SoftICE if you want to quickly work out this r esult. Example 72h XOR 42h = 30h 0111 0010 = 72h (114 decimal) 0100 0010 = 42h (66 decimal) ----------0011 0000 = 30h (48 decimal) We now need to terminate our name by ensuring that the next character produces a n XOR result of zero, so our next value must be 47 i.e. XOR 47,47=0, the remaini ng 7 bytes can be left blank as they will not be checked (If you want to do this easily I recommend using Hiew in HEX mode). The last 4 digits however must be t he sum of the decrypted values XOR-ed with 12345678. So the sum of our decrypt = 23E (Tip: Obtain this value from DS:004020F9 from th

e SoftICE register window). Now we need to XOR this result 23E with 12345678. 12345678 xxxxx23E ---------12345446 So the last 4 bytes of the keyfile for me are 46 54 34 12. CrackMe 3.0 Registered Picture Back to CrackMe's 1998,1999, 2000 CrackZ. June 1998.