首页> 中国专利> 一种在软件保护装置中简化实现.Net虚拟机的系统和方法

一种在软件保护装置中简化实现.Net虚拟机的系统和方法

摘要

本发明提供了一种在软件保护装置中简化实现.Net虚拟机的系统和方法,属于信息安全领域。所述在软件保护装置中简化实现.Net虚拟机的系统包括:内存管理模块、指令解析模块、加载模块、系统库模块和接口库模块。所述方法包括如下步骤:实现内存管理;实现可加载核心代码的加载器;实现核心代码解析的指令解析器;实现系统库;以及实现接口库。本发明通过在软件保护装置中实现内存管理装置、指令解析装置、加载装置、系统库装置和接口库装置,从而实现了.Net虚拟机,允许用户根据自己的需要选择不同的.Net开发语言,将其植入软件保护装置,解决了软件保护装置内存有限的问题。

著录项

  • 公开/公告号CN101593258A

    专利类型发明专利

  • 公开/公告日2009-12-02

    原文格式PDF

  • 申请/专利权人 北京飞天诚信科技有限公司;

    申请/专利号CN200810113144.2

  • 发明设计人 陆舟;于华章;

    申请日2008-05-28

  • 分类号G06F21/22(20060101);G06F9/455(20060101);

  • 代理机构

  • 代理人

  • 地址 100083 北京市海淀区学院路40号研7楼5层

  • 入库时间 2023-12-17 23:10:12

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2011-09-21

    专利权人的姓名或者名称、地址的变更 IPC(主分类):G06F21/22 变更前: 变更后: 申请日:20080528

    专利权人的姓名或者名称、地址的变更

  • 2010-09-08

    授权

    授权

  • 2010-01-27

    实质审查的生效

    实质审查的生效

  • 2009-12-02

    公开

    公开

说明书

技术领域

本发明属于信息安全领域,尤其涉及一种在软件保护装置中简化实现.Net虚拟机的系统和方法。

背景技术

.Net是微软的新一代技术平台,是全新的基于互联网的跨语言软件开发平台,顺应了当今软件工业分布式计算、面向组件、企业级应用、软件服务化和以Web为中心等大趋势。.Net并非开发语言,但是在.Net开发平台上可以支持多门开发语言。.Net最突出的一个特点是它能够使用户通过Web与众多智能设备相交互,同时确保用户而不是应用程序控制这个交互。这就使得微软.Net体验是极具个性化、综合化的体验,这种体验通过与XMLWeb服务相连的智能设备来实现。这些智能设备是一种具有Web功能的工具,如个人电脑、掌上电脑、智能电话,在这些设备中配上软件,这些软件使得它们在与用户、网络、信息及其它设备和服务的交互过程中更加智能化。

.Net语言的编译分为两个阶段,首先高级语言被编译成一种称作IL(中间代码)的中间语言,与高级语言相比,IL更像是机器语言,然而,IL却包含一些抽象概念(比如:类、异常),这也是这种语言被称为中间语言的原因。高级语言在初次被编译时,编译器做两件事:首先把编译得到的IL存储在DLL或EXE中,然后为类的每个方法创建一个stub函数,此函数会调用即时编译器,并将自身的地址作为参数传给编译器。即时编译器则从DLL或EXE中获取相应的IL,编译成机器语言,并将内存中的原零时调用函数替换成机器语言。stub函数再调用编译器,将自身编译为本地机器语言。JIT是一个典型的即时编译器,JIT编译器在每段代码执行前进行编译,编译的结果为本地静态机器码,如x86指令程序的运行环境下的机器码。

.NET Framework没有限制应用程序的类型,它可以实现开发的应用程序包括:Windows应用程序、Web应用程序、Web服务和其他各种类型的应用程序。由此.NET Framework的设计方式保证它可以用于各种语言比如:C#语言、C++、Visual Basic、JScript,甚至一些旧的语言,如COBOL。.NET Framework功能实现主要在于它包含一个非常大的代码库和.NET公共语言运行库(CommonLanguage Runtime,CLR),代码库使得客户可以在客户语言(如C#)中通过面向对象编程技术(OOP)来使用这些代码,而.NET公共语言运行库负责管理用.NET库开发的所有应用程序的执行。所以,使用.NET Framework编写应用程序,实质就是使用.NET代码库编写代码,编程语言被目标操作系统能够理解,需要编译代码,将.NET Framework代码库中的代码变译成Microsoft的中间语言。

