菜鸟 学注册机编写之 “RSA”
测试环境
系统: 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 retn
4.分析关键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)
当把学习当成一种习惯!