测试环境 系统: xp sp3
调试器 :od 1.10
RSA简单介绍
选取两个别人不知道的大素数p, q. 公共模n = p*q 欧拉值φ(n) = (p-1)(q-1) 选取公匙(加密匙) e , 条件是1< e <φ(n),且e与φ(n) 互质. 常用为3, 65537等. 根据扩展欧几里德算法求得: 私匙 d = e^-1 mod φ(n) . 加解密算法: 加密: 密文c = m^e mod n 解密: 明文 m = c^d mod n
一: 定位关键CALL
1.OD载入程序, F9运行, 点击”Register”随便输入用户名与注册码,如下图
2.点击 “暂停” 点击 “K” ,来到如下图的地方
3.点”显示调用” 往上找就能找到关键跳与关键CALL,如下 地方
1 00402830 81EC 00020000 sub esp,0x200
2 00402836 56 push esi
3 00402837 6A 01 push 0x1
4 00402839 8BF1 mov esi,ecx
5 0040283B E8 D0020900 call Apollo_3.00492B10 ; jmp 到 mfc42.#?UpdateData@CWnd@@QAEHH@Z_6334
6 00402840 8B86 34010000 mov eax,dword ptr ds:[esi+0x134] ; 注册码
7 00402846 8B8E 38010000 mov ecx,dword ptr ds:[esi+0x138] ; 用户名
8 0040284C 50 push eax
9 0040284D 51 push ecx
10 0040284E E8 2DE50000 call Apollo_3.00410D80 ; 关键Call
11 00402853 83C4 08 add esp,0x8
12 00402856 85C0 test eax,eax
13 00402858 75 1B jnz short Apollo_3.00402875 ; 关键跳
14 0040285A 6A 40 push 0x40
15 0040285C 68 B0724C00 push Apollo_3.004C72B0 ; ASCII "抱歉"
16 00402861 68 88724C00 push Apollo_3.004C7288 ; ASCII "无效的用户名或注册码"
17 00402866 8BCE mov ecx,esi
18 00402868 E8 9D020900 call Apollo_3.00492B0A ; jmp 到 mfc42.#?MessageBoxA@CWnd@@QAEHPBD0I@Z_4224
19 0040286D 5E pop esi
20 0040286E 81C4 00020000 add esp,0x200
21 00402874 C3 retn4.分析关键Call
1 00410D80 6A FF push -0x1
2 00410D82 68 095A4900 push Apollo_3.00495A09
3 00410D87 64:A1 00000000 mov eax,dword ptr fs:[0]
4 00410D8D 50 push eax
5 00410D8E 64:8925 0000000>mov dword ptr fs:[0],esp
6 00410D95 81EC 94000000 sub esp,0x94
7 00410D9B 8B8424 A4000000 mov eax,dword ptr ss:[esp+0xA4]
8 00410DA2 53 push ebx
9 00410DA3 56 push esi
10 00410DA4 50 push eax
11 00410DA5 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]
12 00410DA9 C74424 60 5F144>mov dword ptr ss:[esp+0x60],0xE14B145F ; 初始化 模n
13 00410DB1 C74424 64 86C6C>mov dword ptr ss:[esp+0x64],0xEC9C686
14 00410DB9 C74424 68 1969E>mov dword ptr ss:[esp+0x68],0x6BEF6919
15 00410DC1 C74424 6C 63CF1>mov dword ptr ss:[esp+0x6C],0xCC14CF63
16 00410DC9 C74424 70 CDB41>mov dword ptr ss:[esp+0x70],0x2D15B4CD
17 00410DD1 C74424 74 B1716>mov dword ptr ss:[esp+0x74],0xA26E71B1
18 00410DD9 C74424 78 CD44C>mov dword ptr ss:[esp+0x78],0xDDCC44CD
19 00410DE1 C74424 7C 02064>mov dword ptr ss:[esp+0x7C],0x5C4D0602
20 00410DE9 E8 B61C0800 call Apollo_3.00492AA4 ; jmp 到 mfc42.#??0CString@@QAE@PBD@Z_537
21 00410DEE 8B8C24 B0000000 mov ecx,dword ptr ss:[esp+0xB0]
22 00410DF5 C78424 A4000000>mov dword ptr ss:[esp+0xA4],0x0
23 00410E00 51 push ecx
24 00410E01 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
25 00410E05 E8 9A1C0800 call Apollo_3.00492AA4 ; jmp 到 mfc42.#??0CString@@QAE@PBD@Z_537
26 00410E0A 68 647C4C00 push Apollo_3.004C7C64 ; UNICODE " "
27 00410E0F 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]
28 00410E13 C68424 A8000000>mov byte ptr ss:[esp+0xA8],0x1
29 00410E1B E8 D81F0800 call Apollo_3.00492DF8 ; jmp 到 mfc42.#?TrimLeft@CString@@QAEXPBD@Z_6928
30 00410E20 68 647C4C00 push Apollo_3.004C7C64 ; UNICODE " "
31 00410E25 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]
32 00410E29 E8 C41F0800 call Apollo_3.00492DF2 ; jmp 到 mfc42.#?TrimRight@CString@@QAEXPBD@Z_6930
33 00410E2E 68 647C4C00 push Apollo_3.004C7C64 ; UNICODE " "
34 00410E33 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
35 00410E37 E8 BC1F0800 call Apollo_3.00492DF8 ; jmp 到 mfc42.#?TrimLeft@CString@@QAEXPBD@Z_6928
36 00410E3C 68 647C4C00 push Apollo_3.004C7C64 ; UNICODE " "
37 00410E41 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
38 00410E45 E8 A81F0800 call Apollo_3.00492DF2 ; jmp 到 mfc42.#?TrimRight@CString@@QAEXPBD@Z_6930
39 00410E4A 8B5424 0C mov edx,dword ptr ss:[esp+0xC]
40 00410E4E 8B35 68AD4900 mov esi,dword ptr ds:[0x49AD68] ; msvcrt._mbscmp
41 00410E54 68 285E4D00 push Apollo_3.004D5E28
42 00410E59 52 push edx
43 00410E5A FFD6 call esi ; 判断用户名是否为空 mbscmp
44 00410E5C 83C4 08 add esp,0x8
45 00410E5F 85C0 test eax,eax
46 00410E61 0F84 0F020000 je Apollo_3.00411076
47 00410E67 8B4424 08 mov eax,dword ptr ss:[esp+0x8]
48 00410E6B 68 285E4D00 push Apollo_3.004D5E28
49 00410E70 50 push eax
50 00410E71 FFD6 call esi ; 判断注册码是否为空
51 00410E73 83C4 08 add esp,0x8
52 00410E76 85C0 test eax,eax
53 00410E78 0F84 F8010000 je Apollo_3.00411076
54 00410E7E 57 push edi
55 00410E7F 6A 00 push 0x0
56 00410E81 8D4C24 44 lea ecx,dword ptr ss:[esp+0x44]
57 00410E85 E8 261F0000 call Apollo_3.00412DB0
58 00410E8A 6A 00 push 0x0
59 00410E8C 8D4C24 4C lea ecx,dword ptr ss:[esp+0x4C]
60 00410E90 C68424 AC000000>mov byte ptr ss:[esp+0xAC],0x2
61 00410E98 E8 131F0000 call Apollo_3.00412DB0
62 00410E9D B3 03 mov bl,0x3
63 00410E9F 68 01000100 push 0x10001 ; 公钥 e 10001
64 00410EA4 8D4C24 5C lea ecx,dword ptr ss:[esp+0x5C]
65 00410EA8 889C24 AC000000 mov byte ptr ss:[esp+0xAC],bl
66 00410EAF E8 FC1E0000 call Apollo_3.00412DB0 ; cinstr(e,"10001")初始化公钥e
67 00410EB4 8D4C24 58 lea ecx,dword ptr ss:[esp+0x58]
68 00410EB8 C68424 A8000000>mov byte ptr ss:[esp+0xA8],0x4
69 00410EC0 51 push ecx
70 00410EC1 8D4C24 4C lea ecx,dword ptr ss:[esp+0x4C]
71 00410EC5 E8 461F0000 call Apollo_3.00412E10
72 00410ECA 8D4C24 58 lea ecx,dword ptr ss:[esp+0x58]
73 00410ECE 889C24 A8000000 mov byte ptr ss:[esp+0xA8],bl
74 00410ED5 E8 861F0000 call Apollo_3.00412E60
75 00410EDA 8D5424 60 lea edx,dword ptr ss:[esp+0x60]
76 00410EDE 6A 08 push 0x8
77 00410EE0 52 push edx
78 00410EE1 8D4C24 48 lea ecx,dword ptr ss:[esp+0x48]
79 00410EE5 E8 961D0000 call Apollo_3.00412C80 ; 将模N转换成大数
80 00410EEA B9 08000000 mov ecx,0x8
81 00410EEF 33C0 xor eax,eax
82 00410EF1 8D7C24 18 lea edi,dword ptr ss:[esp+0x18]
83 00410EF5 8D5424 2C lea edx,dword ptr ss:[esp+0x2C]
84 00410EF9 F3:AB rep stos dword ptr es:[edi]
85 00410EFB 8D4424 34 lea eax,dword ptr ss:[esp+0x34]
86 00410EFF 8D4C24 30 lea ecx,dword ptr ss:[esp+0x30]
87 00410F03 50 push eax
88 00410F04 51 push ecx
89 00410F05 8D4424 30 lea eax,dword ptr ss:[esp+0x30]
90 00410F09 52 push edx
91 00410F0A 8D4C24 30 lea ecx,dword ptr ss:[esp+0x30]
92 00410F0E 50 push eax
93 00410F0F 8D5424 30 lea edx,dword ptr ss:[esp+0x30]
94 00410F13 51 push ecx
95 00410F14 8D4424 30 lea eax,dword ptr ss:[esp+0x30]
96 00410F18 52 push edx
97 00410F19 8B5424 24 mov edx,dword ptr ss:[esp+0x24]
98 00410F1D 8D4C24 30 lea ecx,dword ptr ss:[esp+0x30]
99 00410F21 50 push eax
100 00410F22 51 push ecx ; 注册码格式成16进制数据
101 00410F23 68 0C914C00 push Apollo_3.004C910C ; ASCII "%08lX-%08lX-%08lX-%08lX-%08lX-%08lX-%08lX-%08lX\n"
102 00410F28 52 push edx
103 00410F29 FF15 98AD4900 call dword ptr ds:[0x49AD98] ; msvcrt.sscanf
104 00410F2F 8B4424 50 mov eax,dword ptr ss:[esp+0x50] ; sn5
105 00410F33 8B4C24 4C mov ecx,dword ptr ss:[esp+0x4C] ; sn4
106 00410F37 8B7C24 48 mov edi,dword ptr ss:[esp+0x48] ; sn3
107 00410F3B 8B5424 44 mov edx,dword ptr ss:[esp+0x44] ; sn2
108 00410F3F 03C1 add eax,ecx ; sn5 = sn5+sn4
109 00410F41 8B4C24 5C mov ecx,dword ptr ss:[esp+0x5C] ; sn8
110 00410F45 03C7 add eax,edi ; sn5 = (sn5+sn4)+sn3
111 00410F47 8B7C24 58 mov edi,dword ptr ss:[esp+0x58] ; sn7
112 00410F4B 03C2 add eax,edx ; sn5 = (sn5+sn4+sn3)+sn2
113 00410F4D 8B5424 40 mov edx,dword ptr ss:[esp+0x40] ; sn1
114 00410F51 33C8 xor ecx,eax ; sn8 ^= (sn5+sn4+sn3+sn2)
115 00410F53 8B4424 54 mov eax,dword ptr ss:[esp+0x54] ; sn6
116 00410F57 83C4 28 add esp,0x28
117 00410F5A 03C2 add eax,edx ; sn6 = sn6+sn1
118 00410F5C 894C24 34 mov dword ptr ss:[esp+0x34],ecx ; 存放sn8 ^= (sn5+sn4+sn3+sn2)
119 00410F60 33F8 xor edi,eax ; sn7 ^= (sn6+sn1)
120 00410F62 6A 00 push 0x0
121 00410F64 8D4C24 3C lea ecx,dword ptr ss:[esp+0x3C]
122 00410F68 897C24 34 mov dword ptr ss:[esp+0x34],edi ; 存放sn7 ^= (sn6+sn1)
123 00410F6C E8 3F1E0000 call Apollo_3.00412DB0
124 00410F71 8D4C24 18 lea ecx,dword ptr ss:[esp+0x18]
125 00410F75 6A 08 push 0x8
126 00410F77 51 push ecx
127 00410F78 8D4C24 40 lea ecx,dword ptr ss:[esp+0x40]
128 00410F7C C68424 B0000000>mov byte ptr ss:[esp+0xB0],0x5
129 00410F84 E8 F71C0000 call Apollo_3.00412C80
130 00410F89 8D5424 38 lea edx,dword ptr ss:[esp+0x38]
131 00410F8D 8D4424 50 lea eax,dword ptr ss:[esp+0x50]
132 00410F91 52 push edx
133 00410F92 50 push eax
134 00410F93 8D4C24 48 lea ecx,dword ptr ss:[esp+0x48] ; 指向注册计算出来的数
135 00410F97 E8 94140000 call Apollo_3.00412430 ; powmod c= m^e mod n
136 00410F9C B9 08000000 mov ecx,0x8
137 00410FA1 33C0 xor eax,eax
138 00410FA3 8D7C24 18 lea edi,dword ptr ss:[esp+0x18]
139 00410FA7 6A 08 push 0x8
140 00410FA9 F3:AB rep stos dword ptr es:[edi] ; 清空
141 00410FAB 8D4C24 1C lea ecx,dword ptr ss:[esp+0x1C]
142 00410FAF C68424 AC000000>mov byte ptr ss:[esp+0xAC],0x6
143 00410FB7 51 push ecx
144 00410FB8 8D4C24 58 lea ecx,dword ptr ss:[esp+0x58]
145 00410FBC E8 FF1C0000 call Apollo_3.00412CC0 ; big_to_bytes
146 00410FC1 B9 08000000 mov ecx,0x8
147 00410FC6 33C0 xor eax,eax
148 00410FC8 8DBC24 80000000 lea edi,dword ptr ss:[esp+0x80]
149 00410FCF F3:AB rep stos dword ptr es:[edi]
150 00410FD1 5F pop edi
151 00410FD2 8A5404 17 mov dl,byte ptr ss:[esp+eax+0x17] ; 循环交换数据位置 4字节一组 应当是小端转大端操作
152 00410FD6 8A4C04 16 mov cl,byte ptr ss:[esp+eax+0x16]
153 00410FDA 885404 7C mov byte ptr ss:[esp+eax+0x7C],dl
154 00410FDE 8B5404 14 mov edx,dword ptr ss:[esp+eax+0x14]
155 00410FE2 884C04 7D mov byte ptr ss:[esp+eax+0x7D],cl
156 00410FE6 8A4C04 14 mov cl,byte ptr ss:[esp+eax+0x14]
157 00410FEA C1EA 08 shr edx,0x8
158 00410FED 885404 7E mov byte ptr ss:[esp+eax+0x7E],dl
159 00410FF1 884C04 7F mov byte ptr ss:[esp+eax+0x7F],cl
160 00410FF5 83C0 04 add eax,0x4
161 00410FF8 83F8 20 cmp eax,0x20
162 00410FFB ^ 7C D5 jl short Apollo_3.00410FD2 ; 判断是否结束
163 00410FFD 8D5424 7C lea edx,dword ptr ss:[esp+0x7C]
164 00411001 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]
165 00411005 52 push edx
166 00411006 E8 991A0800 call Apollo_3.00492AA4 ; jmp 到 mfc42.#??0CString@@QAE@PBD@Z_537
167 0041100B 8B4424 10 mov eax,dword ptr ss:[esp+0x10]
168 0041100F 8B4C24 0C mov ecx,dword ptr ss:[esp+0xC]
169 00411013 50 push eax
170 00411014 51 push ecx
171 00411015 FFD6 call esi ; 比较用户名是否相同
172 00411017 83C4 08 add esp,0x8
173 0041101A 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]
174 0041101E 85C0 test eax,eax
175 00411020 C68424 A4000000>mov byte ptr ss:[esp+0xA4],0x6
176 00411028 0F84 86000000 je Apollo_3.004110B4算法分析总结
以上是注册的第一步,检查是否受到用户名和注册码的输入,如果没有输入就返回 false,同时,也已经找到了 RSA 算法中的公钥 e 和模 n,可以进入下一步参与大数运算了.
我们现在可以分解N 然后得到D
如下图
注册码格式是 s0-s1-s2-s3-s4-s5-s6-s7,首先把 s6 和 s7 原先处理一下,处理的方法是: s6 = ( s0 + s5 ) ^ s6 s7 = ( s1 + s2 + s3 + s4 ) ^ s7
二:注册码机编写
1. 注册机源码
1 #include <stdio.h>
2 #include <windows.h>
3 #include "MIRACL.H"
4
5 #pragma comment(lib,"ms32.lib")
6
7 #if _DEBUG
8 #pragma comment(linker,"/NODEFAULTLIB:LIBC")
9 #endif
10
11
12 void hex_to_str(char *ptr,unsigned char *buf,int len)
13 {
14 int i=0;
15 for(i = 0; i < len; i++)
16 {
17 sprintf(ptr, "%02x",buf[i]);
18 ptr += 2;
19 }
20 }
21
22
23 void main()
24 {
25
26 miracl* mip=mirsys(500,16);
27 char szName[256]={0};
28 unsigned char hexstring[256] = {0};
29 unsigned char UserSun[256] = {0};
30 char License[256] = {0};
31 char szSerial[256] = {0};
32 int i, j;
33 big n,d,c,m;
34 long dtLength;
35 unsigned char temp[8] = {0};
36 unsigned int SN[8] = {0};
37
38 printf("------HA-Apollo3GP_362 注册码机-------\n\n");
39
40 printf("请输入用户名:");
41 scanf("%s",szName);
42
43 if (strlen(szName) > 240)
44 {
45 printf("用户名不长度不能大于240\n");
46 return;
47 }
48
49
50 //将用户名转换成10进制值并逆转
51
52 for (i =0; i<strlen(szName); i++)
53 {
54 UserSun[i] = toascii(szName[i]);
55 }
56
57 //交换位置
58 j =0;
59 for (; i>4; i-=4)
60 {
61
62 strncpy(temp, UserSun+j, 4);
63 strncpy(UserSun+j, UserSun+i-4, 4);
64 strncpy(UserSun+i-4,temp, 4);
65 j+=4;
66 }
67
68
69 hex_to_str(hexstring, UserSun, strlen(UserSun));
70
71 dtLength = strlen(hexstring);
72 mip->IOBASE=16; // 16进制模式
73 c=mirvar(0); // MIRACL的大数类型
74 n=mirvar(0);
75 d=mirvar(0);
76 m=mirvar(0);
77
78 cinstr(c,hexstring); // 将用户名转换成大数
79 cinstr(n,"5C4D0602DDCC44CDA26E71B12D15B4CDCC14CF636BEF69190EC9C686E14B145F"); // 初始化模数n
80 cinstr(d,"D32AA4860A4A3B5EFA2F138CF648A2CB1C889773DFD90D95AC93B6D76E08FB9"); // 初始化私钥d
81 powmod(c,d,n,m); // 计算m = (c ^ d) mod n
82 cotstr(m,szSerial);
83
84 //组合注册码
85 //SN7 = SN7 ^ (sn6+sn1)
86 //SN8 = SN8 ^ (sn5+sn4+sn3+sn2)
87
88 //-每4字节进行计算
89 memset(UserSun, 0, strlen(UserSun));
90 j = 0;
91
92 //逆序组合注册码格式
93 for (i = strlen(szSerial); i>0; i -= 8)
94 {
95 strncpy(UserSun+j, szSerial+i-8, 8);
96
97 if (i !=8)
98 {
99 strcat(UserSun,"-");
100 }
101
102
103 j += 9;
104 }
105
106
107 //--格式化成16进制数据 dword值
108
109 j = 0;
110 for (i=0; i<strlen(UserSun)-8; i+=8)
111 {
112 sscanf(UserSun+i+j, "%08lX", SN+j);
113 j += 1;
114 }
115
116 //SN7 = SN7 ^ SN1+ SN6;
117 //SN8 = SN8 ^ (sn5+sn4+sn3+sn2)
118 SN[7-1] = SN[7-1] ^ (SN[1-1]+SN[6-1]);
119 SN[8-1] = SN[8-1] ^ (SN[5-1]+SN[4-1]+SN[3-1]+SN[2-1]);
120
121
122 //-将16进制转换成字符串
123
124 //-生成最终注册码
125 j=0;
126 for (i=0; i<8; i++)
127 {
128 sprintf(License+j, "%08X", SN[i]);
129 if (i != 7)
130 {
131 strcat(License, "-");
132 }
133
134 j+=9;
135 }
136
137 printf("注册码: %s\n",License);
138 system("pause");
139
140 }2. 测试注册机
输入用户名test
成功注册
完。
样本及注册机源码下载
http://yunpan.cn/cAqLfTSHxYBvX (提取码:3855)