【文章标题】: 简单的CrackMe的算法分析
【文章作者】: bxm
【作者邮箱】: bxm78@163.com
【软件名称】: Duelist's Crackme #4
【保护方式】: name,code
【编写语言】: MASM32 / TASM32 [覆盖]
【使用工具】: OD
【操作平台】: xinxp
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
通过简单的跟踪,发现name最好为字母,如果输入]将出现错误,应该是软件设计的原因,不能出现数字,好,下断点MessageBoxA可以很容易断下来,输入
name:bxm
code:780
00401127 > /6A 00 push 0 ; /lParam = 0
00401129 . |6A 00 push 0 ; |wParam = 0
0040112B . |6A 0E push 0E ; |Message = WM_GETTEXTLENGTH
0040112D . |6A 03 push 3 ; |ControlID = 3
0040112F . |FF75 08 push dword ptr [ebp+8] ; |hWnd
00401132 . |E8 41020000 call <jmp.&USER32.SendDlgItem>; \SendDlgItemMessageA
00401137 . |A3 AF214000 mov [4021AF], eax ; EAX为name长度
0040113C . |83F8 00 cmp eax, 0 ; EAX=0 ?
0040113F . |0F84 D5000000 je 0040121A ; 是,完蛋
00401145 . |83F8 08 cmp eax, 8 ; EAX>8 ?
00401148 . |0F8F CC000000 jg 0040121A ; 是,完蛋
0040114E . |8BF0 mov esi, eax ; name长度入ESI
00401150 . |6A 00 push 0 ; /lParam = 0
00401152 . |6A 00 push 0 ; |wParam = 0
00401154 . |6A 0E push 0E ; |Message = WM_GETTEXTLENGTH
00401156 . |6A 04 push 4 ; |ControlID = 4
00401158 . |FF75 08 push dword ptr [ebp+8] ; |hWnd
0040115B . |E8 18020000 call <jmp.&USER32.SendDlgItem>; \SendDlgItemMessageA
00401160 . |83F8 00 cmp eax, 0 ; EAX为code长度
00401163 . |0F84 B1000000 je 0040121A ; EAX为0,跳向结束
00401169 . |3BF0 cmp esi, eax ; name长度=code长度 ?
0040116B . |0F85 A9000000 jnz 0040121A ; 不是,完蛋
00401171 . |68 60214000 push 00402160 ; /lParam = 402160
00401176 . |6A 08 push 8 ; |wParam = 8
00401178 . |6A 0D push 0D ; |Message = WM_GETTEXT
0040117A . |6A 03 push 3 ; |ControlID = 3
0040117C . |FF75 08 push dword ptr [ebp+8] ; |hWnd
0040117F . |E8 F4010000 call <jmp.&USER32.SendDlgItem>; \SendDlgItemMessageA
00401184 . |68 79214000 push 00402179 ; /lParam = 402179
00401189 . |6A 10 push 10 ; |wParam = 10
0040118B . |6A 0D push 0D ; |Message = WM_GETTEXT
0040118D . |6A 04 push 4 ; |ControlID = 4
0040118F . |FF75 08 push dword ptr [ebp+8] ; |hWnd
00401192 . |E8 E1010000 call <jmp.&USER32.SendDlgItem>; \SendDlgItemMessageA
00401197 . |B9 FFFFFFFF mov ecx, -1
0040119C > |41 inc ecx ; ECX作为name的字符计数器
0040119D . |0FBE81 602140>movsx eax, byte ptr [ecx+40216>; EAX依次读入name的每个字符
004011A4 . |83F8 00 cmp eax, 0 ; Switch (cases 0..7A)
004011A7 . |74 32 je short 004011DB ; 读完了,跳
004011A9 . |BE FFFFFFFF mov esi, -1 ; ESI作为表1的计数器
004011AE . |83F8 41 cmp eax, 41 ; EAX<41H ?
004011B1 . |7C 67 jl short 0040121A ; 是,跳向失败
004011B3 . |83F8 7A cmp eax, 7A ; EAX>=7AH ?
004011B6 . |77 62 ja short 0040121A ; 是,跳向失败
004011B8 . |83F8 5A cmp eax, 5A ; EAX<5AH ?
004011BB . |7C 03 jl short 004011C0 ; 是,跳
004011BD . |83E8 20 sub eax, 20 ; EAX-20H; Cases 5A ('Z'),5B ('['),5C ('\'),5D (']'),5E ('^'),5F ('_'),60 ('`'),61 ('a'),62 ('b'),63 ('c'),64 ('d'),65 ('e'),66 ('f'),67 ('g'),68 ('h'),69 ('i'),6A ('j'),6B ('k'),6C ('l'),6D ('m')... of switch 004011A4
004011C0 > |46 inc esi ; Cases 41 ('A'),42 ('B'),43 ('C'),44 ('D'),45 ('E'),46 ('F'),47 ('G'),48 ('H'),49 ('I'),4A ('J'),4B ('K'),4C ('L'),4D ('M'),4E ('N'),4F ('O'),50 ('P'),51 ('Q'),52 ('R'),53 ('S'),54 ('T')... of switch 004011A4
004011C1 . |0FBE96 172040>movsx edx, byte ptr [esi+40201>; 读表1
004011C8 . |3BC2 cmp eax, edx ; name转换后的字符与表1中的字符比较
004011CA .^|75 F4 jnz short 004011C0 ; 不相等,继续读表
004011CC . |0FBE86 3C2040>movsx eax, byte ptr [esi+40203>; 根据ESI的值读表2
004011D3 . |8981 94214000 mov [ecx+402194], eax ; EAX存于内存单元
004011D9 .^|EB C1 jmp short 0040119C
004011DB > |FF35 AF214000 push dword ptr [4021AF] ; /CODE长度; Case 0 of switch 004011A4
004011E1 . |68 94214000 push 00402194 ; |真CODE
004011E6 . |68 79214000 push 00402179 ; |假CODE
004011EB . |E8 54000000 call 00401244 ; \due-cm4.00401244
004011F0 . |83F8 01 cmp eax, 1 ; 返回值为1表示成功
004011F3 .^|0F84 DEFEFFFF je 004010D7 ; 跳向成功地址
004011F9 . |EB 1F jmp short 0040121A
004011FB > |837D 10 01 cmp dword ptr [ebp+10], 1 ; |
004011FF .^\0F84 22FFFFFF je 00401127 ; |
00401205 . 837D 10 02 cmp dword ptr [ebp+10], 2 ; |
00401209 . 75 2F jnz short 0040123A ; |
0040120B > E8 B4000000 call <jmp.&KERNEL32.ExitProce>; \ExitProcess
00401210 . B8 01000000 mov eax, 1
00401215 .^ E9 FFFEFFFF jmp 00401119
0040121A > 68 00200000 push 2000 ; /Style = MB_OK|MB_TASKMODAL; Default case of switch 004011A4
0040121F . 68 01204000 push 00402001 ; |Title = "Duelist's Crackme #4"
00401224 . 68 AE204000 push 004020AE ; |Text = "Your registration info is invalid... Note that most of the special chars may raise registration problems!"
00401229 . 6A 00 push 0 ; |hOwner = NULL
0040122B . E8 36010000 call <jmp.&USER32.MessageBoxA>; \MessageBoxA
算法小结:
1、name长度为1――8位,code长度与其相等。
2、把name的每个字符转换成小大写字母。
3、name的每个字符在表1中的位置,记为A。
4、根据A的值查表2,得到的即为注册码。
可用的注册码
name:bxm
code:487
附注册机:
#include<iostream.h>
#include <string.h>
void main()
{
char name[9],code[9];
char table1[34]={
0x41, 0x31, 0x4C, 0x53, 0x4B, 0x32, 0x44, 0x4A, 0x46, 0x34, 0x48, 0x47, 0x50, 0x33, 0x51, 0x57,
0x4F, 0x35, 0x45, 0x49, 0x52, 0x36, 0x55, 0x54, 0x59, 0x5A, 0x38, 0x4D, 0x58, 0x4E, 0x37, 0x43,
0x42, 0x56};
char table2[34]={
0x53, 0x55, 0x37, 0x43, 0x53, 0x4A, 0x4B, 0x46, 0x30, 0x39, 0x4E, 0x43, 0x53, 0x44, 0x4F, 0x39,
0x53, 0x44, 0x46, 0x30, 0x39, 0x53, 0x44, 0x52, 0x4C, 0x56, 0x4B, 0x37, 0x38, 0x30, 0x39, 0x53,
0x34, 0x4E};
int i,j;
cout<<"Please input name(1-8bit):\n";
cin>>name;
for(i=0;i<strlen(name);i++)
{
if(name[i]>0x5A)name[i]-=0x20;
j=0;
while(name[i]!=table1[j])j++;
code[i]=table2[j];
}
code[i]=0;
cout<<endl<<"Code is "<<code<<endl;
}
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年08月01日 下午 05:37:27
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!