测试环境 系统: xp sp3
调试器 :od 1.10
一: 定位关键CALL
1.OD载入程序, F9运行, 点击”Register”随便输入用户名与注册码,如下图:
2.点击 “暂停” 点击 “K” ,来到如下图的地方
3.选择”MessageBoxA” 右键 “显示调用”,来到如下图的地方
4.往上找就能找到关键跳与关键CALL,如下图
5.在关键CALL下好断点后重新载入OD, F9运行,随便输入用户名与注册码,接着就是分析算法了
二:算法分析
1.F7跟进关键Call
将用户名与一个固定字符串组后,然后生成两个字符串
1 004704B0 /$ 55 push ebp
2 004704B1 |. 8BEC mov ebp,esp
3 004704B3 |. 6A 00 push 0x0
4 004704B5 |. 6A 00 push 0x0
5 004704B7 |. 6A 00 push 0x0
6 004704B9 |. 6A 00 push 0x0
7 004704BB |. 6A 00 push 0x0
8 004704BD |. 6A 00 push 0x0
9 004704BF |. 6A 00 push 0x0
10 004704C1 |. 6A 00 push 0x0
11 004704C3 |. 53 push ebx
12 004704C4 |. 56 push esi
13 004704C5 |. 57 push edi
14 004704C6 |. 8BD9 mov ebx,ecx
15 004704C8 |. 8955 FC mov [local.1],edx
16 004704CB |. 8BF8 mov edi,eax
17 004704CD |. 8B45 FC mov eax,[local.1]
18 004704D0 |. E8 FB47F9FF call FlashSli.00404CD0
19 004704D5 |. 33C0 xor eax,eax
20 004704D7 |. 55 push ebp
21 004704D8 |. 68 0B064700 push FlashSli.0047060B
22 004704DD |. 64:FF30 push dword ptr fs:[eax]
23 004704E0 |. 64:8920 mov dword ptr fs:[eax],esp
24 004704E3 |. 8D45 FC lea eax,[local.1]
25 004704E6 |. BA 24064700 mov edx,FlashSli.00470624 ; I1Fa$Mdf8
26 004704EB |. E8 0046F9FF call FlashSli.00404AF0 ; 用户与固定字符连接
27 004704F0 |. 8B45 FC mov eax,[local.1]
28 004704F3 |. E8 F045F9FF call FlashSli.00404AE8 ; ----长度
29 004704F8 |. 8BF0 mov esi,eax
30 004704FA |. D1FE sar esi,1 ; 计算要分取字符串的长度 算术右移
31 004704FC |. 79 03 jns short FlashSli.00470501
32 004704FE |. 83D6 00 adc esi,0x0
33 00470501 |> 8D45 F0 lea eax,[local.4]
34 00470504 |. 50 push eax
35 00470505 |. 8BCE mov ecx,esi
36 00470507 |. BA 01000000 mov edx,0x1
37 0047050C |. 8B45 FC mov eax,[local.1]
38 0047050F |. E8 2C48F9FF call FlashSli.00404D40 ; 分取上面计算长度的字符串
39 00470514 |. 8B45 F0 mov eax,[local.4]
40 00470517 |. 50 push eax
41 00470518 |. 8D45 EC lea eax,[local.5]
42 0047051B |. 50 push eax
43 0047051C |. 8B45 FC mov eax,[local.1]
44 0047051F |. E8 C445F9FF call FlashSli.00404AE8 ; 长度
45 00470524 |. 8BC8 mov ecx,eax ; 总字符串长度
46 00470526 |. 8D56 01 lea edx,dword ptr ds:[esi+0x1] ; 要取字符串开始地址
47 00470529 |. 8B45 FC mov eax,[local.1]
48 0047052C |. E8 0F48F9FF call FlashSli.00404D40 ; 取字符串
49 00470531 |. 8B55 EC mov edx,[local.5]
50 00470534 |. 8D45 FC lea eax,[local.1]
51 00470537 |. 59 pop ecx
52 00470538 |. E8 F745F9FF call FlashSli.00404B34 ; ---交换字符串
53 0047053D |. 8D45 F8 lea eax,[local.2]
54 00470540 |. 50 push eax
55 00470541 |. B9 0A000000 mov ecx,0xA ; 要取的长度
56 00470546 |. BA 01000000 mov edx,0x1
57 0047054B |. 8B45 FC mov eax,[local.1]
58 0047054E |. E8 ED47F9FF call FlashSli.00404D40 ; ---取交换组合后的字符
59 00470553 |. 8D45 F4 lea eax,[local.3]
60 00470556 |. 50 push eax
61 00470557 |. 8B45 FC mov eax,[local.1]
62 0047055A |. E8 8945F9FF call FlashSli.00404AE8 ; 交换后字符串长度
63 0047055F |. 8BC8 mov ecx,eax ; 要取的度长
64 00470561 |. BA 06000000 mov edx,0x6 ; 从第6个字符开始取
65 00470566 |. 8B45 FC mov eax,[local.1]
66 00470569 |. E8 D247F9FF call FlashSli.00404D40 ; --取交换组合后的字符
67 0047056E |. 837D F4 00 cmp [local.3],0x0
68 00470572 |. 75 10 jnz short FlashSli.00470584
69 00470574 |. 8D45 F4 lea eax,[local.3]
70 00470577 |. BA 24064700 mov edx,FlashSli.00470624 ; I1Fa$Mdf8
71 0047057C |. 8B4D F8 mov ecx,[local.2]
72 0047057F |. E8 B045F9FF call FlashSli.00404B34
2.将上面生成的两个字符串传入函数进行计算
1 0046FB94 /$ 55 push ebp
2 0046FB95 |. 8BEC mov ebp,esp
3 0046FB97 |. 83C4 E0 add esp,-0x20
4 0046FB9A |. 53 push ebx
5 0046FB9B |. 56 push esi
6 0046FB9C |. 57 push edi
7 0046FB9D |. 33DB xor ebx,ebx
8 0046FB9F |. 895D E0 mov [local.8],ebx
9 0046FBA2 |. 895D F0 mov [local.4],ebx
10 0046FBA5 |. 894D F8 mov [local.2],ecx
11 0046FBA8 |. 8955 FC mov [local.1],edx
12 0046FBAB |. 8B45 FC mov eax,[local.1]
13 0046FBAE |. E8 1D51F9FF call FlashSli.00404CD0
14 0046FBB3 |. 8B45 F8 mov eax,[local.2]
15 0046FBB6 |. E8 1551F9FF call FlashSli.00404CD0
16 0046FBBB |. 33C0 xor eax,eax
17 0046FBBD |. 55 push ebp
18 0046FBBE |. 68 B0FC4600 push FlashSli.0046FCB0
19 0046FBC3 |. 64:FF30 push dword ptr fs:[eax]
20 0046FBC6 |. 64:8920 mov dword ptr fs:[eax],esp
21 0046FBC9 |. 8B45 F8 mov eax,[local.2]
22 0046FBCC |. E8 174FF9FF call FlashSli.00404AE8 ; 长度 后一次取的字符串
23 0046FBD1 |. 8945 F4 mov [local.3],eax
24 0046FBD4 |. 837D F4 00 cmp [local.3],0x0
25 0046FBD8 |. 75 0D jnz short FlashSli.0046FBE7
26 0046FBDA |. 8D45 F8 lea eax,[local.2]
27 0046FBDD |. BA C8FC4600 mov edx,FlashSli.0046FCC8 ; Think Space
28 0046FBE2 |. E8 E14CF9FF call FlashSli.004048C8
29 0046FBE7 |> 33F6 xor esi,esi
30 0046FBE9 |. BB 00010000 mov ebx,0x100 ; 初始化0x100
31 0046FBEE |. 8D45 F0 lea eax,[local.4]
32 0046FBF1 |. 50 push eax ; /Arg1
33 0046FBF2 |. C745 E4 00010>mov [local.7],0x100 ; |
34 0046FBF9 |. C645 E8 00 mov byte ptr ss:[ebp-0x18],0x0 ; |
35 0046FBFD |. 8D55 E4 lea edx,[local.7] ; |
36 0046FC00 |. 33C9 xor ecx,ecx ; |
37 0046FC02 |. B8 DCFC4600 mov eax,FlashSli.0046FCDC ; |%1.2x
38 0046FC07 |. E8 E0AAF9FF call FlashSli.0040A6EC ; \格式化成字符串
39 0046FC0C |. 8B45 FC mov eax,[local.1]
40 0046FC0F |. E8 D44EF9FF call FlashSli.00404AE8 ; 长度 第一次取的字符
41 0046FC14 |. 8BF8 mov edi,eax
42 0046FC16 |. 85FF test edi,edi
43 0046FC18 |. 7E 60 jle short FlashSli.0046FC7A ; 循环取余
44 0046FC1A |. C745 EC 01000>mov [local.5],0x1 ; 索引
45 0046FC21 |> 8B45 FC /mov eax,[local.1] ; 字符串地址
46 0046FC24 |. 8B55 EC |mov edx,[local.5] ; 索引
47 0046FC27 |. 0FB64410 FF |movzx eax,byte ptr ds:[eax+edx-0x1] ; 取第一次取的字符串1字节
48 0046FC2C |. 03C3 |add eax,ebx ; 相加
49 0046FC2E |. B9 FF000000 |mov ecx,0xFF
50 0046FC33 |. 99 |cdq
51 0046FC34 |. F7F9 |idiv ecx ; 取余
52 0046FC36 |. 8BDA |mov ebx,edx ; 取余后的值存放在ebx
53 0046FC38 |. 3B75 F4 |cmp esi,[local.3] ; 比较字符长度
54 0046FC3B |. 7D 03 |jge short FlashSli.0046FC40
55 0046FC3D |. 46 |inc esi ; 索引加1
56 0046FC3E |. EB 05 |jmp short FlashSli.0046FC45
57 0046FC40 |> BE 01000000 |mov esi,0x1 ; 索引
58 0046FC45 |> 8B45 F8 |mov eax,[local.2] ; 字符串地址
59 0046FC48 |. 0FB64430 FF |movzx eax,byte ptr ds:[eax+esi-0x1] ; 取第二次取的字符串1字节
60 0046FC4D |. 33D8 |xor ebx,eax ; 与上个字符取余后的值xor
61 0046FC4F |. 8D45 E0 |lea eax,[local.8]
62 0046FC52 |. 50 |push eax ; /Arg1
63 0046FC53 |. 895D E4 |mov [local.7],ebx ; |
64 0046FC56 |. C645 E8 00 |mov byte ptr ss:[ebp-0x18],0x0 ; |
65 0046FC5A |. 8D55 E4 |lea edx,[local.7] ; |
66 0046FC5D |. 33C9 |xor ecx,ecx ; |
67 0046FC5F |. B8 DCFC4600 |mov eax,FlashSli.0046FCDC ; |%1.2x
68 0046FC64 |. E8 83AAF9FF |call FlashSli.0040A6EC ; \格式化成字符串
69 0046FC69 |. 8B55 E0 |mov edx,[local.8]
70 0046FC6C |. 8D45 F0 |lea eax,[local.4]
71 0046FC6F |. E8 7C4EF9FF |call FlashSli.00404AF0 ; 存放字符串 eax指向字符串地址
72 0046FC74 |. FF45 EC |inc [local.5] ; 索引加1
73 0046FC77 |. 4F |dec edi ; 第一次字符长度
74 0046FC78 |.^ 75 A7 \jnz short FlashSli.0046FC21 ; 判断是否结束
75 0046FC7A |> 8B45 08 mov eax,[arg.1]
76 0046FC7D |. 8B55 F0 mov edx,[local.4]
77 0046FC80 |. E8 FF4BF9FF call FlashSli.00404884
78 0046FC85 |. 33C0 xor eax,eax
79 0046FC87 |. 5A pop edx
80 0046FC88 |. 59 pop ecx
81 0046FC89 |. 59 pop ecx
82 0046FC8A |. 64:8910 mov dword ptr fs:[eax],edx
83 0046FC8D |. 68 B7FC4600 push FlashSli.0046FCB7
84 0046FC92 |> 8D45 E0 lea eax,[local.8]
85 0046FC95 |. E8 964BF9FF call FlashSli.00404830
86 0046FC9A |. 8D45 F0 lea eax,[local.4]
87 0046FC9D |. E8 8E4BF9FF call FlashSli.00404830
88 0046FCA2 |. 8D45 F8 lea eax,[local.2]
89 0046FCA5 |. BA 02000000 mov edx,0x2
90 0046FCAA |. E8 A54BF9FF call FlashSli.00404854
91 0046FCAF \. C3 retn
3.计算完成后得到一串字符串 0x17长度,取该字符串每5位加上字符’-’做为注册码
1 00470592 |. 8D45 E8 lea eax,[local.6]
2 00470595 |. 50 push eax
3 00470596 |. 8B03 mov eax,dword ptr ds:[ebx]
4 00470598 |. B9 05000000 mov ecx,0x5 ; 要取的长度
5 0047059D |. BA 01000000 mov edx,0x1 ; 从第一个字节
6 004705A2 |. E8 9947F9FF call FlashSli.00404D40 ; ---取字符串
7 004705A7 |. FF75 E8 push [local.6]
8 004705AA |. 68 38064700 push FlashSli.00470638 ; -
9 004705AF |. 8D45 E4 lea eax,[local.7]
10 004705B2 |. 50 push eax
11 004705B3 |. 8B03 mov eax,dword ptr ds:[ebx]
12 004705B5 |. B9 05000000 mov ecx,0x5 ; 要取的长度
13 004705BA |. BA 06000000 mov edx,0x6 ; 从第6个字节
14 004705BF |. E8 7C47F9FF call FlashSli.00404D40 ; 取字符串
15 004705C4 |. FF75 E4 push [local.7]
16 004705C7 |. 68 38064700 push FlashSli.00470638 ; -
17 004705CC |. 8D45 E0 lea eax,[local.8]
18 004705CF |. 50 push eax
19 004705D0 |. 8B03 mov eax,dword ptr ds:[ebx]
20 004705D2 |. B9 05000000 mov ecx,0x5 ; 要取的长度
21 004705D7 |. BA 0B000000 mov edx,0xB ; 从0xB开始取
22 004705DC |. E8 5F47F9FF call FlashSli.00404D40 ; 取字符串
23 004705E1 |. FF75 E0 push [local.8]
24 004705E4 |. 8BC3 mov eax,ebx
25 004705E6 |. BA 05000000 mov edx,0x5
26 004705EB |. E8 B845F9FF call FlashSli.00404BA8
27 004705F0 |. 33C0 xor eax,eax
28 004705F2 |. 5A pop edx
29 004705F3 |. 59 pop ecx
30 004705F4 |. 59 pop ecx
31 004705F5 |. 64:8910 mov dword ptr fs:[eax],edx
32 004705F8 |. 68 12064700 push FlashSli.00470612
33 004705FD |> 8D45 E0 lea eax,[local.8]
34 00470600 |. BA 08000000 mov edx,0x8
35 00470605 |. E8 4A42F9FF call FlashSli.00404854
36 0047060A \. C3 retn
4.比较注册码
1 00470387 |. E8 C48DF9FF call FlashSli.00409150 ; strcmp 比较注册码,不同返回1
2
3 0047038C |. 85C0 test eax,eax
4
5 0047038E |. 75 41 jnz short FlashSli.004703D1
分析总结
A. 获得用户名并与固定字符串连接
B. 将连接后字符串长度算术右移1位得到一个长度
C. 取连接后字符串(长度为上面右移后的长度)
D. 甚下的字符串与上面取的字符做前后交换
E. 取交换后字符(0xA长度)
F. 甚下的字符与上面取得的字符传入一个函数时行计算
G. 计算后得到一串字符,取其中值做注册码
5.算法分析清楚了就开始 注册机编写
1 #include <stdio.h>
2 #include <windows.h>
3 #include <string.h>
4
5 //与用户名连接的固定字符串
6 char *ConstStrig = "I1Fa$Mdf8";
7 char License[256] = {0};
8 char UserSun[256] = {0};
9
10 //-算法,将用户名组合后计算得到一串字符
11 void Algorithm(char* UserAgo, char* UserBack)
12 {
13
14 int UserBackLen = 0;
15 int UserAgoLen = 0;
16
17 unsigned int initVal = 0x100;
18 char strtemp[4] = {0};
19
20
21 if (NULL == UserAgo || NULL == UserBack)
22 {
23 return;
24 }
25
26 UserBackLen = strlen(UserBack);
27 if (0 == UserBackLen)
28 {
29 return;
30 }
31 UserAgoLen = strlen(UserAgo);
32 if (0 == UserAgoLen)
33 {
34 return;
35 }
36
37 //--格式化成字符串
38 sprintf(UserSun, "%02X",initVal);
39
40
41 for (int i=0; i<UserAgoLen; i++)
42 {
43
44 unsigned int N = 0XFF;
45 unsigned int Val_A = UserAgo[i];
46 initVal += Val_A;
47
48 //取余
49 initVal %= N;
50
51 unsigned int Val_B = UserBack[i];
52
53 initVal ^= Val_B;
54 sprintf(UserSun+3+i*2, "%02X", initVal);
55
56
57 }
58
59 }
60
61 int main()
62 {
63
64 char UserName[256] = {0};
65 char License[256] = {0};
66 int len = 0;
67
68 printf("----------------AliveFlashSlideshowMaker 注册机----------\n");
69 printf("请输入用户名:");
70 scanf("%s",UserName);
71 if ( strlen(UserName) > 200)
72 {
73 printf("用户名不能超过200位\n");
74 return -1;
75 }
76
77 //连接用户名
78 strcat(UserName,ConstStrig);
79
80 len = strlen(UserName);
81 if (0 == len)
82 {
83 return -1;
84 }
85
86 //长度算术右移1位
87 len >>= 1;
88
89 char strtempuser[256] = {0};
90 char strtempuser1[256] = {0};
91
92 //将组合好的字符分成两个字符
93 strncpy(strtempuser, UserName, len);
94 strncpy(strtempuser1, UserName+len, strlen(UserName)-len);
95
96 //-重新组合交换字符
97 memset(UserName, 0, strlen(UserName));
98 strncpy(UserName, strtempuser1, strlen(strtempuser1));
99 strcat(UserName, strtempuser);
100
101 //取交换后字符前0xA位
102 memset(strtempuser, 0, strlen(strtempuser));
103 memset(strtempuser1, 0 ,strlen(strtempuser1));
104 strncpy(strtempuser, UserName, 0xA);
105 strncpy(strtempuser1, UserName+5, strlen(UserName)-5);
106
107 Algorithm(strtempuser, strtempuser1);
108
109 //--生成注册码
110 strncpy(License, UserSun, 5);
111 strncpy(License+strlen(License), "-", 1);
112 strncpy(License+strlen(License), UserSun+5, 5);
113 strncpy(License+strlen(License), "-", 1);
114 strncpy(License+strlen(License), UserSun+10, 5);
115
116
117 printf("注册码为:%s\n",License);
118 system("pause");
119 return 0;
120 }
6.测试注册机
输入用户名test
输入生成的注册码,注册成功
完成。
样本及注册机下载
http://yunpan.cn/cA3rINnem5cRn (提取码:5b95)