[关闭]
@FadeTrack 2015-10-30T10:28:38.000000Z 字数 4014 阅读 3008

NISLVMP:一种新的保护方式,基于VM,改进之

未译完


Huaijun Wang, Dingyi Fang, Zhanyong Tang, Xin Song
School of Information Science and Technology, Northwest University Xi’an 710127, China
NWU-Irdeto Network-Information Security Joint Laboratory (NISL), Northwest University Xi’an 710127, China
E-mail: hjwang006@163.com, dyf@nwu.edu.cn, http://www.nwu.edu.cn

摘要——VM(虚拟机)软件保护技术是一个热门研究领域。基于对传统VM的研究,我们进行了新的设计和改进,名为:NISLVMP。他拥有多重寄存器环境,安全的虚拟指令以及更多的变型模板。最后,分析和测试表明,NISLVMP能有效提高安全保护软件。

关键词:基于vm软件保护;多重VM_Context;安全虚拟指令;变形引擎。

一、 介绍

在这个信息化时代,软件已经布及世界的每一个角落,但随之而来的安全问题也是越来越多。
静态和动态分析被广泛应用于程序的理解,代码分析、动态调试,等等。也拥有许多成熟工具和技术。因此,即使软件并非是以源代码形式发行的,攻击者也可以分析二进制机器代码。
软件在白盒测试环境中运行时,软件的整个执行流程暴露在攻击者的眼下。尽管只要有充足的时间,没有软件是不能被破解的,但是加大破解的学习成本,延长被破解的周期也是很要必要性的,在当今,这种需求达到了最高点。

目前,有一些常用的软件保护技术,如序列号、加密、软件水印和壳。大量数据表明,这些方法在实际应用中都有一定的局限性:

序列号只用于保护程序的入口点;
加密程序执行之前必须解密;
软件水印应用于司法取证,避免版权纠纷等问题。
基于vm的软件保护很快变成了软件保护的热点研究领域。T. Maude提出了替代方法隐藏程序的解释过程。巴兰特斯提出的 指令集随机化改进的概念,用于抵抗代码注入攻击。
本文所说的虚拟机并不是系统级虚拟机( VM Ware or Virtual PC.)。
VM保护技术大大增加了虚拟机的发展。

本文在第二部分,软件保护中对传统的基于 VM 的虚拟机进行了介绍。
第三部分主要介绍了 多层虚拟机环境的设计。
第四部分中提出了 安全指令(VSI) 。
在第六部分和第七部分总结了纸未来的工作的细节。

二、相关工作

一旦软件被带有VM的壳保护起来,攻击者就算可以反编译代码,也无济于事,因为他们得不到正确的代码,看到的仅仅是虚拟指令。因此,他们必须得到每一个虚拟代码的含义和解释的规则。

A.基于vm软件保护

在商业领域,有一些著名的基于虚拟机壳(软件保护软件),例如代码virtulizer,Themida和VMProtect,在学术界,也有一些人来研究这项技术。Amir 提出了一个有效的基于vm软件保护。他们消弱了对系统的依赖,只依赖假设抽象的系统来开发的基于vm本身的加密措施和 有权/可信 的计算环境,可以击败 Rolles’ 的攻击方法。杨明也曾提出了一种软件保护方案,通过嵌套虚拟机,从而逆向工程师必须完全理解前一层,才能继续理解下一层。这样,可以有效提高被保护软件的安全性。作者提出一个概念,使用多个不同的解释器来混淆。

B.基于vm软件保护的相关概念

VM-based 保护的思路是,将关键代码转换成虚拟机码,
破坏掉原来的代码,之后通过虚拟机在运行时解释执行。
首先,我们将介绍相关的概念:

关键代码段:用户指定的代码与重要的算法。虚拟机的目的主要是为了保护这些关键代码段。

虚拟指令(VI):

Virtual Instruction (VI): The intermediate results of
the instructions which need to be protected after
transformation in the VM protection process. These
intermediate results are independent of the instruction
format, but they don’t exist in the protected program.

在虚拟机保护过程中,需要在转换后进行保护的指令执行的中间结果。这些中间结果是独立的指令格式,但他们不存在于受保护的计划。

VM翻译:虚拟机解释器是一个抽象的概念,它包括VM_Context、处理程序和调度者程序。

VM_Context:这是虚拟翻译执行所用的环境。它用来存储寄存器的值。进入虚拟机的时候,解释和执行处理程序会根据寄存器的值来设置VM_Context。与此同时,它将模拟修改寄存器的值。最后,跳出虚拟机,将值从VM_Context恢复到真正的寄存器。

处理程序[Handler]:
虚拟机解释器的重要组成部分。这是一群本地指令片段用来解释虚拟指令。

调度者:主要用于读取Driver_data和跳转执行相应的处理程序。过程执行后,返回到调度者。重复以上步骤,直到执行完 Driver_data 字节码。

