基于虚拟机的软件保护技术

本文并不打算对vmprotect或其它某款软件安全套件进行深刻讨论,而着眼于研究基于虚拟机的软件保护技术的起源、思想和实现。java

基于虚拟机的软件保护技术基于虚拟机的软件保护技术

现有软件保护技术概述linux

传统的软件保护技术,根据针对对象不一样,可分为反静态调试和反动态调试两大类。反静态调试主要针对对象为反汇编器。反汇编器经过面向特定平台的反汇编引擎(如PC平台即为X86反汇编引擎),将编译器生成的二进制文件还原成汇编代码,有经验的逆向工程师能够据此还原出算法等核心运算机制。反静态调试主要是经过特定区段加密等方式,将核心信息保护起来,只在运行期才经过解密等算法动态还原,阻碍反汇编器静态地将二进制文件还原成汇编码。
反动态调试主要针对对象为调试器,因为通过静态加密的二进制码最终必须解密才能执行,所以经过Ollydbg等动态调试器仍然能够加以查看,反动态调试经过检测调试器和屏蔽调试端口等各类反调试技术阻止逆向工程师经过调试器跟踪软件进程的运行状况,使得软件的运行时情况始终保持处于黑盒状态。
被动型软件保护概念上述两种保护方案均采起主动出击的策略,意图“御敌于国以外”,中心思想是一个“挡字”,阻止逆向工程是窥视软件内部机理,但盾与矛的对抗老是无休止的,并无任何一种主动型软件保护手段能真正完全阻断逆向工程,所以另外一种“以人为本”的被动型软件保护技术开始走向斗争舞台的中央。
被动型软件保护手段基于一个假设,即逆向工程师已经经过各类办法突破了主动型软件保护措施,能够为所欲为地观察一切,此时“挡”已经挡不住了,只能采起“藏”的策略,经过提升核心代码的隐蔽性来提升逆向工程在阅读反汇编代码阶段的时间成本投入,间接起到软件保护的效果。被动型软件保护手段具体实现方式主要有乱序和混淆。
乱序是指在在程序执行流中添加跳转指令,如jmp,经过这些跳转指令将一个从上至下执行的完整代码块切分红若干执行前后顺序不一致的代码片断。乱序可以必定程度上增长反汇编代码的阅读难度,但若只是简单地植入无条件跳转很容易被识别和去除,所以工业级的保护产品每每经过采用条件跳转的方式增长识别难度。
基于虚拟机的软件保护技术基于虚拟机的软件保护技术
混淆是指经过加入无心义代码(又称为花指令或垃圾代码)或者有意义代码,增长反汇编码的理解难度。俗话说要藏好一棵树,最好的地点必定是森林,混淆技术就是经过代码膨胀增长反汇编代码的总量,为隐藏核心代码构造出一片代码“森林”。早期增长的混淆代码为无心义代码,实现类nop操做的执行效果,如push指令和pop指令搭配使用,但这类代码无实际意义,去除后并不会对软件运行产生影响,所以有经验的逆向工程师每每会首先去除这些无心义的混淆代码才开始进行反汇编码的阅读工做,使混淆技术失去效果。为了确保混淆代码不被去除,工业级的保护产品更倾向于采用有意义的混淆代码,核心思想是等价替换,经过多条指令实现核心代码中一条指令的效果,如最简单的赋值指令moveax,3能够替换成xoreax,eax;inceax;inceax;inceax这四条指令,操做效果同样,但指令数量翻了两番。被动型软件保护技术究竟可否对软件安全起到实质性的做用,业界一直存在争论。反对的观点主要集中在认为被动型软件保护技术只是提升了阅读反汇编代码的难度和数量,让人“眼花”而已,并无任何实质性的效果。本文认为,软件安全不应简单理解成让软件绝对安全不可攻破,而实际该是攻方与防方、投入与产出的反复博弈的过程,攻方人力的投入天然也是成本之一。一我的单位时间内阅读代码的数量是固定的,所以,提升了阅读反汇编代码的难度和数量,也就提升了阅读反汇编代码的时间,提升了攻方人力成本的投入,对软件安全是有切实效果的。算法

虚拟机软件保护技术安全

虚拟机软件保护的思想jvm

