菜鸟 学注册机编写之 “序列号组合”
测试环境
系统: 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)
当把学习当成一种习惯!