----------------------------------------------- How to code a keygen for CDRCue Cuesheet editor ----------------------------------------------- Cracker: stealthFIGHTER Target: CDRCue Cuesheet editor v1.3 Tools: OllyDbg IDA VC++ Where: http://www.dcsoft.com Protection: MD5 -------------------------------------------------- Sorry for my English, it's not my mother language. -------------------------------------------------- ---------------- ---[ Step 1 ]--- ---------------- ======================================================================= As this target is written in VC++ (as the previous one) we will use the same technique at the beginning. ======================================================================= Load your target in OllyDbg. Use GetWindowTextLength api to break on name/serial check. Trace a bit, pass some RETs and first useful code is here: ======================================================================= :004150C5 push offset aKbd_hxidoxyoRo ;"KBD.HXIDOxyo`ro|" ======================================================================= Some funny string is pushed here (looks like encrypted str.). Continue tracing: ======================================================================= :004150E0 lea ecx, [ebp+var_454] ;ecx = our name :004150E6 call KeygenProc ;important function ======================================================================= Trace into this procedure/function and inside you can see there is only one! - call sub_0_4169DE. Before this call there are five arguments pushed into memory (you can see in OllyDbg in Strack wnd): ======================================================================= Arg1 = 006BE07C ASCII "stealthFIGHTER" ;our name Arg2 = 0000000E ;length of our name Arg3 = 006BE17C ASCII "KAB+DSC=GoodTeam" ;decrypted string :-) Arg4 = 00000010 ;length of decrypted string Arg5 = 006BE288 ;buffer ======================================================================= Ok. Trace into call sub_0_4169DE: ======================================================================= :004169E7 cmp [ebp+szName], 0 ;compare our name with zero :004169EB jz short loc_0_4169F9 ;end if equal :004169ED cmp dword ptr [ebp+aKAB_DSC_GoodTeam], 0 ;cmp. const. ;string with z. :004169F1 jz short loc_0_4169F9 ;end if equal :004169F3 cmp [ebp+arg_10], 0 :004169F7 jnz short loc_0_4169FE ;we jump from ;here ======================================================================= Cool. Trace a bit (F8 key) till you are here: ======================================================================= :00416AA4 @loop: :00416AA4 mov eax, [ebp+var_B0] :00416AAA add eax, 1 ;increase counter :00416AAD mov [ebp+var_B0], eax ;var_B0 = counter :00416AB3 :00416AB3 loc_0_416AB3: :00416AB3 cmp [ebp+var_B0], 40h ;if counter = 0x40 :00416ABA jge short @end ;jump to end :00416ABC mov ecx, [ebp+var_B0] :00416AC2 mov dl, [ebp+ecx+aKAB_DSC_GoodTeam] ;dl = char from str :00416AC9 xor dl, 36h ;dl = dl xor 0x36 :00416ACC mov eax, [ebp+var_B0] :00416AD2 mov [ebp+eax+aKAB_DSC_GoodTeam], dl ;aKAB_DSC_. = dl :00416AD9 mov ecx, [ebp+var_B0] :00416ADF mov dl, [ebp+ecx+aKAB_DSC_GoodTeam_2] ;dl=char from str :00416AE3 xor dl, 5Ch ;dl = dl xor 0x5C :00416AE6 mov eax, [ebp+var_B0] :00416AEC mov [ebp+eax+aKAB_DSC_GoodTeam_2], dl ;aKAB_DSC_2. = dl :00416AF0 jmp short @loop ;jump to loop begin ======================================================================= Description of the loop: ======================================================================= 1. We have two inputs and outputs: aKAB_DSC_GoodTeam and aKAB_DSC_GoodTeam_2. These inputs are same strings: KAB+DSC=GoodTeam. ======================================================================= 2. This loop will execute 64-times (cmp [ebp+var_B0], 40h). ======================================================================= 3. The first string (aKAB_DSC_GoodTeam) is taken and its all chars are xored by 0x36. So the result is: }wtreu qYYRbSW[. ======================================================================= 4. The second string (aKAB_DSC_GoodTeam_2) is taken and its all chars are xored by 0x5C. So the result is: wa3389=m. ======================================================================= 5. Because the loop will execute 64-times the rest (64-16=48) is filled with number '6' (for the first string) and slash '/' (for the second string). Why six and slash? 0x00 xor 0x36 = 0x36, 0x00 xor 0x5C = 0x5C. ======================================================================= Final string no. 1: }wtreu qYYRbSW[ 6666666666666666 6666666666666666 6666666666666666 ======================================================================= Final string no. 2: wa3389=1 \\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\\ \\\\\\\\\\\\\\\\ ======================================================================= Maybe it looks horrible :/ but my source in C can help you: szConstant = KAB+DSC=GoodTeam; for (i=0; i<64; i++) { dl = szConstant[i]; dl ^= 0x36; aKAB_DSC_GoodTeam[i] = dl; ;Final string no. 1 dl = szConstant[i]; dl ^= 0x5C; aKAB_DSC_GoodTeam_2[i] = dl; ;Final string no. 2 } ======================================================================= After this loop ends we see initialization of MD5 algorithm: ======================================================================= :00416AF2 lea ecx, [ebp+MD5_CTX] ;ecx = MD5 context :00416AF8 push ecx ;push MD5 context :00416AF9 call MD5_Init ======================================================================= Inside MD5_init you can see four hex. constant. In IDA scroll down: ======================================================================= :00416B01 push 40h ;length of aKAB_DSC_Team :00416B03 lea edx, [ebp+aKAB_DSC_Team] :00416B09 push edx ;push aKAB_DS_Team :00416B0A lea eax, [ebp+MD5_CTX] :00416B10 push eax ;push MD5 context :00416B11 call MD5_Update ======================================================================= Wow! First encryption routine: Here is encrypted first string aKAB_DSC_GoodTeam (result no. 1 from loop above). ======================================================================= In IDA scrool down: ======================================================================= :00416B19 mov ecx, [ebp+arg_4] ;ecx = length of our name :00416B1C push ecx :00416B1D mov edx, [ebp+szName] ;edx = our name :00416B20 push edx :00416B21 lea eax, [ebp+MD5_CTX] ;eax = MD5 context :00416B27 push eax :00416B28 call MD5_Update ======================================================================= Second enryption routine: Here is encrypted our name. Below this you see: ======================================================================= :00416B30 lea ecx, [ebp-0ACh] ;ecx = MD5 context :00416B36 push ecx :00416B37 mov edx, [ebp+18h] ;edx = buffer for result :00416B3A push edx :00416B3B call MD5_Final ======================================================================= Here is MD5 final function. ======================================================================= :00416B43 lea eax, [ebp-0ACh] ;eax = MD5 context :00416B49 push eax :00416B4A call MD5_Init ======================================================================= Second MD5 initialization function. ======================================================================= :00416B52 push 40h ;length of aKAB_DSC_GoodTeam_2 :00416B54 lea ecx, [ebp-54h] ;ecx = aKAB_DSC_GoodTeam_2 :00416B57 push ecx :00416B58 lea edx, [ebp-0ACh] ;edx = MD5 context :00416B5E push edx :00416B5F call MD5_Update ======================================================================= Third encryption routine: Here is encrypted second string aKAB_DSC_GoodTeam_2 (result no. 2 from loop above). Immediately below this you see: ======================================================================= :00416B67 push 10h ;length of buffer from MD5_Final :00416B69 mov eax, [ebp+18h] ;eax = buffer from MD5_Final :00416B6C push eax :00416B6D lea ecx, [ebp-0ACh] ;ecx = MD5 context :00416B73 push ecx :00416B74 call MD5_Update ======================================================================= Here is encrypted the result buffer from the MD5_Final function (see above). Scroll down: ======================================================================= :00416B7C lea edx, [ebp-0ACh] ;edx = MD5 context :00416B82 push edx :00416B83 mov eax, [ebp+18h] ;buffer for result from MD5_Final :00416B86 push eax :00416B87 call MD5_Final ======================================================================= Final encryption routine. ======================================================================= Keygen steps: 1. Take users name. 2. Take string KAB+DSC=GoodTeam and hash all chars. using xor 0x36. 3. Behind result from step 2 add 48 '6' (six). 4. Take string KAB+DSC=GoodTeam and hash all chars. using xor 0x5C. 5. Behind resutl from step 4 add 48 '/' (slash). 6. MD5 initialization. 7. MD5 update the result from step 3. 8. MD5 update users name. 9. MD5 final. 10. MD5 initialization. 11. MD5 update the result from step 5. 12. MD5 update the result from step 9. 13. MD5 final. 14. Format and display serial. ======================================================================= My source in C: ======================================================================= unsigned char szName[100] = {0}; unsigned char szSerial[100] = {0}; unsigned char szHash[100] = {0}; unsigned char szKAB_DSC_GoodTeam[64] = {0}; unsigned char szKAB_DSC_GoodTeam_2[64] = {0}; unsigned char szConstant[64] = { 0x4B,0x41,0x42,0x2B,0x44,0x53,0x43,0x3D,0x47,0x6F,0x6F,0x64,0x54,0x65, 0x61,0x6D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; // KAB+DSC=GoodTeam string int nameLength,i,dl,inputLen; MD5_CTX md; //**********_Begin_algorithm_here_************ for (i=0; i<64; i++) { // loop dl = szConstant[i]; // KAB+DSC=GoodTeam string dl ^= 0x36; aKAB_DSC_GoodTeam[i] = dl; //Final string no. 1 dl = szConstant[i]; // KAB+DSC=GoodTeam string dl ^= 0x5C; aKAB_DSC_GoodTeam_2[i] = dl; //Final string no. 2 } MD5Init(&md); MD5Update(&md,aKAB_DSC_GoodTeam,0x40); MD5Update(&md,szName,nameLength); MD5Final(szSerial,&md); MD5Init(&md); MD5Update(&md,szaKAB_DSC_GoodTeam_2,0x40); MD5Update(&md,szSerial,0x10); MD5Final(szHash,&md); //**********_End_algorithm_here_************ //**********_The_rest_is_formating_of_the_final_serial_only_******** inputLen = strlen(szHash); for (i=0; i