虚拟机软件保护技术是被动型软件保护技术的分支,具体来讲是添加有意义的混淆代码的一种变型使用。
虚拟机技术目前在软件领域应用普遍,根据应用层级不一样,基本可分为硬件抽象层虚拟机、操做系统层虚拟机和软件应用层虚拟机。用于保护软件安全的虚拟机属于软件应用层虚拟机,同层的虚拟机还包括高级语言虚拟机,如java程序语言运行环境jvm和.net程序语言运行环境CLR,后者采用虚拟机的缘由是便于移植,所以编译器没有直接生成可直接在机器上执行的nativecode,而改成生成中间代码byte-code,再经过在不一样机器环境下安装对应版本的虚拟机对byte-code进行解释执行,从而实现跨平台运行。
用于保护软件安全的虚拟机采用相似的流程。虚拟机保护软件首先会对被保护的目标程序的核心代码进行“编译”——须要注意的是,这里被编译的不是源文件,而是二进制文件——并生成效果等价的byte-code,而后为软件添加虚拟机解释引擎。用户最终使用软件时,虚拟机解释引擎会读取byte-code,并进行解释执行,从而实现用户体验彻底一致的执行效果。编码

虚拟机软件保护的实现加密

编译生成byte-code
要设计一套虚拟机保护软件,首先要设计一套虚拟机指令,也便是byte-code的指令集表,生成byte-code的过程,实际是将原始机器指令流等价转译成虚拟机指令流的过程。spa

虚拟机指令集表应知足如下两条设计原则:
第一条设计原则是虚拟机指令集表与原始机器指令集表越正交越好,安全系数越高。最坏的状况是虚拟机指令集表与原始机器指令集表为一一对应的关系,采用这种指令集的虚拟机保护程序安全系数趋近与零,对于逆向工程师而言只须要进行简单的换算,便可还原出原始代码。
另外一条设计原则是应尽量地具有图灵完备性,可以完整地表达出原始机器指令的全部可能表达。图灵完备性越好,则虚拟机保护引擎的保护的覆盖范围越广,健壮性越高。理想状态下,虚拟机指令集应完整地实现对原始机器指令集的等价替代,须要彻底知足图灵完备性。但实际上完整替代的代价太高甚至不太可能实现,如x86指令集的FCLEX、FPTAN等指令,仿真难度较高,且核心代码使用这类指令的可能性很小,综合效费比考虑,虚拟机指令集一般并不涵盖这些“生僻”指令。对于不能仿真的指令,能够采起退出虚拟机执行,获取执行结果再进入虚拟机的方法解决。操作系统

解释执行byte-code
在软件运行时,编译产生的Byte-code由内嵌入软件可执行文件中的虚拟机解释引擎,采用读取-分派的方式解释执行。
虚拟机解释引擎分为两大部分,分别为Dispatcher和handle。.net

基于虚拟机的软件保护技术基于虚拟机的软件保护技术

Dispatcher的中文字面意思为“分派器”,至关于虚拟机解释引擎的CPU,负责读取Byte-code,并指派对应的handle进行解释执行。Handle的中文字面意思为“处理”,实际做用为虚拟机指令经过平台nativecode(如PC平台即为x86指令)的实现。Handle的数量与虚拟机指令集的指令数量是一致的。
虚拟机的进入和退出问题
软件保护虚拟机与高级语言虚拟机并不彻底同样,主要体如今高级语言虚拟机由始至终均在虚拟机环境下执行,但软件保护虚拟机必须经历本地环境与虚拟机环境的切换,为了保证执行结果的一致性,必需要求虚拟机环境可以正确获取和还本来地环境的执行上下文。较为便捷的方法是采用堆栈机模型,即虚拟机基于堆栈来进行数据操做。进入虚拟机前,先将本地环境压栈,虚拟机直接以栈地址执行指令流操做,退出虚拟机后,再一一出栈,从而保证了上下文在不一样执行环境的无缝切换。

结语

基于虚拟机的软件保护技术能够大大增长了逆向工程还原代码的难度,一套设计良好的软件保护虚拟机可以显著增长代码还原所需的时间,从而抬高了逆向工程的成本,达到软件保护的效果。但采用虚拟机并不是有百利而无一害,和高级语言虚拟机同样,软件保护虚拟机一样面临会致使执行效率下降的问题,安全和效率老是处于相生相斥的关系,具体偏重只能根据生产环节的要求具体权衡。

 

免费提供最新Linux技术教程书籍,为开源技术爱好者努力作得更多更好:http://www.linuxprobe.com/

相关文章
相关标签/搜索