钩子透明加密技术和过滤驱动加密技术

超时代视频加密软件系列产品均采用过滤驱动透明加密技术对大文件的视频流进行加密,完美地解决了加密强度与效率之间的问题,成为视频加密产品的行业标杆。

钩子透明加密技术

早期的透明加密的技术手段大多是通过API钩子技术进行,其工作方式为静态加密和重定向,基本思想为钩子程序拦截到受保护文件的打开操作,先将已加密的文件拷贝到一个临时目录中,然后告诉驱动程序把这个文件隐藏起来,然后解密这个文件,并将这个临时文件返回给打开文件的进程,这样打开的就是磁盘上的一个明文文件,用户程序可以进行正常的处理,这里文件是进行了整体的拷贝并解密;在文件关闭时,钩子拦截到以后,将那个明文的临时文件加密,然后再拷贝回来覆盖掉原文件。
简单的讲,就是打开文件时,将加密文件的副本拷贝到隐蔽位置,然后把这个文件解密、打开,保存时再把临时文件加密后覆盖原文件。这种加密实质上是通过临时文件来实现的,为了确保明文和密文之间的一致性,必须在每次用户存盘或者系统自动存盘的时候对整个文件进行一次整体加密和并复制到用户文件原来存储的位置,因此效率较低,且由于在计算机上保存了完整的明文文件,只要跟踪到临时文件所在位置即可能泄密,此外,文件在打开和存储过程中需要多次复制,效率损失很大,HookAPI的方式对于一些程序不能够完美的支持,兼容性有待考证。
由于文件映射的存在,在应用层进行动态加密比较困难,虽然原理上有一定的可行性,但是其加密效率、兼容性、可移植性、稳定性较之于内核层的过滤驱动加密要差很多,好处在于开发难度较小,网络操作能力强。

过滤驱动透明加密技术

1 驱动技术简介

过滤驱动加密技术是基于windows的文件系统过滤驱动(IFN)技术,工作在Windows的内核层。它是目前炙手可热的一门技术,其特点是技术门槛较高,需要深入理解windows系统内核,开发过程中稍有不慎就会破坏系统内核,因此核心技术仅被少数几家实力雄厚的公司所掌握。
文件过滤驱动是把文件作为一种设备来处理的一种虚拟驱动,WindowsNF系统内核采用堆栈式可扩展驱动模型J,原则上可以在任何一个层次上加载自己的过滤驱动,但是加载的层次不同,开发的难度和应用价值也不同,现在的技术主要还是加载在文件系统驱动的上层,这样就可以充分利用并扩充文件系统的现有功能],该技术在病毒实时监控与防护、数据备份与还原以及文件访问控制等领域都有着非常广泛的应用。
过滤驱动中几种非常重要的概念包括驱动对象、设备对象、设备堆栈、I/O堆栈,驱动对象标示驱动程序,设备对象记录加载的设备,一个驱动对象可以有多个设备对象构成设备对象链表,设备堆栈用于记录所有驱动程序的设备,I/O栈用来记录穿越设备堆栈时的操作属性,操作的对象为IRP(I/O Request Package),IRP包由系统的某个组件创建,类似于Windows应用程序的“消息”概念,要处理某种数据只需要把IRP包传送到相应驱动的相应派遣函数中。

2 加密的基本思想

在Windows NT内核操作系统中,应用程序的一次数据请求的过程如图2所示:只有在无缓存或者FAST I/O不可用的情况下才在硬盘上读取数据,因此只用拦截IRP->F1agS为IRP_NOCACHE(表示I/O请求从存储的媒介而不是高速缓存中读取数据)、IRP—PAGING—IO(表示此时执行内存页的I/O操作)和IRP—SYNCHRONOUS—PAGING—1O(表示内存页需要同步更新,此标志也是由内存管理器使用)的数据包,对于写数据的IRP包,在其分发例程中嵌入加密算法完成加密动作,而对于读数据的IRP包,在IRP包的完成例程中嵌入解密算法,对得到的数据进行解密处理。

3 写数据加密的实现

