【文章标题】: CuTedEvil's CrackMe #2的算法分析+注册机
【文章作者】: bxm
【作者邮箱】: bxm78@163.com
【保护方式】: name,serial
【编写语言】: MASM32 / TASM32
【使用工具】: od,peid,计算器,VC++
【操作平台】: winxp
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
通过字符串在[00401163]处下断,输入
user name:bxm78
user key:780328051
00401163 . E8 F2020000 call <jmp.&USER32.GetDlgItemT>; \GetDlgItemTextA
00401168 . 83F8 00 cmp eax, 0
0040116B . 0F84 36020000 je 004013A7
00401171 . 6A 20 push 20 ; /Count = 20 (32.)
00401173 . 68 50324000 push 00403250 ; |Buffer = CrckMe2.00403250
00401178 . 68 EC030000 push 3EC ; |ControlID = 3EC (1004.)
0040117D . FF35 2C324000 push dword ptr [40322C] ; |hWnd = 000803A4 ('CuTedEvil Crack Me 2',class='DLGCLASS')
00401183 . E8 D2020000 call <jmp.&USER32.GetDlgItemT>; \GetDlgItemTextA
00401188 . 83F8 00 cmp eax, 0
0040118B . 0F84 2F020000 je 004013C0
00401191 . 60 pushad
00401192 . 8D35 30324000 lea esi, [403230]
00401198 . 8D3D 70324000 lea edi, [403270]
0040119E . 68 30324000 push 00403230 ; /String = "bxm78"
004011A3 . E8 06030000 call <jmp.&KERNEL32.lstrlenA> ; \lstrlenA
004011A8 . 83F8 20 cmp eax, 20 ; name长度<32 ?
004011AB . 0F82 C0010000 jb 00401371 ; 是,跳
004011B1 > 8BC8 mov ecx, eax
004011B3 > 83F9 00 cmp ecx, 0
004011B6 . 74 04 je short 004011BC
004011B8 . A4 movs byte ptr es:[edi], byte >
004011B9 . 49 dec ecx
004011BA .^ EB F7 jmp short 004011B3
004011BC > 8D3D 70324000 lea edi, [403270] ; 扩充后的name入EDI
004011C2 . 8D35 EE314000 lea esi, [4031EE] ; 表0首地址入ESI
004011C8 . 8B1F mov ebx, [edi] ; name前4位的ASCII值入EBX
004011CA . 8B4F 04 mov ecx, [edi+4] ; name第5-8位的ASCII值入ECX
004011CD . 33C0 xor eax, eax ; EAX清0
004011CF . 66:C705 03324>mov word ptr [403203], 20 ; 循环次数存入[403203]单元
004011D8 . EB 3F jmp short 00401219
004011DA > 05 DCBC1B4F add eax, 4F1BBCDC ; EAX+4F1BBCDC
004011DF . 8BD1 mov edx, ecx
004011E1 . C1E2 04 shl edx, 4 ; EDX逻辑左移4位
004011E4 . 03DA add ebx, edx ; EBX+EDX
004011E6 . 8B16 mov edx, [esi] ; 表的前4位入EDX(即72657355H)
004011E8 . 33D1 xor edx, ecx ; EDX与ECX异或
004011EA . 03DA add ebx, edx ; EBX+EDX
004011EC . 8BD1 mov edx, ecx ; ECX入EDX
004011EE . C1EA 05 shr edx, 5 ; EDX逻辑右移5位
004011F1 . 33D0 xor edx, eax ; EDX与EAX异或
004011F3 . 03DA add ebx, edx ; EBX+EDX
004011F5 . 035E 04 add ebx, [esi+4] ; EBX+表的第5-8位(即656D614EH)
004011F8 . 8BD3 mov edx, ebx ; EBX入EDX
004011FA . C1E2 04 shl edx, 4 ; EDX逻辑左移4位
004011FD . 03CA add ecx, edx ; ECX+EDX
004011FF . 8B56 08 mov edx, [esi+8] ; 表的第9-12位(即64614200H)入EDX
00401202 . 33D3 xor edx, ebx ; EDX与EBX异或
00401204 . 03CA add ecx, edx ; ECX+EDX
00401206 . 8BD3 mov edx, ebx ; EBX入EDX
00401208 . C1EA 05 shr edx, 5 ; EDX逻辑右移5位
0040120B . 33D0 xor edx, eax ; EDX与EAX异或
0040120D . 03CA add ecx, edx ; ECX+EDX
0040120F . 034E 0C add ecx, [esi+C] ; ECX+表的第13-16位(6172435FH)
00401212 . 66:FF0D 03324>dec word ptr [403203] ; 循环次数减1
00401219 > 66:833D 03324>cmp word ptr [403203], 0 ; 循环完了没
00401221 .^ 77 B7 ja short 004011DA ; 没有,继续循环
00401223 . 891D 90324000 mov [403290], ebx ; 我的EBX为3AF3F16F
00401229 . 890D 94324000 mov [403294], ecx ; 我的ECX为D31760F0
0040122F . 33C9 xor ecx, ecx ; ECX清0
00401231 > 83F9 08 cmp ecx, 8 ; ECX=8?
00401234 . 74 30 je short 00401266 ; 是,跳
00401236 . 8A81 90324000 mov al, [ecx+403290] ; name的前8位运算结果作为表1
0040123C . 8A99 05324000 mov bl, [ecx+403205] ; 依次装入表2数据(表2为十六进制值2D 27 A1 25 5C 6B 27 5D)
00401242 . 8A91 0F324000 mov dl, [ecx+40320F] ; 依次装入表3数据(表3为字符串10100111)
00401248 . 80EA 30 sub dl, 30 ; DL-30H
0040124B . 0AD2 or dl, dl
0040124D . 75 04 jnz short 00401253 ; 如DL为1,跳,否则,不跳,即根据DL的值分支处理
0040124F . 02C3 add al, bl ; AL+BL
00401251 . EB 02 jmp short 00401255
00401253 > 2AC3 sub al, bl ; AL-BL
00401255 > 8A99 19324000 mov bl, [ecx+403219] ; 依次装入表4数据(表4为十六进制值43 75 54 65 64 45 76 69)
0040125B . 38D8 cmp al, bl ; AL=BL ?
0040125D 0F85 29010000 jnz 0040138C ; 不等,完蛋
00401263 . 41 inc ecx
00401264 .^ EB CB jmp short 00401231
00401266 > 8D3D 70324000 lea edi, [403270] ; 扩充后的name首址入EDI
0040126C . 8D35 F7314000 lea esi, [4031F7] ; 表5首址入ESI
00401272 . 8B5F 08 mov ebx, [edi+8] ; name第9-12位的ASCII值入EBX
00401275 . 8B4F 0C mov ecx, [edi+C] ; name第13-16位的ASCII值入ECX
00401278 . 33C0 xor eax, eax ; 清0
0040127A . 66:C705 03324>mov word ptr [403203], 20 ; 循环次数入[403203]
00401283 . EB 3F jmp short 004012C4
00401285 > 05 3412CDAB add eax, ABCD1234
0040128A . 8BD1 mov edx, ecx
0040128C . C1E2 04 shl edx, 4
0040128F . 03DA add ebx, edx
00401291 . 8B16 mov edx, [esi]
00401293 . 33D1 xor edx, ecx
00401295 . 03DA add ebx, edx
00401297 . 8BD1 mov edx, ecx
00401299 . C1EA 05 shr edx, 5
0040129C . 33D0 xor edx, eax
0040129E . 03DA add ebx, edx
004012A0 . 035E 04 add ebx, [esi+4]
004012A3 . 8BD3 mov edx, ebx
004012A5 . C1E2 04 shl edx, 4
004012A8 . 03CA add ecx, edx
004012AA . 8B56 08 mov edx, [esi+8]
004012AD . 33D3 xor edx, ebx
004012AF . 03CA add ecx, edx
004012B1 . 8BD3 mov edx, ebx
004012B3 . C1EA 05 shr edx, 5
004012B6 . 33D0 xor edx, eax
004012B8 . 03CA add ecx, edx
004012BA . 034E 0C add ecx, [esi+C]
004012BD . 66:FF0D 03324>dec word ptr [403203]
004012C4 > 66:833D 03324>cmp word ptr [403203], 0
004012CC .^ 77 B7 ja short 00401285
004012CE . 891D A0324000 mov [4032A0], ebx ; 我的EBX为5E2D1B86
004012D4 . 890D A4324000 mov [4032A4], ecx ; 我的ECX为67BF2A24
004012DA . 803D A0324000>cmp byte ptr [4032A0], 0E0
004012E1 . 0F85 A5000000 jnz 0040138C
004012E7 . A0 A0324000 mov al, [4032A0]
004012EC . 0205 A1324000 add al, [4032A1]
004012F2 . 0205 A2324000 add al, [4032A2]
004012F8 . 0205 A3324000 add al, [4032A3]
004012FE . 0205 A4324000 add al, [4032A4]
00401304 . 0205 A5324000 add al, [4032A5]
0040130A . 0205 A6324000 add al, [4032A6]
00401310 . 0205 A7324000 add al, [4032A7]
00401316 . 0205 A8324000 add al, [4032A8]
0040131C . 3C EF cmp al, 0EF
0040131E . 75 6C jnz short 0040138C
上面都是对name 的前16位验证,我用VC++把上面的代码改成了C,通过穷举法算出name的前16位为字符串Cracked &\zM$NJ'
下面才是对name的后半部分和key进行验证。
00401320 . 8D3D 80324000 lea edi, [403280] ; 扩充后的name的第17位首址入EDI
00401326 . 8D35 50324000 lea esi, [403250] ; serial入ESI
0040132C . B9 10000000 mov ecx, 10 ; 循环次数入ECX
00401331 . BA 03000000 mov edx, 3 ; EDX=3
00401336 > 83F9 00 cmp ecx, 0 ; ECX=0 ?
00401339 . 74 1B je short 00401356 ; 比较完,跳向成功
0040133B . 8A07 mov al, [edi] ; [EDI]入AL
0040133D . 8A1E mov bl, [esi] ; [ESI]入BL
0040133F . 3C 30 cmp al, 30 ; AL=30H ?
00401341 . 75 07 jnz short 0040134A ; 不等于,跳
00401343 . 83F9 0C cmp ecx, 0C ; ECX>=0C ?
00401346 . 73 44 jnb short 0040138C ; 是,完蛋,这句说明name长度至少为21位,最后几位可以为空
00401348 . EB 44 jmp short 0040138E ; 跳向成功
0040134A > 32C3 xor al, bl ; AL与BL异或
0040134C . 38D0 cmp al, dl ; AL=BL ?
0040134E . 75 3C jnz short 0040138C ; 不等,完蛋
00401350 . 46 inc esi
00401351 . 47 inc edi
00401352 . 42 inc edx
00401353 . 49 dec ecx
00401354 .^ EB E0 jmp short 00401336
00401356 > EB 36 jmp short 0040138E
算法小结:
1、name长度至少为23个字符,其中前16位为固定字符串Cracked &\zM$NJ'。
2、key的长度至少等于name的后半部分长度,多余的部分不参加运算,name的第17-21位不能有字符0。
3、如果name的第22位以后(包括22位)为0,那么它对应的key为任何字符都能注册成功,这可能是算法的Bug吧。
可用的一组数据:
name:Cracked &\zM$NJ'bxm78
key:a|h1?
附注册机源码:
#include<iostream.h>
#include<string.h>
void main()
{
int i,j;
char name[17],serial[17];
cout<<"Please input your name:";
cin>>name;
j=3;
for(i=0;i<strlen(name);i++)
{
serial[i]=name[i]^j;
j++;
}
serial[i]=0;
cout<<endl<<"User name:Cracked &\zM$NJ'"<<name<<endl;
cout<<"User key:"<<serial<<endl;
}
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年08月11日 下午 11:34:34
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!