本帖最后由 qazwsxlty 于 2016-9-13 16:14 编辑
本人是小白,写注册机的方式可能和各位大神不同,勿喷。。。
破解的程序制作公司为”海贝益友“,是一款计算机二级Office练习软件(C语言、VFP、ACCESS除了字典都是一样的),但是不能评分,下次换一个能评分的。
以下是过程:(图片、代码再次修复)
1.先用Reflector打开程序文件. 2.很简单地找到了注册码段,软件没有进行混淆,所以加密的代码全部都暴露出来了. 3.分析代码,发现验证过程是这样的: 3.1.一开始,有机器码(s1); 3.2.然后用户输入了一个注册码(s2); 3.3.接下来,程序从注册码取第1,3,5,7,9…位,从机器码取第2,4,6,8,10…位,放到相应的位置组合成一个新的字符串(s3); 3.4.取s3的第1,2位,将这两位的字符ASCII码相加,对36取余得到一个数(num1),在上方的数组(字典)中找到num1位置的对应的字符(注意:数组的下表是从0开始的,如果num1等于1,则是第二个字符),将这个字符保存到新字符串(s4)的第2位;
3.5.取s3的第2,3位,重复上一步,保存到s4的第3位……取s3的第19,20位,重复上一步,保存到s4的第20位;
3.6.将s2的第1位保存到s4的第一位;
3.7.对比s2和s4,如果全部一样,就注册成功; 4.既然知道了是如何验证的,那么考虑要如何推出注册码. 4.1.倒推出注册码貌似是不可能的,而且注册码应该不唯一.
4.2.那就来暴力:枚举出所有的可能性,然后取验证是否正确.
4.2.1.但是,如果直接枚举20位注册码,最坏的情况是20!,351928天… 4.2.2.所以考虑一位一位来,先随机取第1位,然后枚举第2位,在字典中查出第2位,得出s4的第2位,和注册码第2位对比,如果相同,继续枚举第3位,不同则继续枚举第2位或第1位.
4.2.3.具体的实现方法,就是DFS. 5.开写.(更新一下完整代码好了) [C++] 纯文本查看 复制代码 #include <set>
#include <map>
#include <list>
#include <cmath>
#include <stack>
#include <queue>
#include <ctime>
#include <string>
#include <cstdio>
#include <vector>
#include <cctype>
#include <climits>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
#define ms(a) memset(a,0,sizeof(a))
typedef long long ll;
const int INF = INT_MAX;
const int MAXN = 1000 + 10;
using namespace std;
bool flag = 0;
char chArray[]
{
'L', 'U', '3', 'A', 'R', '4', 'K', '5', 'F', '6', 'M', '7', 'Y', '8', 'W', '9',
'B', 'D', 'E', 'H', 'I', 'N', 'P', 'Q', 'S', 'T', 'V', 'X', 'Z', 'J', '0', 'O',
'G', '1', 'C', '2'
};
char PrivatePWD[30] = { '0' };
char UserPublicPWD[30];
int main()
{
srand(time(0));
while (cin >> UserPublicPWD)
{
for (int i = 0; i < 24; i++)
{
if (!(i % 2))PrivatePWD[i] = chArray[rand() % 36];//加上随机数生成的比较好看
else PrivatePWD[i] = chArray[(PrivatePWD[i - 1] + UserPublicPWD[i]) % 36];
}
cout << PrivatePWD << endl;
}
return 0;
} 6.注册成功 PS:程序更新后,只是更换了字典.
|