原文见:
http://bbs.pediy.com/showthread.php?s=&threadid=25503
破解过程:
此CrackMe先后用到MD5,BlowFish,和TEA三种加密算法。分析如下
00401CC3 . 6A 00 push 0 ; /pFileSystemNameSize = NULL
00401CC5 . 6A 00 push 0 ; |pFileSystemNameBuffer = NULL
00401CC7 . 6A 00 push 0 ; |pFileSystemFlags = NULL
00401CC9 . 6A 00 push 0 ; |pMaxFilenameLength = NULL
00401CCB . 68 8D304000 push 0040308D ; |pVolumeSerialNumber = KeyGenMe.0040308D
00401CD0 . 6A 00 push 0 ; |MaxVolumeNameSize = 0
00401CD2 . 6A 00 push 0 ; |VolumeNameBuffer = NULL
00401CD4 . 68 88304000 push 00403088 ; |RootPathName = "c:\\"
00401CD9 . E8 40020000 call <jmp.&kernel32.GetVolumeInformationA> ; \GetVolumeInformationA
00401CDE . A1 8D304000 mov eax, [40308D]
00401CE3 . 35 78563412 xor eax, 12345678
00401CE8 . A3 91304000 mov [403091], eax //这个值后面一直没用到,所以就不管了
00401CED . E9 EA010000 jmp 00401EDC
00401CF2 > 817D 0C 1101000>cmp dword ptr [ebp+C], 111
00401CF9 . 0F85 CD010000 jnz 00401ECC
00401CFF . 8B45 10 mov eax, [ebp+10]
00401D02 . 3D EE030000 cmp eax, 3EE
00401D07 . 0F85 9F010000 jnz 00401EAC
00401D0D . 6A 10 push 10 ; /Length = 10 (16.)
00401D0F . 68 D4304000 push 004030D4 ; |Destination = KeyGenMe.004030D4
00401D14 . E8 0B020000 call <jmp.&kernel32.RtlZeroMemory> ; \RtlZeroMemory
00401D19 . 6A 28 push 28 ; /Count = 28 (40.)
00401D1B . 68 E4304000 push 004030E4 ; |Buffer = KeyGenMe.004030E4
00401D20 . FF35 04304000 push dword ptr [403004] ; |hWnd = 000A018C (class='Edit',parent=003E017A)
00401D26 . E8 CF010000 call <jmp.&user32.GetWindowTextA> ; \GetWindowTextA
00401D2B . 68 D4304000 push 004030D4 ; /Arg3 = 004030D4 ASCII "06f642a174362eb5771e93c5c3715bfe"
00401D30 . 50 push eax ; |Arg2
00401D31 . 68 E4304000 push 004030E4 ; |Arg1 = 004030E4 ASCII "771e93c5c3715bfe"
00401D36 . E8 C5F2FFFF call 00401000 ; \KeyGenMe.00401000 把注册名进行md5变换,变成一个32个字符的字符串md5str
00401D3B . 53 push ebx
00401D3C . 56 push esi
00401D3D . 57 push edi
00401D3E . 55 push ebp
00401D3F . 33D2 xor edx, edx
00401D41 . 33C0 xor eax, eax
00401D43 . 8D35 D4304000 lea esi, [4030D4]
00401D49 . B9 04000000 mov ecx, 4
00401D4E > 0BD0 or edx, eax
00401D50 . 33C0 xor eax, eax
00401D52 . AC lods byte ptr [esi]
00401D53 . C1E2 08 shl edx, 8
00401D56 .^ E2 F6 loopd short 00401D4E
00401D58 . 0BD0 or edx, eax
00401D5A . 8915 9D304000 mov [40309D], edx //取md5str的头4位变成DWORD存到[40309D]中,blowfish中加密用到LEFTDWORD
00401D60 . B9 04000000 mov ecx, 4
00401D65 . 33C0 xor eax, eax
00401D67 . 33D2 xor edx, edx
00401D69 > 0BD0 or edx, eax
00401D6B . AC lods byte ptr [esi]
00401D6C . C1E2 08 shl edx, 8
00401D6F .^ E2 F8 loopd short 00401D69
00401D71 . 0BD0 or edx, eax
00401D73 . 8915 95304000 mov [403095], edx//取md5str的5-8位变成DWORD存到[403095]中,blowfish中加密用到RIGHTDWORD
00401D79 . 6A 0C push 0C ; /Arg2 = 0000000C
00401D7B . 68 C7304000 push 004030C7 ; |Arg1 = 004030C7 ASCII "ChinaCracker" BLOWFISH的KEY "ChinaCracker"
00401D80 . E8 53FCFFFF call 004019D8 ; \KeyGenMe.004019D8 BLOWFISH的初始化
00401D85 . 68 95304000 push 00403095 ; /Arg2 = 00403095 RIGHTDWORD
00401D8A . 68 9D304000 push 0040309D ; |Arg1 = 0040309D LEFTDWORDA
00401D8F . E8 E8FBFFFF call 0040197C ; \KeyGenMe.0040197C BLOWFISH的加密过程 把上面MD5中提取出来的LEFTDWORD,和RIGHTDWORD进行加密
00401D94 . 90 nop
00401D95 . 90 nop
00401D96 . 90 nop
00401D97 . B8 04000000 mov eax, 4
00401D9C . 6A 28 push 28 ; /Count = 28 (40.)
00401D9E . 68 48314000 push 00403148 ; |Buffer = KeyGenMe.00403148
00401DA3 . FF35 08304000 push dword ptr [403008] ; |hWnd = 001001A6 (class='Edit',parent=003E017A)
00401DA9 . E8 4C010000 call <jmp.&user32.GetWindowTextA> ; \GetWindowTextA ;去SERIAL号
00401DAE . 83F8 10 cmp eax, 10
00401DB1 . 0F85 DC000000 jnz 00401E93
00401DB7 . B9 08000000 mov ecx, 8
00401DBC . 33C0 xor eax, eax
00401DBE . 33D2 xor edx, edx
00401DC0 . 8D35 48314000 lea esi, [403148]
00401DC6 . 8D3D AC314000 lea edi, [4031AC]
00401DCC > 0FB606 movzx eax, byte ptr [esi]
00401DCF . 83F8 61 cmp eax, 61 ; Switch (cases 30..40)
00401DD2 . 72 05 jb short 00401DD9
00401DD4 . 83E8 57 sub eax, 57
00401DD7 . EB 12 jmp short 00401DEB
00401DD9 > 83F8 41 cmp eax, 41
00401DDC . 72 05 jb short 00401DE3
00401DDE . 83E8 37 sub eax, 37
00401DE1 . EB 08 jmp short 00401DEB
00401DE3 > 83F8 30 cmp eax, 30
00401DE6 . 72 03 jb short 00401DEB
00401DE8 . 83E8 30 sub eax, 30 ; Cases 30 ('0'),31 ('1'),32 ('2'),33 ('3'),34 ('4'),35 ('5'),36 ('6'),37 ('7'),38 ('8'),39 ('9'),3A (':'),3B (';'),3C ('<'),3D ('='),3E ('>'),3F ('?'),40 ('@') of switch 00401DCF
00401DEB > C1E0 04 shl eax, 4 ; Default case of switch 00401DCF
00401DEE . 46 inc esi
00401DEF . 0FB616 movzx edx, byte ptr [esi]
00401DF2 . 83FA 61 cmp edx, 61 ; Switch (cases 30..40)
00401DF5 . 72 05 jb short 00401DFC
00401DF7 . 83EA 57 sub edx, 57
00401DFA . EB 12 jmp short 00401E0E
00401DFC > 83FA 41 cmp edx, 41
00401DFF . 72 05 jb short 00401E06
00401E01 . 83EA 37 sub edx, 37
00401E04 . EB 08 jmp short 00401E0E
00401E06 > 83FA 30 cmp edx, 30
00401E09 . 72 03 jb short 00401E0E
00401E0B . 83EA 30 sub edx, 30 ; Cases 30 ('0'),31 ('1'),32 ('2'),33 ('3'),34 ('4'),35 ('5'),36 ('6'),37 ('7'),38 ('8'),39 ('9'),3A (':'),3B (';'),3C ('<'),3D ('='),3E ('>'),3F ('?'),40 ('@') of switch 00401DF2
00401E0E > 03C2 add eax, edx ; Default case of switch 00401DF2
00401E10 . 25 FF000000 and eax, 0FF
00401E15 . 8807 mov [edi], al //把系列号保存到内存中
00401E17 . 47 inc edi
00401E18 . 46 inc esi
00401E19 . 49 dec ecx
00401E1A .^ 75 B0 jnz short 00401DCC
00401E1C . B9 08000000 mov ecx, 8
00401E21 . 8D35 5E434000 lea esi, [40435E]
00401E27 . 8D3D C0314000 lea edi, [4031C0]
00401E2D . F3:A4 rep movs byte ptr es:[edi], byte ptr [esi]
00401E2F . 68 B6304000 push 004030B6 ; /Arg2 = 004030B6 ASCII "[BCG][FCG][DFCG]" TEA解密的Key "[BCG][FCG][DFCG]"
00401E34 . 68 AC314000 push 004031AC ; |Arg1 = 004031AC TEA解密数据,就是保存内存中的输入的序列号
00401E39 . E8 46FDFFFF call 00401B84 ; \KeyGenMe.00401B84 TEA解密过程
00401E3E . 5D pop ebp ; 0013FB0C
00401E3F . 5F pop edi
00401E40 . 5E pop esi
00401E41 . 5B pop ebx
00401E42 . 33C0 xor eax, eax
00401E44 . B9 08000000 mov ecx, 8
00401E49 . 8D35 AC314000 lea esi, [4031AC]
00401E4F . 8D3D C0314000 lea edi, [4031C0]
00401E55 . F3:A6 repe cmps byte ptr es:[edi], byte ptr [esi] //比较
00401E57 . 0BC1 or eax, ecx
00401E59 . 74 19 je short 00401E74
00401E5B . 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401E5D . 68 DA204000 push 004020DA ; |Title = "KeyGen #1"
00401E62 . 68 B0204000 push 004020B0 ; |Text = "Serial error"
00401E67 . FF35 00304000 push dword ptr [403000] ; |hOwner = 003E017A ('KeyGenMe #1',class='#32770')
00401E6D . E8 94000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00401E72 . EB 68 jmp short 00401EDC
00401E74 > 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401E76 . 68 DA204000 push 004020DA ; |Title = "KeyGen #1"
00401E7B . 68 BD204000 push 004020BD ; |Text = "Well Done! Now Code a KeyGen"
00401E80 . FF35 00304000 push dword ptr [403000] ; |hOwner = 003E017A ('KeyGenMe #1',class='#32770')
00401E86 . E8 7B000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00401E8B . 33C0 xor eax, eax
00401E8D . C9 leave
00401E8E . C2 1000 retn 10
00401E91 . EB 49 jmp short 00401EDC
00401E93 > 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401E95 . 68 DA204000 push 004020DA ; |Title = "KeyGen #1"
00401E9A . 68 E4204000 push 004020E4 ; |Text = "length of Serial error"
00401E9F . FF35 00304000 push dword ptr [403000] ; |hOwner = 003E017A ('KeyGenMe #1',class='#32770')
00401EA5 . E8 5C000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00401EAA . EB 30 jmp short 00401EDC
00401EAC > 3D EF030000 cmp eax, 3EF
00401EB1 . 75 29 jnz short 00401EDC
00401EB3 . 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401EB5 . 68 38204000 push 00402038 ; |Title = "aBout"
00401EBA . 68 3E204000 push 0040203E ; |Text = "KeyGenMe #1 By lnn1123",LF,CR,"Code With Win32Asm!",LF,CR,"Only KeyGen",LF,CR,"Date:2006.5",LF,CR,"Difficulty:2/10",LF,CR,"Thanks to all people! ",LF,CR,""
00401EBF . FF35 00304000 push dword ptr [403000] ; |hOwner = 003E017A ('KeyGenMe #1',class='#32770')
00401EC5 . E8 3C000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00401ECA . EB 10 jmp short 00401EDC
00401ECC > 837D 0C 10 cmp dword ptr [ebp+C], 10
00401ED0 . 75 0A jnz short 00401EDC
00401ED2 . 6A 00 push 0 ; /Result = 0
00401ED4 . FF75 08 push dword ptr [ebp+8] ; |hWnd
00401ED7 . E8 12000000 call <jmp.&user32.EndDialog> ; \EndDialog
00401EDC > 33C0 xor eax, eax
00401EDE . C9 leave
00401EDF . C2 1000 retn 10
【结论】
通过分析,我们可以很清晰的看出这个CrackMe的过程,MD5(username)=>md5str,取md5str的前8位转换成两个 DWORD,用BlowFish加密,密钥为"ChinaCracker",再对保存的序列号用TEA解密,密钥为"[BCG][FCG][DFCG]",最后比较BlowFish加密的数据和 TEA解密的数据。
注册机过程,就是对BlowFish加密过的数据进行TEA加密,再按照格式转换成对应的字符串就是真正的注册号了。具体算法见注册机。
我的序列号
Name:nightfox
Serial:593e36c3b79738ab
谢谢你看到这里,谢谢lnn1123的辛勤劳动,//BOW
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课