发明内容
针对上述缺陷,本发明解决的技术问题在于,提供一种在软件保护装置中实现软件保护的方法,该方法可以使软件开发者无需进行程序改写,就可以顺利的实现软件保护。同时,本发明提供一种实现该方法的装置。
本发明提供的一种在软件保护装置中实现软件保护的方法,用于已实现X86虚拟机的软件保护装置;包括:
在有待保护的程序的可执行文件中挑选部分指令段,作为写入软件保护装置的指令段;
将被挑选的指令段中使用的主机内存地址、寄存器名、堆栈地址等转换为软件保护装置虚拟机的内存地址、寄存器名、堆栈地址;
将转换后的指令段写入所述软件保护装置中,同时去除原被选中指令段,并写入通讯指令;
运行所述被保护的程序时,当运行到写入软件保护装置的指令段时,进行下列步骤:
将所述写入软件保护装置指令段涉及的内存、寄存器、堆栈的内容,从主机映射到所述软件保护装置虚拟机对应的内存、寄存器、堆栈;
所述软件保护装置虚拟机运行该指令段;
运行完毕后,软件保护装置虚拟机将上述内存、寄存器、堆栈中的内容反映射到主机中对应的内存、寄存器、堆栈。
优选地,所述通讯程序可以写在所述去除指令段的原位置。
优选地,通讯程序写在被保护软件的任意位置,在原去除指令段的位置处写入调用指令。
优选地,通讯程序写在被保护软件的起始地址处,调用时,通讯程序填充原删除指令段的位置。
优选地,所述主机内存地址、寄存器名、堆栈地址转换为软件保护装置虚拟机中的内存地址、寄存器名、堆栈地址时,记录两者之间的对应关系;在所述通讯指令中,记录该对应关系。
优选地,所述映射是将主机中内存、寄存器、堆栈的内容写入软件保护装置虚拟机对应的内存、寄存器、堆栈中,所述反映射则与上述过程相反。
优选地,所述在有待保护的程序中挑选部分指令段的过程,由计算机根据程序段的重要性自动进行选择;或者由人工选择。
优选地,所述软件保护装置虚拟机的寄存器名采用与主机相同的寄存器名,此时,只需将所挑选的程序段中的主机内存地址转换为软件保护装置虚拟机的内存地址。
本发明同时提供一种使用上述方法实现软件保护的装置,包括:已实现X86虚拟机的软件保护装置,还包括:
选取单元,用于读取有待保护的程序,并从中挑选部分指令段,作为写入软件保护装置的指令段输出;
转换单元,用于接收所述选取单元输出的指令段,将该指令段中的主机内存地址、寄存器名、堆栈地址等转换为软件保护装置虚拟机的内存地址、寄存器名、堆栈地址,并输出经过上述处理的程序段;
程序写入单元,用于接收所述转换单元输出的程序段,并将该程序段写入所述软件保护装置虚拟机中;同时从待保护程序中去除被选取单元选中的指令段;
映射单元,在运行所述被保护程序时,当运行到所述选定程序时,该映射单元根据所述通讯程序的记录,读取主机中所述选定程序段涉及的内存、寄存器、堆栈中的内容,并将上述存储单元中的内容写入软件保护装置虚拟机中对应的内存、寄存器、堆栈中;
反映射单元,该单元在所述软件保护装置虚拟机运行完其存储的选定指令段后,将该指令段相关的内存地址、寄存器名、堆栈地址中的内容输入给主机应用程序,并根据通讯程序中有关主机与虚拟机的内存地址、寄存器名、堆栈地址对应关系的记录,将上述内容分别写入主机中相应的内存、寄存器、堆栈中;
通讯程序写入单元,用于将通讯程序写入该待保护的程序的可读取位置中。
优选地,所述通讯程序写入单元写入通讯程序的可读取位置为所述去除指令段的原位置。
优选地,所述通讯程序写入单元写入通讯程序的可读取位置还可以为被保护软件的任意位置,此时,该装置还包括调用指令写入单元,该单元在选定指令段的原位置写入调用通讯程序的指令。
优选地,所述调用指令写入单元写入的调用通讯程序的指令,用于调用通讯程序。
优选地,所述通讯程序写入单元写入通讯程序的可读取位置还可以在被保护软件的起始地址处,调用时,通讯程序填充原删除指令段的位置。
优选地,所述转换单元还根据转换结果,输出所述被选中程序段中主机各个存储单元与软件保护装置虚拟机中各个存储单元的对应关系的记录;
所述通讯程序写入单元接收转换单元输出的主机各个存储单元与软件保护装置虚拟机中各个存储单元的对应关系的记录,并将该对应关系记录在所述通讯程序中。
本发明的基本思路是,在现有的软件保护装置内部实现X86虚拟机,并在此基础上,将在主机上运行的程序的部分指令段转移到虚拟机上运行。为此,可以由计算机自动对写入虚拟机的指令段进行适当的修改,将其中涉及的主机内存地址、堆栈地址、寄存器名转化为虚拟机中的内存地址、堆栈地址、寄存器名;并在该程序中加入通讯程序。运行该程序时,当运行到写入虚拟机的指令段时,根据通讯程序的内容,首先将主机中与运行程序相关的内存、堆栈、寄存器等中的内容,映射到虚拟机中对应的内存、堆栈、寄存器,然后由虚拟机继续运行该程序。虚拟机运行结束后,再将相关内存、堆栈、寄存器的内容反映射到主机中。最终获得完整的运行结果。
与现有技术相比,本发明提供的方法,在软件保护装置内部实现X86虚拟机的基础上,实现软件保护。该方法可以使运行在X86系列计算机上的程序只需进行简单的转换,就可实现对软件的保护,显著降低了X86系列计算机使用软件保护装置的难度。
具体实施方式
请参看图1,为本发明第一实施例中设置软件加密的流程图。该实施例中,软件保护装置是加密锁,并且该加密锁中已经实现了X86虚拟机,这样,运行在X86系列计算机上的可执行文件能够在该加密锁上执行,这样,就为后续简化软件保护的过程创造了条件。现有技术中,存在多种方法在加密锁上实现X86虚拟机,因此,在此不进行详细说明。以下结合图1详细说明设置软件加密的流程。为了便于理解,该实施例结合一个具体的程序进行说明。
步骤S101,选择有待保护的可执行文件。
所述有待保护的可执行文件是使用各种高级语言、汇编语言等编写的程序在PC机上运行得到的可执行文件。
所述可执行文件具体是.exe形式的文件。由于加密锁已经实现为X86虚拟机,因此,在一般的PC机上运行的.exe形式的可执行文件,可以在加密锁上运行。
步骤S102,在所述可执行文件中,选择部分程序段。
本实施例提供的这种软件保护方法,是将部分可执行文件放置在加密锁上,由加密锁运行。而原来可执行文件上的这部分内容则从主机上完全去除。由于主机上不保留这部分内容,因此,不可能仅仅依靠主机上的内容获得完整的程序,只有拥有加密锁的合法用户才能正常使用该软件。在加密锁中,还可以对该程序段采取加密等措施。这样,就实现了对软件的保护。为了实现对程序的有效保护,需要选择比较重要的程序段,作为放入加密锁的内容。具体选择的方式,可以由软件开发者人工选择,也可以采用一定的标准,由计算机自动选择较为重要的程序段。
例如,本实施例中选择源程序中的以下段落作为写入加密锁虚拟机的程序段。
int add(int a,int b)
{
return a+b+constVar;
}
在本实施例中,constVar是一个全局变量。
根据上述源程序编译获得的汇编语言程序如下:
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,40h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-40h]
0040102C mov ecx,10h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr[edi]
00401038 mov eax,dword ptr[ebp+8]
0040103B add eax,dword ptr[ebp+0Ch]
0040103E add eax,dword ptr[00424b04]
00401044 pop edi
00401045 pop esi
00401046 pop ebx
00401047 mov esp,ebp
00401049 pop ebp
0040104A ret
由源程序编译形成的可执行程序为.exe文件,其具体形式是二进制机器码,但是,二进制机器码不易于理解。由于汇编语言程序与二进制机器码是直接对应的,使用汇编语言对其说明将更易于理解,因此,以上采用汇编语言的形式说明由源程序编译而成的可执行文件。
步骤S103,将所选择的程序段进行适应性转换后,写入所述加密锁。同时,将该段程序从原主机的可执行文件中去除。
所述加密锁虽然实现了X86虚拟机,但是,其硬件环境与主机仍有很大的差别,主要差别在于,加密锁虚拟机上不可能具有与主机相同的内存环境,以及寄存器、堆栈等,必须将准备写入的程序段的相应内容根据加密锁的环境进行改写,也就是将该段程序使用的内存地址、寄存器名、堆栈地址等,改为加密锁虚拟机中的内存地址、寄存器名、堆栈地址。同时,记录更改前后使用的内存地址、寄存器名、堆栈地址的对照关系,以便后续使用。例如,上述程序段中,要将add eax,dword ptr[00424b04]转换为add eax.dword ptr[10]。程序中其他的内存地址以及寄存器名、堆栈地址也转换为加密锁中的内存地址、寄存器名、堆栈地址。上述转换具有规律性,可以由计算机自动完成。由于主机寄存器的内容有限,而一段程序使用的堆栈也是有限的,因此,加密锁虚拟机中的寄存器、堆栈可以与主机中相同,此时,该程序中的寄存器名和堆栈地址可以无需变换。但是,加密锁中不可能具有与主机同样多的内存,所以,两者的内存地址完全不同。因此,内存地址必然要进行变换。
步骤S104,在主机上所述写入加密锁的程序段的位置写入调用通讯程序的指令,以及向程序中合适位置写入通讯程序。
所述调用通讯程序的指令用于实现对通讯程序的调用,使程序运行到此处后,跳转到通讯程序,由通讯程序完成通讯过程。当然,如果通讯程序直接写入被去除的指令段的原位置,也可以不需要该调用通讯程序指令。
所述通讯程序可以写入该待保护程序的任何合适位置,包括程序的起始位置,以及其他合适位置。该通讯程序主要用于完成主机与加密锁之间的通讯,首先是使主机暂停程序运行,并在该通讯程序的控制下,进行存储单元的映射;然后控制所述加密锁虚拟机运行存储在该虚拟机上的指令段;加密锁虚拟机运行完存储在该虚拟机中的指令段后,在该通讯程序控制下,将加密锁虚拟机中存储单元的内容反映射到主机,然后控制主机继续运行程序。该通讯程序中具有主机的内存、寄存器、堆栈与加密锁的内存、寄存器、堆栈的对应关系,以便运行到此后,可以在主机与虚拟机的存储单元之间进行映射和反映射。所述对应关系,在步骤S104对选定指令段进行适应性转换时,在转换过程中,记录该对应关系以便记录到通讯程序中。
步骤S105,保存上述经过变换后的.exe文件。
上述步骤将一个可执行文件转换为了被保护的程序,该程序分为两部分,其中一小部分存储在加密锁虚拟机中。执行该程序,必须使加密锁虚拟机与主机连接,使主程序能够通过通讯程序将程序交给加密锁虚拟机运行。
经过上述处理,所述的待保护程序获得保护,成为被保护程序。
请参看图2,该图为本实施例中执行所述被保护程序的方法流程图。以下结合该流程图对该程序中置入加密锁虚拟机部分的程序段的执行过程进行详细说明。
步骤S201,启动所述被保护程序的运行过程,主机将程序调入内存。
运行用户程序时,计算机首先需要将程序调入内存,以便读取和执行
步骤S202,开始运行该程序。
计算机CPU读取内存中的程序,并且根据该程序的指令执行相应的命令。运行中,该程序会有许多中间结果放入主机寄存器、堆栈以及主机内存。
步骤S203,运行至被写入加密锁的程序段,主机根据写在该位置处的调用通讯程序指令调用所述通讯程序,并在该通讯程序的控制下寻找加密锁虚拟机以及进行存储单元映射等工作。
该步骤是本实施例中的关键步骤,为了更好的说明,请参看图3。图3中示出加密锁虚拟机301、主机302,以及它们内部的CPU、寄存器、内存、堆栈等。该图示出映射和反映射的相关步骤。
所述调用通讯程序的指令首先向CPU提供加密锁虚拟机中通讯程序的地址,CPU根据该地址得以调用该通讯程序,在该通讯程序的控制下,加密锁开始运行其中保存的指令段,主机则处于等待结果的状态。
该步骤为图3中304所示。
由于主机在程序执行中产生许多中间结果,放入寄存器、内存、堆栈等各种主机的存储单元中,如果希望虚拟机正确执行程序,就需要将在虚拟机中执行的程序段涉及的寄存器、内存、堆栈等中存储的内容进行主机到虚拟机的映射。所谓映射,就是将主机中存储单元的内容,写入虚拟机中对应的存储单元中。经过映射后,所述虚拟机的寄存器、内存、堆栈等就与主机具有相同的内容,使虚拟机对所保存的程序段的运行结果和该程序段在主机中运行完全相同。如图3中所示,图3中的306代表寄存器映射,308代表内存映射,310代表堆栈映射。如前所述,由于通讯程序中包含主机寄存器、内存、堆栈与虚拟机的寄存器、内存、堆栈的对应关系,因此,该种映射过程可以根据上述对应关系方便的完成。当然,上述过程并非将主机中所有的寄存器、堆栈、内存内容全部都映射到虚拟机中,而是仅仅将与虚拟机中保存的程序段相关的内容映射到虚拟机中。
步骤S204,虚拟机处理保存在其中的指令段。同时,主机处于等待状态。
由于上述步骤已经实现了将虚拟机的环境、中间存储元件的存储结果等转换为主机中的运行环境和存储结果,因此,此时虚拟机根据存储在其中的程序段执行程序将获得与主机中运行该程序段相同的结果。所述程序段由加密锁虚拟机的CPU运行。
步骤S205,加密锁虚拟机将运行结果反映射到主机上,主机得到结果停止等待,继续程序的运行。
所述加密锁虚拟机已经获得所存储的程序段的运行结果,这些运行结果全部存储在加密锁虚拟机的内存、寄存器和堆栈上。这些结果必须传送到主机的对应内存、寄存器和堆栈上,才能使在加密锁虚拟机上的运行结果反映到主机上。具体的传送过程与上述步骤S203的过程相反,称之为反映射。如图3所示,305将虚拟机寄存器的内容反映射到主机相应的寄存器上;307将虚拟机内存的内容反映射到主机内存中;309将所述虚拟机堆栈的内容反映射到所述主机堆栈上。经过上述过程,最终使在虚拟机上获得的运行结果,反映到主机的存储单元中,这样,在虚拟机上运行就取得与主机上运行相同的结果。最后,进行图3中的303,使主机继续运行程序。上述过程,都是在所述通讯程序的控制下完成的,虚拟机可以从通讯程序获知主机和虚拟机的存储单元对应关系,从而进行正确的反映射。
经过上述对软件设置加密锁保护和运行软件的过程的介绍,可以看出,该实施例提供的技术方案能够在加密锁实现X86虚拟机的基础上,正确的运行待保护的程序,使程序得到有效的保护。
在本实施例中,软件保护装置是加密锁。另外,软件保护装置实现X86虚拟机时,无需实现对X86系列的所有指令都可以运行的虚拟机,该虚拟机只需要能够运行部分重要指令即可。此时选择放入虚拟机的指令段时,要选择指令段中的所有指令都可以在该X86虚拟机上运行的指令段。
对于以上第一实施例中提供的方法,具体可以采用多种形式的装置实现。以下第二实施例提供一种实现上述方法的装置。
请参看图4,为该实施例提供的装置的单元组成框图。该装置的使用环境包括主机和实现了X86虚拟机的加密锁或者其他形式的软件保护装置。
本实施例中提供的装置包括软件加密设置单元41、执行单元42。
所述软件加密设置单元41用于实现对待保护程序设置软件加密,也就是在待保护程序中选择合适的程序段写入加密锁等软件保护装置中,并对写入加密锁的程序进行相应的处理。
所述软件加密设置单元41包括:选取单元411、转换单元412、程序写入单元413、调用指令写入单元414、通讯程序写入单元415。
所述选取单元411,用于读取有待保护的程序,并从中挑选部分指令段,作为写入软件保护装置的指令段输出。
所述有待保护的程序包括许多指令段,可以从中选择重要的指令段作为写入软件保护装置的指令段。为此,可以确定一种选择规则,以便选取单元411根据该规则在待保护程序中选择重要的指令段。进行所述选择时,该待保护程序应当已经转化为可执行文件的形式。实际上,该单元的功能也可以通过人工实现。
所述转换单元412,用于接收所述选取单元411输出的指令段,将该指令段中的主机内存地址、寄存器名、堆栈地址等转换为软件保护装置虚拟机的内存地址、寄存器名、堆栈地址,并输出经过上述处理的程序段。
由于主机的存储单元环境与虚拟机中不同需要将主机中相关存储单元的运行结果转换为虚拟机环境下的存储单元,才能实现在虚拟机中运行该程序段。转换单元412将所选择的程序段中的相关存储单元转换为虚拟机中的存储单元后输出。该转换单元412同时输出上述存储单元在主机与虚拟机中的对应关系。
所述程序写入单元413,用于接收所述转换单元412输出的经过转换的程序段,并将该程序段写入所述软件保护装置虚拟机中;同时从待保护程序中去除被选取单元411选中的该程序段。
所述调用指令写入单元414,用于根据被选取单元挑选的具体指令段位置,向所述待保护程序写入调用通讯程序的指令。所述调用通讯程序的指令用于使程序运行到被选中指令段时,能够获得如何调用通讯程序的信息。该调用指令应当与被选中指令段具有一定的关联,例如位于被选中指令段在程序中的原位置,以便程序运行时,能够知道何时需要获得该指令段,以及从何处获得该指令段。当然,在采用直接将通讯程序写入到被选中指令段的原位置的方法时,可以不使用该单元。
所述通讯程序写入单元415,用于向写入软件保护装置的程序段中写入通讯程序。
所述通讯程序的作用在于,当运行到被选中指令段位置时,控制主机停止运行,并且实现主机存储单元到虚拟机存储单元的映射,然后使虚拟机运行存储在其上的指令段;当虚拟机运行结束后,在该通讯程序控制下,虚拟机存储单元中的内容反映射到主机,然后控制主机继续运行程序。该通讯程序由所述通讯程序写入单元415写入主机程序的合适位置。所述通讯程序实现已经编好,但是其中的一些数据需要根据具体情况变化。主要的数据是有关主机与虚拟机的存储单元的对应关系,这些对应关系由所述转换单元412输出,这些数据记录在所述通讯程序中,以便后续映射单元421和反映射单元422使用。
所述执行单元42的作用在于执行加密后的程序。该程序执行过程主要是由主机运行该程序,由软件保护装置的虚拟机运行写入虚拟机的程序段。运行过程中,当主机运行到被选中指令段时,在通讯程序的控制下,实现主机存储单元到虚拟机存储单元的映射,并且控制虚拟机运行所存储的指令段;当虚拟机运行完毕后,通讯程序控制虚拟机将存储单元内容反映射到主机,最终由主机继续运行程序。
所述映射单元421,其作用在于在运行所述被保护程序时,当运行到所述选定程序时,该映射单元421根据所述通讯程序的记录,读取主机中所述选定程序段涉及的内存、寄存器、堆栈中的内容,并将上述存储单元中的内容写入软件保护装置虚拟机中对应的内存、寄存器、堆栈中。
反映射单元422,该单元在所述软件保护装置虚拟机运行完其存储的选定程序段后,读取所述虚拟机中与该程序段相关的内存、寄存器、堆栈中的内容,并根据通讯程序中有关主机与虚拟机的内存地址、寄存器名、堆栈地址对应关系的记录,将上述内容分别写入主机中相应的内存、寄存器、堆栈中。
以上所述仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。