所谓虚拟机,可以把它想象成一台用软件来模拟的机器,在这台机器里有处理器、内存、寄存器等各种硬件,模拟执行各种指令,在这台机器上运行的软件对运行环境没有特殊要求,所以虚拟机对在它上运行的程序是透明的。例如,x86虚拟机模拟的是x86指令程序的运行环境,c51虚拟机模拟的是c51指令程序的运行环境

软件保护装置是一种通过标准的个人计算机接口提供信息加密处理的便携式设备。它内置单片机或智能卡芯片,可以存储密钥或数字证书,利用软件保护装置内置的密码算法实现对信息的加密功能。软件保护装置能够很好地保护软件版权,防止盗版。加密锁(又称加密狗或软件狗)是一种常见的软件保护装置。

在现有技术中,虚拟机一般是用于PC机的。对于软件保护装置,由于存储空间、内存有限,在其中安装虚拟机有一定的难度。而且,即使在其中实现了虚拟机,也难以用其来运行代码。

发明内容

为解决现有技术中,软件保护装置存储空间和内存有限,虚拟机难以在软件保护装置中实现的问题,本发明提供了一种在软件保护装置中简化实现.Net虚拟机的系统和方法。

一方面,本发明提供了一种在软件保护装置中简化实现.Net虚拟机的系统,具体包括:内存管理模块、指令解析模块、加载模块、系统库模块和接口库模块;

所述内存管理模块连接于所述加载模块,用于管理内存的分配、回收及复用;

所述指令解析模块连接于所述加载模块、系统库模块及接口库模块,用于在软件保护装置中写入的代码在软件保护装置中运行时,将代码运行时的中间指令(IL指令)解析成虚拟机所能运行的指令;

所述加载模块连接于所述指令解析模块,用于写入软件保护装置中的代码在软件保护装置中运行时,根据所述指令解析模块的需要将指定的内容加载到内存中;

所述系统库模块连接于所述指令解析模块,用于在软件保护装置中模拟主机上的系统库;

所述接口库模块连接于所述指令解析模块,用于实现主机和软件保护装置及软件保护装置内各部分之间的通信。

所述软件保护装置为加密锁。

所述内存管理模块通过引用计数(reference count)和/或垃圾回收(garbagecollection)机制来管理内存。

本发明还提供了一种在软件保护装置中简化实现.Net虚拟机的方法,具体如下:

1)、实现内存管理

由于系统内存很小,采用多种内存分配策略以达到最优使用内存;内存根据需要分为两个池,分别为固定大小内存池,可变内存池;通过引用计数(referencecount)和/或垃圾回收(garbage collection)机制来管理内存;

2)、实现可加载核心代码的加载器

在解析运行代码时,根据需要在被执行的文件中寻找相应的内容加载到内存中供指令解析使用;

3)、实现核心代码解析的指令解析器

实现用于控制整个执行流程的指令解析器;

4)、实现系统库

实现相应的系统调用及功能;

5)、实现接口库

实现主机和软件保护装置以及软件保护装置内各部分之间的通信。

所述一种在软件保护装置中简化实现.Net虚拟机的方法,还可以包括核心代码简化优化的步骤。

所述核心代码简化优化的方法可以但不限于哈希算法、函数数组等。

所述实现内存管理是指实现内存的分配、回收及复用。

所述步骤2中,在软件保护装置中实现加载器,是为了将写入软件保护装置的代码分段加载到软件保护装置的内存。

所述步骤3,在软件保护装置中实现(植入)的系统库与主机中的系统库相对应。

有益效果:本发明通过在软件保护装置中实现内存管理装置、加载装置、指令解析装置、系统库装置和接口库装置,从而在软件保护装置中实现了.Net虚拟机,允许用户根据需要选择不同的.Net开发语言,将其植入软件保护装置,解决了软件保护装置内存有限的问题。

附图说明

图1是本发明实施例一种在软件保护装置中简化实现.Net虚拟机的系统的结构示意图。

图2是本发明实施例一种在软件保护装置中简化实现.Net虚拟机的方法的流程图。

具体实施例

为使本发明的目的、技术方案和优点更加清楚,下面将结合附图对本发明实施方式作进一步地详细描述。

