【文章标题】: KeyMe2算法分析
【软件名称】: KeyMe2
【软件大小】: 10.5K
【下载地址】: 看附件
【编写语言】: VC
【使用工具】: UNKILLOD
【操作平台】: WINXP
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
该软件有ANTI-DEBUG部分,但是非常简单只是检测父进程,用UNKILLOD轻松躲过,下断BP GetWindowTextA可拦截,拦截返回后里面有SEH反调试代码,按F7略过,下面是分析算法:
00401285 |. E8 6D000000 CALL KeyMe2.004012F7 ; F7单步
0040128A |. EB 65 JMP SHORT KeyMe2.004012F1
0040128C |> 3D EC030000 CMP EAX,3EC
00401291 |. 75 15 JNZ SHORT KeyMe2.004012A8
00401293 |. 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401295 |. 68 00304000 PUSH KeyMe2.00403000 ; |about keyme2
0040129A |. 68 0D304000 PUSH KeyMe2.0040300D ; |welcome to new crackme!\n\n\nthis crackme needs generic keygen as solution,
nothing\n\nmore, nothing less. it is very easy. when you solve it,\n\nwrite tutorial how you did it. by! and good luck ;)!\n\n\nbig greetings goes to
everybody on biw reversing ..
0040129F |. 6A 00 PUSH 0 ; |hOwner = NULL
004012A1 |. E8 48050000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
004012A6 |. EB 49 JMP SHORT KeyMe2.004012F1
004012A8 |> 3D EF030000 CMP EAX,3EF
004012AD |. 75 42 JNZ SHORT KeyMe2.004012F1
004012AF |. FF35 EC344000 PUSH DWORD PTR DS:[4034EC] ; /ExitCode = 103 (259.)
004012B5 |. FF35 E8344000 PUSH DWORD PTR DS:[4034E8] ; |hThread = 00000060 (window)
004012BB |. E8 A6050000 CALL <JMP.&kernel32.TerminateThread> ; \TerminateThread
004012C0 |. 6A 00 PUSH 0 ; /lParam = 0
004012C2 |. 6A 00 PUSH 0 ; |wParam = 0
004012C4 |. 6A 10 PUSH 10 ; |Message = WM_CLOSE
004012C6 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012C9 |. E8 26050000 CALL <JMP.&user32.SendMessageA> ; \SendMessageA
004012CE |. EB 21 JMP SHORT KeyMe2.004012F1
004012D0 |> 837D 0C 10 CMP DWORD PTR SS:[EBP+C],10
004012D4 |. 75 1B JNZ SHORT KeyMe2.004012F1
004012D6 |. FF35 EC344000 PUSH DWORD PTR DS:[4034EC] ; /ExitCode = 103 (259.)
004012DC |. FF35 E8344000 PUSH DWORD PTR DS:[4034E8] ; |hThread = 00000060 (window)
004012E2 |. E8 7F050000 CALL <JMP.&kernel32.TerminateThread> ; \TerminateThread
004012E7 |. 6A 00 PUSH 0 ; /Result = 0
004012E9 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012EC |. E8 DF040000 CALL <JMP.&user32.EndDialog> ; \EndDialog
004012F1 |> 33C0 XOR EAX,EAX
004012F3 |. C9 LEAVE
004012F4 \. C2 1000 RETN 10
004012F7 /$ 83F8 00 CMP EAX,0 ; 比较长度
004012FA |. 75 01 JNZ SHORT KeyMe2.004012FD
004012FC |. C3 RETN
004012FD |> 33C0 XOR EAX,EAX
004012FF |. 33DB XOR EBX,EBX
00401301 |. 33C9 XOR ECX,ECX
00401303 |. B8 04000000 MOV EAX,4 ; EAX=4
00401308 |> 81B8 50324000>/CMP DWORD PTR DS:[EAX+403250],3D6F6E2E ; 第四位后,注意这里的3D6F6E2E=".no="(内存中是反序的),我们暂时称它为特征码
00401312 |. 75 03 |JNZ SHORT KeyMe2.00401317
00401314 |. 43 |INC EBX
00401315 |. 8BC8 |MOV ECX,EAX ; 注意:此时EAX=ECX=注册码中这四个字符的开始位,这里的ECX的值非常关键,下面多次用到
00401317 |> 40 |INC EAX ; 第4位开始累加
00401318 |. 83F8 09 |CMP EAX,9 ; 是否达到9位,这段循环中规定注册码第4-9位中必须含有.no=而且该字段的在注册码中的位置赋
值给ECX
0040131B |.^ 75 EB \JNZ SHORT KeyMe2.00401308
0040131D |. 83FB 01 CMP EBX,1
00401320 |. 74 14 JE SHORT KeyMe2.00401336
00401322 |. 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401324 |. 68 DE314000 PUSH KeyMe2.004031DE ; |input error
00401329 |. 68 EA314000 PUSH KeyMe2.004031EA ; |serial format is incorrect! try again.
0040132E |. 6A 00 PUSH 0 ; |hOwner = NULL
00401330 |. E8 B9040000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401335 |. C3 RETN
00401336 |> E8 24000000 CALL KeyMe2.0040135F ; 规定格式
0040133B |. E8 74000000 CALL KeyMe2.004013B4
00401340 |. E8 D7000000 CALL KeyMe2.0040141C
00401345 |. E8 1D010000 CALL KeyMe2.00401467
0040134A |. E8 AD010000 CALL KeyMe2.004014FC
0040134F |. E8 E5010000 CALL KeyMe2.00401539
00401354 |. E8 F9010000 CALL KeyMe2.00401552
00401359 |. E8 45020000 CALL KeyMe2.004015A3
0040135E \. C3 RETN
0040135F /$ C781 50324000>MOV DWORD PTR DS:[ECX+403250],0
00401369 |. 33DB XOR EBX,EBX
0040136B |. EB 24 JMP SHORT KeyMe2.00401391
0040136D |. 47 6F 20 61 7>ASCII "Go away!",0
00401376 |. 49 27 6D 20 6>ASCII "I'm just",0
0040137F |. 63 68 61 6E 6>ASCII "changing",0
00401388 |. 62 75 66 66 6>ASCII "buffers.",0
00401391 |> 8B1D 50324000 MOV EBX,DWORD PTR DS:[403250] ; 注册码第一位,注意403250
00401397 |. 891D 80324000 MOV DWORD PTR DS:[403280],EBX
0040139D |. 8B1D 54324000 MOV EBX,DWORD PTR DS:[403254] ; 第五位,403250+4=1+4
004013A3 |. 891D 84324000 MOV DWORD PTR DS:[403284],EBX
004013A9 |. C781 80324000>MOV DWORD PTR DS:[ECX+403280],0 ; ECX+403280,ECX的值上面已经求得
004013B3 \. C3 RETN
004013B4 /$ 80B9 5C324000>CMP BYTE PTR DS:[ECX+40325C],3A ; 第ECX+12位(ECX的值应该不会忘记吧)必须为:,即5A
004013BB |. 74 17 JE SHORT KeyMe2.004013D4
004013BD |. 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013BF |. 68 DE314000 PUSH KeyMe2.004031DE ; |input error
004013C4 |. 68 EA314000 PUSH KeyMe2.004031EA ; |serial format is incorrect! try again.
004013C9 |. 6A 00 PUSH 0 ; |hOwner = NULL
004013CB |. E8 1E040000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
004013D0 |. 83C4 04 ADD ESP,4
004013D3 |. C3 RETN
004013D4 |> 80B9 65324000>CMP BYTE PTR DS:[ECX+403265],3A ; 第ECX+21位(ECX的值应该不会忘记吧)必须为:,即5A
004013DB |. 74 17 JE SHORT KeyMe2.004013F4
004013DD |. 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013DF |. 68 DE314000 PUSH KeyMe2.004031DE ; |input error
004013E4 |. 68 EA314000 PUSH KeyMe2.004031EA ; |serial format is incorrect! try again.
004013E9 |. 6A 00 PUSH 0 ; |hOwner = NULL
004013EB |. E8 FE030000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
004013F0 |. 83C4 04 ADD ESP,4
004013F3 |. C3 RETN
004013F4 |> 80B9 6E324000>CMP BYTE PTR DS:[ECX+40326E],0 ; 第ECX+30位(ECX的值应该不会忘记吧)必须为空,对注册码的长度做了规定
004013FB |. 74 17 JE SHORT KeyMe2.00401414
004013FD |. 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004013FF |. 68 DE314000 PUSH KeyMe2.004031DE ; |input error
00401404 |. 68 EA314000 PUSH KeyMe2.004031EA ; |serial format is incorrect! try again.
00401409 |. 6A 00 PUSH 0 ; |hOwner = NULL
0040140B |. E8 DE030000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401410 |. 83C4 04 ADD ESP,4
00401413 |. C3 RETN
00401414 |> C681 6E324000>MOV BYTE PTR DS:[ECX+40326E],0
0040141B \. C3 RETN
0040141C /$ 33DB XOR EBX,EBX
0040141E |. 8B99 54324000 MOV EBX,DWORD PTR DS:[ECX+403254] ; 第ECX+5位
00401424 |. 891D 90324000 MOV DWORD PTR DS:[403290],EBX ; 放入DS:[403290]
0040142A |. 8B99 58324000 MOV EBX,DWORD PTR DS:[ECX+403258] ; 第ECX+9位
00401430 |. 891D 94324000 MOV DWORD PTR DS:[403294],EBX ; 放入DS:[403294]
00401436 |. 8B99 5D324000 MOV EBX,DWORD PTR DS:[ECX+40325D] ; 第ECX+14位
0040143C |. 891D 98324000 MOV DWORD PTR DS:[403298],EBX ; 放入DS:[403298]
00401442 |. 8B99 61324000 MOV EBX,DWORD PTR DS:[ECX+403261] ; 第ECX+18位
00401448 |. 891D 9C324000 MOV DWORD PTR DS:[40329C],EBX ; 放入DS:[40329C]
0040144E |. 8B99 66324000 MOV EBX,DWORD PTR DS:[ECX+403266] ; 第ECX+23位
00401454 |. 891D A0324000 MOV DWORD PTR DS:[4032A0],EBX ; 放入DS:[4032A0]
0040145A |. 8B99 6A324000 MOV EBX,DWORD PTR DS:[ECX+40326A] ; 第ECX+27位
00401460 |. 891D A4324000 MOV DWORD PTR DS:[4032A4],EBX ; 放入DS:[4032A4]
00401466 \. C3 RETN
00401467 /$ EB 1A JMP SHORT KeyMe2.00401483
00401469 |. 4E 6F 74 68 6>ASCII "Nothing",0
00401471 |. 69 6E 74 65 7>ASCII "interesting",0
0040147D |. 68 65 72 65 2>ASCII "here.",0
00401483 |> C705 50324000>MOV DWORD PTR DS:[403250],0
0040148D |. C705 54324000>MOV DWORD PTR DS:[403254],0
00401497 |. C705 58324000>MOV DWORD PTR DS:[403258],0
004014A1 |. C705 5C324000>MOV DWORD PTR DS:[40325C],0
004014AB |. C705 60324000>MOV DWORD PTR DS:[403260],0
004014B5 |. C705 64324000>MOV DWORD PTR DS:[403264],0
004014BF |. C705 68324000>MOV DWORD PTR DS:[403268],0
004014C9 |. C705 6C324000>MOV DWORD PTR DS:[40326C],0
004014D3 |. C705 70324000>MOV DWORD PTR DS:[403270],0
004014DD |. C705 74324000>MOV DWORD PTR DS:[403274],0
004014E7 |. C705 78324000>MOV DWORD PTR DS:[403278],0
004014F1 |. C705 7C324000>MOV DWORD PTR DS:[40327C],0
004014FB \. C3 RETN
004014FC /$ 68 80324000 PUSH KeyMe2.00403280 ; /特征字符的前面部分
00401501 |. E8 6C030000 CALL <JMP.&kernel32.lstrlenA> ; \取这部分长度
00401506 |. 33DB XOR EBX,EBX
00401508 |. 33C9 XOR ECX,ECX
0040150A |. 8BD8 MOV EBX,EAX
0040150C |> 0FB68B 7F3240>/MOVZX ECX,BYTE PTR DS:[EBX+40327F] ; 逐个倒取这部分的ASCII码
00401513 |. 51 |PUSH ECX ; /Char
00401514 |. E8 C9020000 |CALL <JMP.&user32.IsCharAlphaA> ; \是否为字母,是字母返回EAX=1
00401519 |. 83F8 00 |CMP EAX,0
0040151C |. 75 17 |JNZ SHORT KeyMe2.00401535
0040151E |. 6A 30 |PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401520 |. 68 DE314000 |PUSH KeyMe2.004031DE ; |input error
00401525 |. 68 EA314000 |PUSH KeyMe2.004031EA ; |serial format is incorrect! try again.
0040152A |. 6A 00 |PUSH 0 ; |hOwner = NULL
0040152C |. E8 BD020000 |CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401531 |. 83C4 04 |ADD ESP,4
00401534 |. C3 |RETN
00401535 |> 4B |DEC EBX ; 逐个递减
00401536 |.^ 75 D4 \JNZ SHORT KeyMe2.0040150C
00401538 \. C3 RETN
00401539 /$ E8 EC020000 CALL <JMP.&kernel32.GetLogicalDrives> ; 取逻辑硬盘名GetLogicalDrives()
0040153E |. A3 B0324000 MOV DWORD PTR DS:[4032B0],EAX ; 返回值放入DS:[4032B0]
00401543 |. 33C0 XOR EAX,EAX
00401545 |. E8 F2020000 CALL <JMP.&kernel32.GetVersion> ; 取系统Windows版本GetVersion()
0040154A |. A3 B4324000 MOV DWORD PTR DS:[4032B4],EAX ; 返回值放入DS:[4032B0+4]
0040154F |. 33C0 XOR EAX,EAX
00401551 \. C3 RETN
00401552 /$ 33C0 XOR EAX,EAX ; EAX清空
00401554 |. 33DB XOR EBX,EBX ; EBX清空
00401556 |. 33C9 XOR ECX,ECX ; ECX清空
00401558 |> 0FB683 803240>/MOVZX EAX,BYTE PTR DS:[EBX+403280] ; 逐个取特征码前面部分注册码的ASCII
0040155F |. 83F8 00 |CMP EAX,0 ; 是否为0
00401562 |. 74 17 |JE SHORT KeyMe2.0040157B ; 如果是0就跳过下面这段计算,即只有特征码前面部分参与计算
00401564 |> 3081 B0324000 |/XOR BYTE PTR DS:[ECX+4032B0],AL ; 异或取得的逻辑硬盘值后放回ECX+4032B0
0040156A |. 41 ||INC ECX ; ECX从0累加
0040156B |. D289 B0324000 ||ROR BYTE PTR DS:[ECX+4032B0],CL ; 每异或一次循环右移一位
00401571 |. 83F9 08 ||CMP ECX,8 ; 是否达到8
00401574 |.^ 75 EE |\JNZ SHORT KeyMe2.00401564
00401576 |. 33C9 |XOR ECX,ECX
00401578 |. 43 |INC EBX
00401579 |.^ EB DD \JMP SHORT KeyMe2.00401558
0040157B |> 33C0 XOR EAX,EAX
0040157D |. 33DB XOR EBX,EBX
0040157F |. 33C9 XOR ECX,ECX
00401581 |> 0FB683 903240>/MOVZX EAX,BYTE PTR DS:[EBX+403290] ; 逐个取特征码后面部分注册码的ASCII
00401588 |> 3081 B0324000 |XOR BYTE PTR DS:[ECX+4032B0],AL ; 异或上次计算后ECX+4032B0中的值
0040158E |. 41 |INC ECX ; ECX累加
0040158F |. D289 B0324000 |ROR BYTE PTR DS:[ECX+4032B0],CL ; 结果循环右移CL位后放回ECX+4032B0
00401595 |. 83F9 08 |CMP ECX,8 ; 是否达到8
00401598 |.^ 75 EE |JNZ SHORT KeyMe2.00401588
0040159A |. 33C9 |XOR ECX,ECX
0040159C |. 43 |INC EBX ; EBX累加
0040159D |. 83FB 10 |CMP EBX,10 ; 是否达到10位
004015A0 |.^ 75 DF \JNZ SHORT KeyMe2.00401581 ; 没有则循环
004015A2 \. C3 RETN
004015A3 /$ A1 B0324000 MOV EAX,DWORD PTR DS:[4032B0] ; 取出DS:[4032B0]的值放入EAX
004015A8 |. 0305 B4324000 ADD EAX,DWORD PTR DS:[4032B4] ; 加DS:[4032B4]的值
004015AE |. 50 PUSH EAX ; 压入结果
004015AF |. 68 22324000 PUSH KeyMe2.00403222 ; /sprintf
004015B4 |. 68 17324000 PUSH KeyMe2.00403217 ; |/msvcrt.dll
004015B9 |. E8 84020000 CALL <JMP.&kernel32.LoadLibraryA> ; |\LoadLibraryA
004015BE |. 50 PUSH EAX ; |hModule
004015BF |. E8 72020000 CALL <JMP.&kernel32.GetProcAddress> ; \GetProcAddress
004015C4 |. 68 11324000 PUSH KeyMe2.00403211 ; ASCII "%.8X"
004015C9 |. 68 C0324000 PUSH KeyMe2.004032C0
004015CE |. FFD0 CALL EAX
004015D0 |. 83C4 0C ADD ESP,0C
004015D3 |. 8D05 A0324000 LEA EAX,DWORD PTR DS:[4032A0] ; 地址=004032A0, 注册码的第二个“:”后面部分
004015D9 |. 50 PUSH EAX ; /注册码5A(:)后部分
004015DA |. 68 C0324000 PUSH KeyMe2.004032C0 ; |对比是否为上面的计算结果
004015DF |. E8 88020000 CALL <JMP.&kernel32.lstrcmpA> ; \lstrcmpA
004015E4 |. 83F8 00 CMP EAX,0
004015E7 |. 74 14 JE SHORT KeyMe2.004015FD ; 爆破点
004015E9 |. 6A 10 PUSH 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004015EB |. 68 A0314000 PUSH KeyMe2.004031A0 ; |serial not valid
004015F0 |. 68 B1314000 PUSH KeyMe2.004031B1 ; |serial number is not valid for this machine!
004015F5 |. 6A 00 PUSH 0 ; |hOwner = NULL
004015F7 |. E8 F2010000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
004015FC |. C3 RETN
004015FD |> 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004015FF |. 68 5C314000 PUSH KeyMe2.0040315C ; |registered!
00401604 |. 68 68314000 PUSH KeyMe2.00403168 ; |serial number is accepted! now write small tutorial :)!
00401609 |. 6A 00 PUSH 0 ; |hOwner = NULL
0040160B |. E8 DE010000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
算法总结:
1、注册码中必须含有字符.no=,我们暂时称它为特征码,其第一个字符位置在整个注册码的第4位到第8位之间,这个位置记为A。
那么注册码的总长度为A+30位,其中第A+13位和第A+22位必须为字符:。
2、特征码前面部分必须为英文字母,逐个取前面部分字母的ASCII码与取得的盘符名分8次做异或运算,每异或一次循环右移一次。假设最终结果为B。
逐个取特征码后面部分的10个字符,也是分8次与上面的结果B做异或运算,每异或一次循环右移它的累加次数一次。最终结果加上取系统版本后的参数值的16进制值为注册码中第二个“:”后的部分。
3、特征码前的英文字母可以任意,目的是推算出后面部分的注册码,特征码后跟第二个“:”之间的字符任意。
比如:.no=是在注册码的第五位开始,注册码前面部分是abcd,则第5+13和第5+23位为字符“:”,注册码前面部分应该是这样形式:abcd.no=90123456:89012345:********, 然后取abcd中的每个字符与GetLogicalDrives()和GetVersion()的各个返回值(两个16进制值)做8次异或运算,再逐个取9012345689与结果也依次分8次做异或运算,然后将前后两部分相加后的16进制值即为注册码的后面部分。
--------------------------------------------------------------------------------
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!
2006年05月22日 15:48:13
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: