本帖最后由 jjjjjj8889 于 2022-2-11 16:03 编辑
vmp脱壳的教程特别多,但是如何使用vmp加壳的教程太少了,遇到不懂的地方想找个人问问都找不到,把自己摸索的一些东西写出来,以防忘记,如果有错误或不完善的地方,希望大家能指出来。
vmp就像winlicense一样,也是分sdk和gui两部分。不过感觉gui部分,winlicense更强大一些,可以使用的限制更多。sdk部分,就是把函数插入到源代码里,让vmp在编译的时候可以对代码指定的部分进行保护。
原理其实也蛮简单的,就是先在源代码上做标记,把需要保护的代码标记出来,等源代码编译后,用vmp工具对标记部分进行代码保护性编译(代码变异、虚拟化等),并同时对软件加壳。
函数主要有以下这些:
代码标记函数:
* VMProtectBegin:标记保护的快开始位置,保护模式可在gui上调整,一个开始必须对应下面的结束,中间不能穿插,下同。
* VMProtectBeginVirtualization:这个是虚拟化的开始,运行效率一般;
* VMProtectBeginMutation:这个是变异的开始;
* VMProtectBeginUltra:这个是变异+虚拟化的开始,gui上对应名次叫超级,运行效率最慢,不要用在对效率要求高的代码上;
* VMProtectBeginVirtualizationLockByKey:虚拟化并锁定序列号,没有正确序列号的话,这一段代码无法执行,相当于功能锁定;
* VMProtectBeginUltraLockByKey:超级并锁定序列号;
* VMProtectEnd:保护代码的结束为止;和上面的任一标记成对使用,中间不能穿插别的标记;
服务函数:
* VMProtectIsProtected:检测是否被保护
* VMProtectIsDebuggerPresent::检测是否调试模式
* VMProtectIsVirtualMachinePresent:是否虚拟机模式
* VMProtectIsValidImageCRC:校验内存是否被更改
* VMProtectDecryptStringA:解密被保护的ansi字符串常量,但是我感觉更像是加密字符串,用途就是你需要用到明文字符串的时候用一下这个函数就可以保护明文防止被反编译找到了。不过到了内存里运行的时候,啥啥都会释放出来,直接搜内存还是能搜到的。
* VMProtectDecryptStringW:解密被保护的unicode字符串常量,同上。
* VMProtectFreeString:施放解密字符串所动态分配的内存,官方说是没必要释放,但你一定要释放就用这个函数。
序列号函数:
* VMProtectSetSerialNumber:载入序列号
* VMProtectGetSerialNumberState:序列号各种状态是否正常,如文件损坏、过期、黑名单等
* VMProtectGetSerialNumberData:序列号包含的数据(用户名、邮箱、日期次数等)
* VMProtectGetCurrentHWID:获取硬件id,只有vmp加壳后才会显示正确id;
以下代码用lazarus写的,引用 uses VMProtectSDK;
做标记的时候,需要写上标记名称,建议直接用函数名,这个标记名,在用gui的时候会列出来供你选择用什么保护模式,比如虚拟化换超级,如果在标记的时候就做好了后面就不用改了;
软件编译后,在被vmp加壳前,是需要VMProtectSDK32.dll才能正常运行,在vmp加壳后,vmp会去掉源代码上的标记,此时不再需要VMProtectSDK32.dll;
[Delphi] 纯文本查看 复制代码 //载入序列号到vmp系统:
procedure TForm1.FormCreate(Sender: TObject);
var
load_xlh:Tstringlist;
begin
if FileExists('序列号.txt') then
begin
load_xlh:=Tstringlist.Create;
load_xlh.LoadFromFile(ExtractFilePath(Application.ExeName) + '序列号.txt');
VMProtectSetSerialNumber(PAnsiChar(AnsiString(load_xlh.Text))); //将序列号载入vmp系统
load_xlh.Free;
end;
end;
//混淆+虚拟procedure TForm1.Button1Click(Sender: TObject);
begin
VMProtectBeginUltra('button1click');
if edit1.Text = VMProtectDecryptStringA('12345') then showmessage(VMProtectDecryptStringA('正确'));//这里用了保护字符串函数,意思好像是反编译就找不到12345和正确这两个字符串,具体没测试过。
VMProtectEnd;
edit1.clear;
end;
//混淆+虚拟+锁定序列号,这里绑定了序列号,如果序列号不正确,会弹出提示并退出程序;
procedure TForm1.Button2Click(Sender: TObject);
begin
VMProtectBeginUltraLockByKey('Button2Click');
if edit1.Text = '12345' then showmessage('正确');
VMProtectEnd;
end;
//获取硬件id;procedure TForm1.Button3Click(Sender: TObject);
var buf: array [0..127] of AnsiChar;
begin
FillChar(buf, 0, sizeof(buf));
VMProtectGetCurrentHWID(buf, sizeof(buf));
edit1.Text := buf;
end;
如果代码使用到保护区域以外的函数,这个函数是不会被保护的,需要自己去添加保护标记;获取序列号中的其它状态或数据,demo里都有详细例子,如果不需要对各种状态进行判定,仅仅是让不让对方用某些功能,上面这些已经够用了。
下面是gui用法,一共有进程、授权、文件、脚本、选项5个栏目:
进程:vmp打开一个exe文件,他会读取源代码里做了标记的部分,放在进程一栏,把标记的名称列出来,这里允许变更保护类型,以及锁定序列号;这个进程一栏其实可改的地方不多;
授权:这个点通用即可生产密钥对;数字2048是加密长度,越大加解密耗时越长,通常默认2048足矣,毕竟银行也是2048;密钥对生成以后,要注意保存项目,不然下次重新生成的密钥对就不一样了;生成密钥对以后,就可以暂时不管了,具体的授权序列号发给用户的时候再生产即可;
文件:这里可以把程序用到的文件也保护起来打包在一起,有点像制作单文件程序;
脚本:不知道干吗用的;
选项,这里参数较多:
文件:4项默认都选是,
检测:如果不在虚拟机里用就都选上吧,
附加:,vm分段默认是.vmp,建议改成.UPX,据说可以迷惑敌人;移除调试信息默认是;移除重定位,如果是delphi编译的可以选是;
消息:就是检测到不同状态时候的提示内容,可以改成中文;
设置完这些,就可以编译vmp了。
下面说序列号生成,在授权那一栏,点添加授权,然后填上对应信息即可,要锁定硬件的话就在程序里加一个获取硬件码的代码,用户获取硬件码后发来填上即可;
其中,运行次数好像没有提供控制函数,需要用户自己在程序里写代码去控制;
最大创建日期,就是该序列号可以用于多个升级版本,在设定的日期之后出的新版本不可用,但是设定日期之前编译的版本一直可用,也就是说可以一直用序列号允许的最后一版,直到序列号过期。
生成序列号以后,没有复制的地方,右击什么的都没有,需要鼠标点一下序列号,按Ctrl+C复制发给用户。
|