在用户写受保护的文件时,文件加解密客户端能透明地对文件写入的内容进行加密。加密文件判别模块判别出此文件为受保护文件后,将密钥传递给加解密过滤驱动,并由过滤驱动完成写操作。为了使过滤驱动能够加密对文件的写操作,需要拦截IRP—MJ—WRITE和IRP—MJ—DEVICE—CONTROL两种IRP。当应用层进程调用API:DeviceIOControl时,向系统发出IRP—MJ—DEVICE—CONTROL,过滤驱动可以通过处理此IRP获得传递给驱动的加密密钥,进而在拦截IRP—MJ—WRITE的例程中进行加密。
下面将分别介绍这两个例程的实现。
(1)处理IRP—MJ—DEVICE—CONTROL例程。
首先获得应用层程序在IRP中携带的输人数据其操作代码,如果携带了传递密钥的操作代码,例程将存储密钥,并直接完成此IRP,否则将IRP交给底层驱动处理。
伪代码如下:
NTSrATUS EneryptDeviceControl(INPDEVICE—OBJECT DeviceObiect,IN PIRP Irp)
{
PVOID inputBuffer;
ULONG inputBufferLength;
Irp->loStatus.Smtus=STATUS—SUCCESS;
Irp->loStams.Information=O;
ioControlCode=irpStack->Parameters.DeviceIoContro1.IoControlCode;
inputBuffer=Irp->AssociaredIrp.SystemBuffer;
inputBufferLength=irpStack->Parameters.DeviceIoContro1.InputBufferLength;
if(ioControlCode==INPUT—KEY)
{
SetKey(inputBuffer);//将输入的加密密钥保存起来
IoCompleteRequest(Irp,IO—NO—INCREMENT);//完成此IRP
Return STATUS-SUCCESS;
}
//接下来将IRP继续下发传递给下层的驱动处理
……
……
}
(2)处理IRP—MJ—WRITE例程。
需要区分IRI携带数据的两种方式,由MDL结构指定或直接包含数据的指针。
其实现的伪代码如下:
NTSTATUS EncryptWrite(IN PDEVICE-OBJECT DeviceObject,IN PIRP Irp)
{
……//完成初始化的工作
PIO—STACK—LOCATION irpsp=loGetCurrentIrpStackLocation(Irp);
switch(irpsp->MinorFunction)
{
case IRP—MN—N0RMAI;
{
if(Irp->MdlAddmss!=NULL)//判断写的数据是否是在MDL结构中
{
产生一个新的MDL结构,将其指向一个加密后的数据库,并将Irp->MdlAddress指针指向新的MDL结构
}
else
{
buffer=Irp->UserBuffer;
Encrypt(buffer,GetKey());//加密所写的数据
}
……//其它的必要操作
}
3.4 读数据解密的实现
在用户读受保护的文件时,文件加解密客户端能透明地对读出的原始内容进行解密。加密文件判别器判别出此文件为受保护文件后,将密钥传递给加解密过滤驱动,并由过滤驱动完成读操作,和写操作类似,需要拦截IRP—MJ—WRITE和IRP一MJ一DEVICE—CONTROL两种IRP。IRP—MJ—DEVICE-CONTROl例程的用途和实现方式和加密时相同。过滤驱动拦截IRP—MJ—READ的例程中进行加密。IRP—MJ—READ例程的实现需要利用完成例程,在完成例程中完成加解密过程。
下面将介绍这个例程的实现。
NTSrATUS EncryptWrite(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
……初始化操作
KeInitializeEvent(&waitEvent,NotificationEvent,FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
loSetCompletionRoutine(IrP,EncryptReadCompletion,&waitEvent,TRUE,TRUE,TRUE);//设置完成例程
status=IoCallDriver(devExt->AttachedToDeviceObject,Irp);
if(STATUS—PENDING==status)
{
status=KeWaitForSingleObject(&waitEvent,Executive,KernelMode,FALSE,NULL);//等待完成例程发出的解密完成消息
}
IoCompleteRequest(Irp,IO-NO—INCREMENT);
ReturnSTATUS—SUCCESS
}
代码中首先初始化一个消息事件,将消息事件作为参数传递给完成例程,接着调用底层驱动获得读出的数据,IRP返回后系统将启动一个新的线程来执行完成例程。
主线程等待消息事件,同时完成例程执行数据的解密操作,解密完成后完成例程发送消息事件,这样主线程被唤醒并正常返回。
完成例程的伪代码如下:
NTSTATUS SfReadCompletion(IN PDEVICE—OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)
{
PKEVENT event=Context;
ASSERT(IS—MY—DEVICE—OBJECT(DeviceObject));
……//完成初始化的工作
PIO—TSACK—LOCATION irpsp=IoGetCurrentIrpStackLocation(Irp);
switch(irpsp->MinorFunction)
{
case IRP—MN—NORMAL;
{
if(Irp->MdlAddress!=NULL)//判断读的数据是否是在MDL结构中
}
产生一个新的MDL结构,将其指向一个解密后的数据块,并将Irp->MdlAddress指针指向新的MDL结构,从而返回被解密的数据
}
else
{
buffer=Irp->UserBuffer;
Decrypt(buffre,GetKey());//解密文件
}
……//其它的必要操作
KeSetEvnet(event,IO—NO—INCREMENT,FALSE);//向主例程发送完成解密的消息
return STATUS_MORE_PROCESSING_ERQUIERD;
}

透明加密技术的分类比较

从底层技术来看, 透明加密产品可分为采用钩子模式和采用驱动模式的两种流派,两种加密技术由于工作在不同的层面, 从应用效果、开发难度上各有特点。

* 钩子透明加密技术

所有Windows应用程序都是通过 windows API函数对文件进行读写的。程序在打开或新建一个文件时, 一般要调用 windows的Create File或Open File、Read File等Windows API函数; 而在向磁盘写文件时要调用Write File函数。

同时windows提供了一种叫钩子 ( Hook) 的消息处理机制, 允许应用程序将自己安装一个子程序到其他的程序中, 以监视指定窗口某种类型的消息。当消息到达后, 先处理安装的子程序后再处理原程序。

钩子透明加密技术就是将上述两种技术组合而成的。通过windows的钩子技术, 监控应用程序对文件的打开和保存, 当打开文件时, 先将密文转换后再让程序读入内存, 保证程序读到的是明文, 而在保存时, 又将内存中的明文加密后再写入到磁盘中。

钩子透明加密技术与应用程序密切相关, 它是通过监控应用程序的启动而启动的。一旦应用程序名更改, 则无法挂钩。同时, 由于不同应用程序在读写文件时所用的方式方法不尽相同, 同一个软件不同的版本在处理数据时也有变化, 钩子透明加密必须针对每种应用程序、甚至每个版本进行开发。目前不少应用程序为了限止黑客入侵设置了反钩子技术, 这类程序在启动时, 一旦发现有钩子入侵, 将会自动停止运行。驱动加密技术基于windows的文件系统(过滤)驱动(FS)技术, 工作在windows的内核层。我们在安装计算机硬件时, 经常要安装其驱动,如打印机、U 盘的驱动。文件系统驱动就是把文件作为一种设备来处理的一种虚拟驱动。当应用程序对某种后缀文件进行操作时, 文件驱动会监控到程序的操作, 并改变其操作方式, 从而达到透明加密的效果。

* 驱动透明加密技术

驱动加密技术与应用程序无关, 他工作于 w in- dow sAPI函数的下层。当API函数对指定类型文件进行读操作时, 系统自动将文件解密; 当进入写操作时, 自动将明文进行加密。由于工作在受 w indow s保护的内核层, 运行速度更快, 加解密操作更稳定。

但是, 驱动加密要达到文件保密的目的, 还必须与用户层的应用程序打交道。通知系统哪些程序是合法的程序, 哪些程序是非法的程序。驱动透明加密工作在内核层。

驱动加密技术虽然有诸多的优点, 但由于涉及到w indow s底层的诸多处理, 开发难度很大。如果处理不好与其他驱动的冲突, 应用程序白名单等问题, 将难以成为一个好的透明加密产品。

* 两种技术比较

两种加密技术由于工作在不同的层面, 从应用效果、开发难度上各有特点。下表从几个方面进行了简单比较:

表 1钩子透明加密与驱动透明加密比较表

项目 钩子透明加密 驱动透明加密
工作层面 用户层 内核层
工作方式 Hook应用程序和文件类型 接受系统IRP进行处理
与应用程序关联性 直接与程序工作方式相关,对新应用程序加密或应用程序升级可能需要再开发。 与程序工作方式无关,但监控应用程序名单。
加解密可靠性 应用层加解密,大文件易死机。速度慢。 内核层加解密,受windows保护,稳定性较好,速度快。
网络操作能力 不受限制 需要专门处理

开发难度 Hook技术, 相对较容易 驱动技术, 开发难度较大。采用钩子模式开发相对容易, 但由于控制的层面较高, 很多底层的操作难以控制, 和各种应用程序之间的兼容性需要特殊处理。所以相对容易受到应用版本的限制, 一旦应用修改了读写方法, 加密软件必须跟着修改。

采用驱动模式是从更为底层的层面进行控制,可以获得更高的安全性和效率, 但是技术难度很大。底层的操作需要顾及系统的各个层面之间的协调处理, 由于驱动中程序的健壮性更多由程序本身决定, 难以依赖操作系统对错误进行处理, 如果这个驱动存在缺陷或者被某些程序异常终止 (例如出现未预料的错误), 在系统底层无任何保护措施的环境下, 最直接的后果就是系统蓝屏崩溃。