变形和混淆:一般来说,处理程序包括几个汇编指令,原型是相对简单的。为了提高安全处理程序本身,它是需要做变形加密等处理。

Driver_data:通过VI生成的需要保护的虚拟字节段。
每个 Driver_data 对应于一个处理程序或一个相关的处理程序。虚拟机解释器读取字节代码和调用相应的处理程序实现保护指令原本的功能。这种结构存在与虚拟机保护程序解释器。

解释了相关概念之后,我们将介绍当前基于虚拟机保护的执行过程。

C.基于虚拟机保护的执行过程

首先,它需要分析PE文件,其次,它需要在植入 VM之后重建PE文件,再其次,它需要将原来的指令转换成解释器可以处理的虚拟指令。
只要保护过程如图1所示:
图1:
基于虚拟机保护的执行过程

根据图1,保护过程的一般步骤如下:
步骤1:分析PE文件和定位关键代码段;
步骤2:将目标(例如,x86)指令转换为虚拟指令;
步骤3:通过变形引擎来变形和无序化处理程序;
步骤4:生成处理程序序列来解释虚拟指令;
步骤5:根据处理程序生成 DriverData 的序列;
步骤6:植入 DriverData 、处理程序 到被保护PE文件,然后修复PE文件。

现在,虚拟机已经完成保护软件。然后,让我们来看看被保护的软件的执行过程,图2所示:

图2:
被保护软件的执行过程

根据图2,一般的执行过程

包括5个步骤:

步骤1:遇到保护指令时,跳转到VM的主要处理程序;
步骤2:主要处理程序得到 DriverData 并 解密;
步骤3:根据解密后的数据,从跳转表中获取相应的处理程序地址并执行处理程序,然后跳转到主要处理程序;
步骤4:重复步骤2和步骤3直到 DriverData 被执行完成;
步骤5:在关键部分执行完后跳出VM,之后继续执行。

D.存在的问题

基于vm软件保护在一定程度上提高保护强度。但这些技术在深入研究后,还存在一些问题,包括:

1) VM_Context很容易跟踪

当虚拟指令执行时,VM_Context充当一种临时结构来记录寄存器和标志的值。所以获得VM_Context成为了攻击VM的一个前提。
一般来说,VM_Context的结构,如图3所示:
这里写图片描述

这个结构太简单了,攻击者通过分析寄存器和标志就能定位到VM_Context,然后监视和跟踪每个寄存器和标志的值的变化来分析真实的指令或行为。

2) 单一功能的虚拟指令

虚拟指令的目的是解释最初的指令集。也就是说,每个虚拟指令都是有效的功能指令(纯粹是为了实现某些功能)。所以攻击者会视图解析每一个虚拟指令,一些基于vm软件保护插入大量的垃圾代码,但这并起不到很好的效果。

3) 变形模板过少

个人觉得这段没说啥,简单意义一下,就是当前的VM类软件的变形模版很少,很容易受到攻击。

三、改善VM_CONTEXT

在NISLVMP双重VM_Context结构设计:VM_Context1,VM_Context2,寄存器的安排是不同的。所以虚拟指令是通过VM_Context1,VM_Context2来获取相应的寄存器和标志的值之后计算,而不是仅仅通过一个VM_Context。
为了更好的描述,我们假设依旧是面向一个VM_Context来计算的,这样可以简化思想。
主要设计过程见图4:
这里写图片描述

在开始保护一条指令,它需要计算vm_context价值与价值两个vm_context根据计算规则,最后保护指令,分配给VM_Context1和VM_Context2 vm_context值和相应的计算规则。所以设计的双VM_Context过程有三个步骤:

在执行一条保护指令时,它首先需要根据 两个vm_context 和一定的计算规则去计算 中间的 vm_context。

分为了如下3个步骤:

步骤1:设计计算规则

规则可以确保我们在分配了分配VM_Context1和VM_Context2后可以得到正确的vm_context的值。所以这个规则并不是唯一的,只要符合下面的条件即可:

这里写图片描述
一个有效的计算规则包括两个算法:algorithm1 algorithm2。不同的寄存器可以使用不同的规则。
下面,我将列举一个栗子。

  1. If a^b = c, then a = b^c;
  2. If a-b = c, then a = b+c;
  3. If a+b = c, then a = c-b;

步骤2:分配 VM_Context1 和 VM_Context2

在保护开始的时候,VM_Context1可以随机分配,并分配VM_Context2 为 null(反之亦然)。当原始指令通过虚拟指令解析的时候,vm_context就变得明显可见了。
然后我们可以根据不同的寄存器的相关规则计算VM_Context2值。VM_Context2的分配过程如下所示:
这里写图片描述

步骤3:vm_context的计算

我们获得了VM_Context1 和 VM_Context2 ,VM_Context 就可以通过步骤1中提到的规则计算了。
这里写图片描述

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注