如图1所示,本发明提供了一种在软件保护装置中简化实现的.Net虚拟机的一个优选实施例。在本实施例中,软件保护装置具体为加密锁。本实施例中用户使用VS2005微软最新的IDE环境,以托管代码中任一代码类型开发其所需软件,并将该软件中核心代码植入到加密锁。如图中所示,该加密锁中实现.Net虚拟机的系统包括内存管理模块101、加载模块102、指令解析模块103、系统库模块104和接口库模块105;

内存管理模块101连接于加载模块102,用于管理内存的分配、回收及复用;由于系统内存很小,采用多种内存分配策略以达到最优使用内存;内存根据需要分为两个池,分别为固定大小内存池,可变内存池;通过引用计数(reference count)和/或垃圾回收(garbage collection)机制来管理内存;

加载模块102连接于内存管理模块101和指令解析模块103,用于在被保护核心代码在加密锁中运行时,根据指令解析模块103的需要将被保护核心代码加载到内存中;

指令解析模块103连接于加载模块102、系统库模块104、接口库模块105,用于被保护核心代码在软件保护装置中运行时,实现用软件保护装置所能运行的指令模拟被保护核心代码运行后得到的中间指令;

系统库模块104连接于指令解析模块103,用于在加密锁内实现系统库,实现核心代码在加密锁内运行需要调用系统库时,直接在锁内调用;

接口库模块105连接于指令解析模块103,用于在加密锁内实现接口库,完成主机、加密锁及加密锁内部各组成部分的通信。

如图2所示,本发明还提供了一种在软件保护装置中简化实现.Net虚拟机的方法,软件保护装置连接于主机,软件保护装置中已写入核心代码,软件保护装置具体为加密锁,具体如下:

201、实现内存管理

由于系统内存很小,采用多种内存分配策略以达到最优使用内存;内存根据需要分为两个池,分别为固定大小内存池,可变内存池;通过引用计数(referencecount)和/或垃圾回收(garbage collection)机制来管理内存。

202、在加密锁中实现可加载核心代码的加载器

本实施例中,加密锁的内存有限,实现核心代码加载就是分段把核心代码加载到加密锁内存,进而需要在加密锁内植入加载器,加载器其实就是虚拟机在运行过程中定位文件中的数据,譬如要想知道入口点,加载器根据文件结构获取入口点然后返回,如果还想知道入口点函数的IL代码,加载器则返回给虚拟机入口点函数代码在文件中的偏移。

本实施例获取.Net程序入口点的步骤和代码,具体如下:

.Net  程序都有IMAGE_COR20_HEADER结构,获取IMAGE_COR20_HEADER结构后,IMAGE_COR20_HEADER.EntryPointToken是入口点TOKEN

PIMAGE_DOS_HEADER                m_pDosHeader;

PIMAGE_NT_HEADERS                 m_pNtHeader;

PIMAGE_FILE_HEADER            m_pFileHeader;

PIMAGE_OPTIONAL_HEADER     m_pOptionalHeader;

PIMAGE_SECTION_HEADER     m_pSectionHeader;

PIMAGE_DATA_DIRECTORY     m_pDataDirectory;

 PIMAGE_COR20_HEADER_X        m_pCor20x;

   //m_lpBase为内存PE的映像

m_pDosHeader=(PIMAGE_DOS_HEADER)m_lpBase;

  m_pNtHeader=(PIMAGE_NT_HEADERS)

((BYTE*)m_pDosHeader+m_pDosHeader->e_lfanew);

  m_pFileHeader=(PIMAGE_FILE_HEADER)

((BYTE*)m_pDosHeader+m_pDosHeader->e_lfanew+4);

  m_pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)

