【原文出处】
http://bbs.pediy.com/showthread.php?threadid=25785
【分析】
lnn1123兄弟这个KenGenMe,比起上个KenGenMe,难度上大了很多,一共用到CRC32,MD5,BLOWFISH,CAST128,TEA加密算法,分析如下:
00406154 . 33C0 xor eax, eax
00406156 . 6A 00 push 0 ; /pFileSystemNameSize = NULL
00406158 . 6A 00 push 0 ; |pFileSystemNameBuffer = NULL
0040615A . 6A 00 push 0 ; |pFileSystemFlags = NULL
0040615C . 6A 00 push 0 ; |pMaxFilenameLength = NULL
0040615E . 68 91804000 push 00408091 ; |pVolumeSerialNumber = KeyGenMe.00408091
00406163 . 6A 00 push 0 ; |MaxVolumeNameSize = 0
00406165 . 6A 00 push 0 ; |VolumeNameBuffer = NULL
00406167 . 68 8C804000 push 0040808C ; |c:\\
0040616C . E8 A9030000 call <jmp.&kernel32.GetVolumeInformationA> ; \GetVolumeInformationA
00406171 . A1 91804000 mov eax, [408091] ;获得C盘的VolumeInformation,再异或0x12345678,保存到serailc
00406176 . 35 78563412 xor eax, 12345678
0040617B . A3 95804000 mov [408095], eax ; 保存到408095中
00406180 . 68 95804000 push 00408095 ; ASCII "x??a24"
00406185 . 6A 04 push 4
00406187 . E8 A3BAFFFF call 00401C2F ; 对serailc的进行CRC32
0040618C . A3 B5804000 mov [4080B5], eax ; 值保存到nserailcCRC32
00406191 . 68 B5804000 push 004080B5
00406196 . 6A 04 push 4
00406198 . E8 92BAFFFF call 00401C2F ;对nserailcCRC32进行CRC32,不过后来没用到,不管
0040619D . A3 BD804000 mov [4080BD], eax
004061A2 . 61 popad
004061A3 . E9 30030000 jmp 004064D8
004061A8 > 817D 0C 11010>cmp dword ptr [ebp+C], 111
004061AF . 0F85 13030000 jnz 004064C8
004061B5 . 8B45 10 mov eax, [ebp+10]
004061B8 . 3D EE030000 cmp eax, 3EE
004061BD . 0F85 E5020000 jnz 004064A8
004061C3 . 53 push ebx
004061C4 . 56 push esi
004061C5 . 57 push edi
004061C6 . 55 push ebp
004061C7 . 6A 10 push 10 ; /Length = 10 (16.)
004061C9 . 68 F3804000 push 004080F3 ; |Destination = KeyGenMe.004080F3
004061CE . E8 4D030000 call <jmp.&kernel32.RtlZeroMemory> ; \RtlZeroMemory
004061D3 . 6A 10 push 10 ; /Length = 10 (16.)
004061D5 . 68 F3804000 push 004080F3 ; |Destination = KeyGenMe.004080F3
004061DA . E8 41030000 call <jmp.&kernel32.RtlZeroMemory> ; \RtlZeroMemory
004061DF . 6A 28 push 28 ; /Count = 28 (40.)
004061E1 . 68 03814000 push 00408103 ; |Buffer = KeyGenMe.00408103 UserName串
004061E6 . FF35 04804000 push dword ptr [408004] ; |hWnd = 0020020E (class='Edit',parent=002001B0)
004061EC . E8 05030000 call <jmp.&user32.GetWindowTextA> ; \GetWindowTextA
004061F1 . A3 D1804000 mov [4080D1], eax ; UserName长度
004061F6 . 68 03814000 push 00408103 ; ASCII "nightfox"
004061FB . 6A 04 push 4
004061FD . E8 2DBAFFFF call 00401C2F
00406202 . A3 C5804000 mov [4080C5], eax ; CRC32值
00406207 . 68 F3804000 push 004080F3 ; /Arg3 = 004080F3 ASCII "06f642a174362eb5771e93c5c3715bfe"
0040620C . FF35 D1804000 push dword ptr [4080D1] ; |Arg2 = 00000008
00406212 . 68 03814000 push 00408103 ; |Arg1 = 00408103 ASCII "nightfox"
00406217 . E8 E4ADFFFF call 00401000 ; \对UserName进行md5变换,保存到32位的string中
0040621C . 33D2 xor edx, edx
0040621E . 33C0 xor eax, eax
00406220 . 8D35 F3804000 lea esi, [4080F3] ; md5 str
00406226 . B9 04000000 mov ecx, 4
0040622B > 0BD0 or edx, eax
0040622D . 33C0 xor eax, eax
0040622F . AC lods byte ptr [esi]
00406230 . C1E2 08 shl edx, 8
00406233 .^ E2 F6 loopd short 0040622B
00406235 . 0BD0 or edx, eax
00406237 . 8915 A1804000 mov [4080A1], edx ; md5str 1-4位 leftdword
0040623D . B9 04000000 mov ecx, 4
00406242 . 33C0 xor eax, eax
00406244 . 33D2 xor edx, edx
00406246 > 0BD0 or edx, eax
00406248 . AC lods byte ptr [esi]
00406249 . C1E2 08 shl edx, 8
0040624C .^ E2 F8 loopd short 00406246
0040624E . 0BD0 or edx, eax
00406250 . 8915 99804000 mov [408099], edx ; md5str 5-8位 rightdword
//上面取md5str的1-8位 组成2个DWORD
00406256 . 6A 04 push 4 ; /Arg2 = 00000004
00406258 . 68 B5804000 push 004080B5 ; |Arg1 = 004080B5
0040625D . E8 76B7FFFF call 004019D8 ; \blowfish_init 用nserailcCRC32做密钥初始化blowfish
00406262 . 68 99804000 push 00408099 ; /Arg2 = 00408099 ASCII "1a24"
00406267 . 68 A1804000 push 004080A1 ; |Arg1 = 004080A1 ASCII "6f60"
0040626C . E8 0BB7FFFF call 0040197C ; \blowfish加密 leftdword rightdword
00406271 . 90 nop
00406272 . 90 nop
00406273 . 90 nop
00406274 . 6A 28 push 28 ; /Count = 28 (40.)
00406276 . 68 2B814000 push 0040812B ; |Buffer = KeyGenMe.0040812B
0040627B . FF35 08804000 push dword ptr [408008] ; |hWnd = 00260232 (class='Edit',parent=002001B0)
00406281 . E8 70020000 call <jmp.&user32.GetWindowTextA> ; \GetWindowTextA
00406286 . 83F8 20 cmp eax, 20
00406289 . 0F85 00020000 jnz 0040648F
0040628F . B9 08000000 mov ecx, 8
00406294 . 33C0 xor eax, eax
00406296 . 33D2 xor edx, edx
00406298 . 8D35 2B814000 lea esi, [40812B]
0040629E . 8D3D 33824000 lea edi, [408233]
004062A4 > 0FB606 movzx eax, byte ptr [esi]
004062A7 . 83F8 61 cmp eax, 61 ; Switch (cases 30..40)
004062AA . 72 05 jb short 004062B1
004062AC . 83E8 57 sub eax, 57
004062AF . EB 12 jmp short 004062C3
004062B1 > 83F8 41 cmp eax, 41
004062B4 . 72 05 jb short 004062BB
004062B6 . 83E8 37 sub eax, 37
004062B9 . EB 08 jmp short 004062C3
004062BB > 83F8 30 cmp eax, 30
004062BE . 72 03 jb short 004062C3
004062C0 . 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
004062A7
004062C3 > C1E0 04 shl eax, 4 ; Default case of switch 004062A7
004062C6 . 46 inc esi
004062C7 . 0FB616 movzx edx, byte ptr [esi]
004062CA . 83FA 61 cmp edx, 61 ; Switch (cases 30..40)
004062CD . 72 05 jb short 004062D4
004062CF . 83EA 57 sub edx, 57
004062D2 . EB 12 jmp short 004062E6
004062D4 > 83FA 41 cmp edx, 41
004062D7 . 72 05 jb short 004062DE
004062D9 . 83EA 37 sub edx, 37
004062DC . EB 08 jmp short 004062E6
004062DE > 83FA 30 cmp edx, 30
004062E1 . 72 03 jb short 004062E6
004062E3 . 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
004062CA
004062E6 > 03C2 add eax, edx ; Default case of switch 004062CA
004062E8 . 25 FF000000 and eax, 0FF
004062ED . 8807 mov [edi], al
004062EF . 47 inc edi
004062F0 . 46 inc esi
004062F1 . 49 dec ecx
004062F2 .^ 75 B0 jnz short 004062A4
004062F4 . B9 08000000 mov ecx, 8
004062F9 . 33C0 xor eax, eax
004062FB . 33D2 xor edx, edx
004062FD . 8D3D E5824000 lea edi, [4082E5]
00406303 > 0FB606 movzx eax, byte ptr [esi]
00406306 . 83F8 61 cmp eax, 61 ; Switch (cases 30..40)
00406309 . 72 05 jb short 00406310
0040630B . 83E8 57 sub eax, 57
0040630E . EB 12 jmp short 00406322
00406310 > 83F8 41 cmp eax, 41
00406313 . 72 05 jb short 0040631A
00406315 . 83E8 37 sub eax, 37
00406318 . EB 08 jmp short 00406322
0040631A > 83F8 30 cmp eax, 30
0040631D . 72 03 jb short 00406322
0040631F . 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
00406306
00406322 > C1E0 04 shl eax, 4 ; Default case of switch 00406306
00406325 . 46 inc esi
00406326 . 0FB616 movzx edx, byte ptr [esi]
00406329 . 83FA 61 cmp edx, 61 ; Switch (cases 30..40)
0040632C . 72 05 jb short 00406333
0040632E . 83EA 57 sub edx, 57
00406331 . EB 12 jmp short 00406345
00406333 > 83FA 41 cmp edx, 41
00406336 . 72 05 jb short 0040633D
00406338 . 83EA 37 sub edx, 37
0040633B . EB 08 jmp short 00406345
0040633D > 83FA 30 cmp edx, 30
00406340 . 72 03 jb short 00406345
00406342 . 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
00406329
00406345 > 03C2 add eax, edx ; Default case of switch 00406329
00406347 . 25 FF000000 and eax, 0FF
0040634C . 8807 mov [edi], al
0040634E . 47 inc edi
0040634F . 46 inc esi
00406350 . 49 dec ecx
00406351 .^ 75 B0 jnz short 00406303
//以上是取输入的32位注册码,保存到按从低到高 保存到4个DWORD中 a,b,c,d
00406353 . 6A 28 push 28 ; /Count = 28 (40.)
00406355 . 68 F3814000 push 004081F3 ; |Buffer = KeyGenMe.004081F3
0040635A . FF35 0C804000 push dword ptr [40800C] ; |hWnd = 001F0218 (class='Edit',parent=002001B0)
00406360 . E8 91010000 call <jmp.&user32.GetWindowTextA> ; \GetWindowTextA
00406365 . 68 67834000 push 00408367 ; /Arg3 = 00408367
0040636A . 50 push eax ; |Arg2 Group String
0040636B . 68 F3814000 push 004081F3 ; |Arg1 = 004081F3
00406370 . E8 8BACFFFF call 00401000 ; \取Group String md5变换 保存到md5str2中
00406375 . 33D2 xor edx, edx
00406377 . 33C0 xor eax, eax
00406379 . 8D35 67834000 lea esi, [408367]
0040637F . B9 04000000 mov ecx, 4
00406384 > 0BD0 or edx, eax
00406386 . 33C0 xor eax, eax
00406388 . AC lods byte ptr [esi]
00406389 . C1E2 08 shl edx, 8
0040638C .^ E2 F6 loopd short 00406384
0040638E . 0BD0 or edx, eax
00406390 . 8915 AD804000 mov [4080AD], edx ;md5str2 1-4位 leftdword1
00406396 . B9 04000000 mov ecx, 4
0040639B . 33C0 xor eax, eax
0040639D . 33D2 xor edx, edx
0040639F > 0BD0 or edx, eax
004063A1 . AC lods byte ptr [esi]
004063A2 . C1E2 08 shl edx, 8
004063A5 .^ E2 F8 loopd short 0040639F
004063A7 . 0BD0 or edx, eax
004063A9 . 8915 A9804000 mov [4080A9], edx ;md5str2 5-8位 leftdword1
//上面取md5str2的1-8位 组成2个DWORD
004063AF . B9 08000000 mov ecx, 8
004063B4 . 8D35 14954000 lea esi, [409514]
004063BA . 8D3D 65824000 lea edi, [408265]
004063C0 . F3:A4 rep movs byte ptr es:[edi], byte ptr [esi] ; 保存leftdword1 rightdword1
004063C2 . 68 F3804000 push 004080F3 ; ASCII "06f642a174362eb5771e93c5c3715bfe"
004063C7 . E8 A6D0FFFF call 00403472 ;用md5str1前16位 初始化cast128
004063CC . 68 33824000 push 00408233
004063D1 . 68 35834000 push 00408335
004063D6 . E8 26D6FFFF call 00403A01 ; 对输入注册码前16位进行CAST128加密,结果送到408335
004063DB . 6A 04 push 4 ; /Arg2 = 00000004
004063DD . 68 B5804000 push 004080B5 ; |Arg1 = 004080B5
004063E2 . E8 F1B5FFFF call 004019D8 ; \blowfish_init 用nserailcCRC32做密钥初始化
004063E7 . 68 A9804000 push 004080A9 ; /Arg2 = 004080A9 ASCII "9c12709f"
004063EC . 68 AD804000 push 004080AD ; |Arg1 = 004080AD ASCII "709f"
004063F1 . E8 86B5FFFF call 0040197C ; \blowfish加密 leftdword1 rightdword1
004063F6 . B9 08000000 mov ecx, 8
004063FB . 8D35 14954000 lea esi, [409514]
00406401 . 8D3D A5824000 lea edi, [4082A5]
00406407 . F3:A4 rep movs byte ptr es:[edi], byte ptr [esi]
00406409 . 8D35 33824000 lea esi, [408233]
0040640F . 83C6 08 add esi, 8
00406412 . 68 D5804000 push 004080D5 ; /[bcg][fcg][dfcg]
00406417 . 68 E5824000 push 004082E5 ; |Arg1 = 004082E5
0040641C . E8 63B7FFFF call 00401B84 ; \对注册码后16位用TEA解密 密钥"[bcg][fcg][dfcg]"
00406421 . 5D pop ebp ; 0013FB0C
00406422 . 5F pop edi
00406423 . 5E pop esi
00406424 . 5B pop ebx
00406425 . 33C0 xor eax, eax
00406427 . B9 08000000 mov ecx, 8
0040642C . 8D35 35834000 lea esi, [408335]
00406432 . 8D3D 65824000 lea edi, [408265]
00406438 . F3:A6 repe cmps byte ptr es:[edi], byte ptr [esi] ;和leftdword rightdword比较
0040643A . 0BC1 or eax, ecx
0040643C . 8BD0 mov edx, eax
0040643E . 33C0 xor eax, eax
00406440 . B9 08000000 mov ecx, 8
00406445 . 8D35 E5824000 lea esi, [4082E5]
0040644B . 8D3D A5824000 lea edi, [4082A5]
00406451 . F3:A6 repe cmps byte ptr es:[edi], byte ptr [esi] ;和leftdword1 rightdword1比较
00406453 . 0BD1 or edx, ecx
00406455 . 74 19 je short 00406470 ;成功
00406457 . 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00406459 . 68 E1704000 push 004070E1 ; |keygen #2
0040645E . 68 B0704000 push 004070B0 ; |wrong serial!
00406463 . FF35 00804000 push dword ptr [408000] ; |hOwner = 002001B0 ('KeyGenMe
#2',class='#32770')
00406469 . E8 94000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
0040646E . EB 68 jmp short 004064D8
00406470 > 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00406472 . 68 E1704000 push 004070E1 ; |keygen #2
00406477 . 68 BE704000 push 004070BE ; |congratulations! now code a keygen
0040647C . FF35 00804000 push dword ptr [408000] ; |hOwner = 002001B0 ('KeyGenMe
#2',class='#32770')
00406482 . E8 7B000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
00406487 . 33C0 xor eax, eax
00406489 . C9 leave
0040648A . C2 1000 retn 10
0040648D . EB 49 jmp short 004064D8
0040648F > 6A 10 push 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00406491 . 68 E1704000 push 004070E1 ; |keygen #2
00406496 . 68 EB704000 push 004070EB ; |length of serial invalid
0040649B . FF35 00804000 push dword ptr [408000] ; |hOwner = 002001B0 ('KeyGenMe
#2',class='#32770')
004064A1 . E8 5C000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004064A6 . EB 30 jmp short 004064D8
004064A8 > 3D EF030000 cmp eax, 3EF
004064AD . 75 29 jnz short 004064D8
004064AF . 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004064B1 . 68 38704000 push 00407038 ; |about
004064B6 . 68 3E704000 push 0040703E ; |keygenme #2 by lnn1123\n\ncode with win32asm!\n\nonly keygen\n\ndate:2006.\n\ndifficulty:3/10\n\nthanks to all people! \n\n
004064BB . FF35 00804000 push dword ptr [408000] ; |hOwner = 002001B0 ('KeyGenMe
#2',class='#32770')
004064C1 . E8 3C000000 call <jmp.&user32.MessageBoxA> ; \MessageBoxA
004064C6 . EB 10 jmp short 004064D8
004064C8 > 837D 0C 10 cmp dword ptr [ebp+C], 10
004064CC . 75 0A jnz short 004064D8
004064CE . 6A 00 push 0 ; /Result = 0
004064D0 . FF75 08 push dword ptr [ebp+8] ; |hWnd
004064D3 . E8 12000000 call <jmp.&user32.EndDialog> ; \EndDialog
004064D8 > 33C0 xor eax, eax
004064DA . C9 leave
004064DB . C2 1000 retn 10
【总结】
这个CrackMe的过程通过上面分析,已经很清楚了,先通过CRC32(C盘的序列号^0x12345678)=>nserailcCRC32,md5(username)=>md5str1,取前8位用blowfish加密,密钥是nserailcCRC32,再用md5str1前16位初始化cast128,对输入注册码前16位转成的2个DWORD进行加密,最后和第一次blowfish结果比较。
md5(group)=>md5str2,取前8位用blowfish加密,密钥是nserailcCRC32,再用TEA对输入注册码前16位转成的2个DWORD进行解密,密钥是"[BCG][FCG][DFCG]",最后和第二次blowfish结果比较。
两次比较结果相同,注册码成功。
破解方面,在第一个blowfish结果用cast128解密,第二次结果用tea加密,在转成对应的字符就是注册码了,具体见注册机代码。
我的注册码:
User:nightfox
Group:pediy
Serial:05f39e8d57fdecd9945c40bc6db7eff0
谢谢你看到这里,谢谢lnn1123的辛勤劳动。//BOW
收工,睡觉Zzzz
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!