步骤2.5:将代码锁定在一个序列号上
VMProtect 是新一代软件盗版保护解决方案。VMProtect 是目前强大的反盗版解决方案之一,许多领先的软件发行商都在使用它。VMProtect允许保护可执行文件(EXE,SCR),动态链接库(DLL,OCX,BPL)和驱动程序(SYS)。
加密解密技术交流群(766135708)
破解程序常见的方法之一是找到检查序列号的地方和附近的条件跳转。如果序列号是正确的,程序的执行就会向一个方向发展,如果不正确,则向另一个方向发展。黑客可以找到这个跳转并将其替换为 "correct "的方式。让我们用这种方式来 "crack "我们的测试程序,是通过直接在源代码中进行测试。接着我们 "switch off "我们的条件跳转:
char *serial = read_serial("serial.txt"); int res = VMProtectSetSerialNumber(serial); delete [] serial; if (false && res) {我们的程序接受任何序列号并正常工作。如果文件是通过VMProtect保护的,即使是有经验的黑客也会花几个月的时间来定位和修改条件跳转。考虑到该程序在不同条件下多次检查序列号,因此,即使是这样一个简单的检查也是相当安全的。
将代码锁定在一个序列号上
VMProtect的演示版在处理功能的数量上有限制:只能处理一个功能。如果你使用演示版,你应该只在项目中包含 foo() 函数,否则 VMProtect 的演示版可以选择 main() 函数,锁定到一个序列号将无法进行工作。
VMProtect 的许可系统允许你将一个或多个函数的代码锁定在一个序列号上,这样,如果没有提供正确的序列号,就无法正常进行。函数的主体被虚拟化,然后被加密,只有用正确的序列号才能解密。这意味着,即使黑客发现并修复了序列号检查中的条件跳转,锁定在序列号上的函数仍然不能工作。在 "Functions "部分选择foo()函数,并在右侧面板将 "Lock to Serial Number "选项改为 "Yes"。
保护该应用程序。由于我们已经 "hacked"了它,在serial.txt文件中放入一个任意的文本并运行该应用程序。下面的文字出现在控制台:
C:\test>dummy_app.vmp.exe serial number is correct, calling foo()黑客 "fixed"了条件跳转,程序以 "correct"方式运行。但是当调用foo()时,程序显示了一条信息:
由于我们将foo()函数锁定在序列号上,而黑客并没有这个序列号,所以试图解密该函数的代码导致故障,无法继续执行程序。当按下 "OK "键时,程序关闭,"done "信息从未在控制台显示。
什么应该锁定在一个序列号上?
将一个只应在程序的注册版本中运行的功能锁定在序列号上是有意义的。由于锁定需要虚拟化,你应该考虑到一些性能的缺失。如果一个文本编辑器不允许在演示版本中保存结果,你可以将保存文档的功能加密在一个序列号上。如果在操作过程中,这个函数调用了其他函数,也没有必要加密它们,因为如果没有主函数,它们就没有任何用处。
你还应该记住,在没有序列号的情况下调用被加密的函数会导致程序关闭,没有机会保存工作结果。这就是为什么你应该彻底测试应用程序,以确保它不会在试用模式下调用这些函数。在上面的例子中,文本编辑器必须在演示模式下禁用 "Save "命令,并且不对Ctrl+S快捷键作出反应。当然,它也不应该要求在退出时保存文档。如果你不注意这一点,用户可能会对你的 "buggy "的演示版本感到失望。
锁定到一个序列号和无效的序列号
当VMProtectSetSerialNumber()函数被调用时,许可模块会检查传递给该函数的序列号。只有在序列号在检查时绝对正确的情况下才会执行加密的代码片段,没有被列入黑名单,具有正确的硬件标识符,没有过期等等。在这种情况下,所有的加密程序都会被执行,直到应用程序被关闭,或者再次调用VMProtectSetSerialNumber()
一些限制会在程序执行过程中 "trigger":例如,程序的运行时间可能会过期或序列号过期日期到来。在这种情况下,许可模块仍然会加密并执行锁定在序列号上的功能。之所以如此,是因为被保护的程序很难检测到这些限制触发的时刻,并相应地改变行为(屏蔽相应的菜单项等)。如果许可模块突然停止执行锁定在序列号上的代码片段,这将很可能导致应用程序的故障。这就是为什么当序列号被设置后,会做出决定,并选择相应的执行模式。