((BYTE*)m_pNtHeader+4+sizeof(IMAGE_FILE_HEADER));

  m_pCor20x=Rva2Raw_x(m_pOptionalHeader->DataDirectory

[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress);

  Token EntryToken=m_pCor20x.EntryPointToken;

203、在加密锁中实现可实现核心代码解析的指令解析器

实际应用中,用户开发被保护软件所用的任一类型托管代码在主机上运行时,先运行得到IL中间语言,然后,微软虚拟机在运行IL中间语言时将其编译成机器语言,实现被保护软件的功能;本实施例中,核心代码在加密锁内运行时,是通过指令解析完成核心代码的运行,从而实现核心代码的功能,返回主机所需核心代码运行结果。核心代码简化优化的方法为哈希算法或函数数组。

譬如主机中,被保护软件运行得到的IL中间语言中有个add,具体运行过程如下:

static void add(int a,ing b)

{

     return a+b;

}

这个函数编译后的IL是:

.method private hidebysig static int32’add’(int32a,

                                              int32b)cil managed

// SIG:00 02 08 08 08

{

  //方法在RVA 0x2109处开始

  //代码大小      4(0x4)

  .maxstack 8

  IL_0000:/*02   |                */ldarg.0

  IL_0001:/*03   |                */ldarg.1

  IL_0002:/*58   |                */add

  IL_0003:/*2A   |                */ret

}

在加密锁内,核心代码运行得到的IL中间语言有个add,加密锁内应用相应的c语言实现add的功能,具体为:首先获取传入参数的值,然后把两个参数入栈,遇到add时把栈顶的两个元素出栈然后相加,再把结果入栈,最后返回

PushStack(arg.0)//把0号参数即第一个参数的值入栈

PushStack(arg.1)//把1号参数即第二个参数的值入栈

PushStack(PopStack(1)+PopStack(1))//把栈顶两个数据出栈相加后把结果压栈

Return//返回

然后用C编译器编译成及其语言既可完成相同的功能。

204、在加密锁中实现系统库

实际应用中,程序在主机运行过程中要调用系统库,例如:

C#:

  static string String ToUpper(string a)

   {

       string c=a.ToUpper();

       return c;

   }

    IL:

.method private hidebysig static string String ToUpper(string a)cil managed

// SIG:00 01 0E 0E

{

  // 方法在RVA 0x210c处开始

  // 代码大小      9(0x9)

  .maxstack 1

  .locals init(string V_0)

  IL_0000: /*02   |                   */ldarg.0

  IL_0001: /*6F   | (0A)000018        */callvirt  instance string

[mscorlib]System.String::ToUpper()

  IL_0006: /*0A   |                   */stloc.0

  IL_0007: /*06   |                   */ldloc.0

  IL_0008: /*2A   |                   */ret

    } // end of method RsaTest::String_ToUpper

而在加密锁中是不存在系统库的,程序运行到需要调用系统库时,加密锁以自身虚拟机中模拟的系统库完成程序对系统库的调用,例如:代码

在上面的IL里面调用了一个[mscorlib]System.String::ToUpper函数,这个是系统库里面的函数,虚拟机中重新实现了这个函数(string_ToUpper())

PushStack(arg.0)//把0号参数即第一个参数的值入栈

string_ToUpper()//现在调用的是重新实现的把字符串全部变成大写的函数

loc.0=PopStack(1)//把栈顶数据即转换后的字符串赋给第一个局部变量

PushStack(loc.0)//把第一个局部变量的值入栈(返回值)

Return//返回

最终实现的系统库与主机中的系统库相对应。

205、在加密锁中实现接口库

本实施例中,接口库的实现和上面实现系统库一样,这里有一个我们提供的.net动态库,封装了调用加密锁的一些接口,譬如RSA加解密,DES、ECC等等,虚拟机里面也要实现前面被封装的那些接口函数。下面的例子是一个调用RSA加密的示例:

  C##:

  ret=rsa.Encrypt(tData.ref rLength);

  IL:

IL_0052: /*07     |                  */ldloc.1

  IL_0053: /*12    | 00               */ldloca.s  V_0

  IL_0055: /*6F    | (0A)000014       */callvirt  instance uint8

[Feitian.Rockey7]Feitian.Rockey7.RSA::Encrypt(uint8[],

int32&)

    VM:

在上面的IL里面调用了一个[Feitian.Rockey7]Feitian.Rockey7.RSA::Encrypt函数,这个是接口库里面的函数,虚拟机中重新实现了这个函数(RSA_Encrypt())

PushStack(loc.1)//把1号局部变量即第二个局部变量的值入栈

PushStack(GetAddress(loc.0))//把0号局部变量即第一个局部变量的地址入栈

RSA_Encrypt()//调用重新实现的RSA加密

从而,可以实现主机和加密锁以及加密锁内各部分之间的通信。

以上所述仅为本发明的较佳实施例,并不用以限制本发明,凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号