一、原理分析
通过分析VMProtect凭证管理的配置过程、测试各项配置的实际效果,可以推断凭证管理的基本原理如下:
1、利用RSA算法生成一个公私钥对;
2、将公钥写入到加壳后的可执行文件,用于解密注册码;
3、根据用户的配置,将客户名称、E-Mail、硬件码、截止日期、运行时间限制、最终创建日期、使用者信息、被屏蔽注册码中选中的字段用私钥加密后写入到加壳后的可执行文件;
4、加壳后的可执行文件运行时,获取用户提供的注册码,然后用保存在自身内部的公钥对其进行解密,解密之后对各类限制条件(各类限制条件的含义如下表)进行判断,如果不符合就拒绝运行。
字段 | 含义 | 说明 |
客户名称 | 用户名 | 提示信息,无限制作用 |
E-Mail | 用户的邮箱地址 | 提示信息,无限制作用 |
硬件码 | 根据MAC、CPU、BIOS等信息计算得到的计算机的唯一标示 | 限制软件只能在指定的机器上运行 |
截止日期 | 软件可以运行的截止日期 | 限制软件只能在指定日期之前运行 |
运行时间限制 | 软件启动可以运行的时间(单位分钟) | 限制软件每次的运行时间 |
最终创建日期 | 允许运行的最晚编译时间 | 常用于限制更新服务,比如此日期设置为2016-1-1,那么对于2016-1-1之后编译的软件,注册码将无效 |
使用者信息 | 自定义的一些信息 | 用法暂不知 |
被屏蔽注册码 | 被屏蔽的注册码将无效 | 黑名单,但这个黑名单应该没有通过网络进行远程验证。因此对于此注册码尚未被拉黑的软件版本是起不到限制作用的 |
二、用法
1、在代码中使用凭证管理功能
代码如下,假设编译得到程序为test.exe
#include<windows.h>
#include"VMProtectSDK.h"
#pragmacomment(lib, "VMProtectSDK32.lib")
voidprint_state(INT state)
{
if (state& SERIAL_STATE_FLAG_CORRUPTED)
{
MessageBox(NULL,"许可文件损坏", "错误", 0);
}
else if(state & SERIAL_STATE_FLAG_INVALID)
{
MessageBox(NULL,"许可文件无效", "错误", 0);
}
else if(state & SERIAL_STATE_FLAG_BLACKLISTED)
{
MessageBox(NULL,"许可文件被列入黑名单", "错误", 0);
}
else if(state & SERIAL_STATE_FLAG_DATE_EXPIRED)
{
MessageBox(NULL,"许可文件过期", "错误", 0);
}
else if(state & SERIAL_STATE_FLAG_RUNNING_TIME_OVER)
{
MessageBox(NULL,"许可文件时限到", "错误", 0);
}
else if(state & SERIAL_STATE_FLAG_BAD_HWID)
{
MessageBox(NULL,"硬件ID不符","错误", 0);
}
else if(state & SERIAL_STATE_FLAG_MAX_BUILD_EXPIRED)
{
MessageBox(NULL,"版本过期", "错误", 0);
}
}
char*read_serial(const char *fname)
{
FILE *f =fopen(fname, "rb");
if (NULL== f) return NULL;
fseek(f,0, SEEK_END);
int s =ftell(f);
fseek(f,0, SEEK_SET);
char *buf= new char[s + 1];
fread(buf,s, 1, f);
buf[s] =0;
fclose(f);
returnbuf;
}
boolValidSerial()
{
char*serial = read_serial("serial.txt");
int res =VMProtectSetSerialNumber(serial);
delete[]serial;
if (res)
{
print_state(res);
returnfalse;
}
returnTRUE;
}
int_tmain(int argc, _TCHAR* argv[])
{
if (argc== 2)
{
int nSize= VMProtectGetCurrentHWID(NULL, 0); // get number of required bytes
char*pBuf = new char[nSize]; // allocate buffer
VMProtectGetCurrentHWID(pBuf,nSize); // obtain hardeare identifier// use it
printf("%s\n",pBuf);
deletepBuf;
}
else
{
if (ValidSerial())
printf("ok\n");
else
printf("err\n");
}
return 0;
}
2、配置凭证管理参数得到注册码
点击 授权管理→生成
根据需求,选择相应的内容,点击序列号,然后把序列号保存到serial.txt文件中。如果序列号内容包括硬件码,运行test.exe aaa(任意加一个参数即可)即可得到本机的硬件码。
3、运行测试
把serial.txt文件与exe文件放到同一目录下,运行exe进行测试,看是否达到预期效果。