PGP透明加解密研究-----简要技术分析


技术分析

⑴.主要派遣例程

IRP_MJ_CREATE例程

对应的函数: CFilterEngine::DispatchCreate(DEVICE_OBJECT *device, IRP *irp)

如果是自己的设备访问则直接放过

if(device ==CFilterControl::s_control)

   {

       irp->IoStatus.Status  = STATUS_SUCCESS;

      irp->IoStatus.Information =FILE_OPENED;     

      IoCompleteRequest(irp,IO_NO_INCREMENT);

      return STATUS_SUCCESS;

   }

 再次判断一些系统进程请求如:svchost.exe则放过不进行加解密操作

if(SkipCreate(device,irp))

   {

      status = irp->IoStatus.Status;

      IoCompleteRequest(irp,IO_DISK_INCREMENT);      

      return status;

   }

1.   PreCreate阶段:初次判断当前状态,并标志上下文flag,以便在PostCreate阶段进行相应操作

extension->Volume.PreCreate(irp,track),pre-Create函数中首先判断经过candidate.NormalizeCreate(irp),此函数判断当前irp是否来自网络重定向器,如果来自网络重定向器的请求则返回失败禁止访问,这样可以防止访问网络共享。若果不是则返回到成功到pre-Create函数,接下来判断SL_OPEN_TARGET_DIRECTORY标志,如果是应用的访问必须是带有SL_OPEN_TARGET_DIRECTORY标志,这个标志表示当前访问的文件或者文件夹的父路径已经被打开,内核层的访问不必有这个标志。就接下来就是判断是否是系统相关的目录比如系统盘:/windows ,temp,Document and Setting,IE等等,如果是这些目录则不进行加解密,实现函数是IsSpecific(track,TRACK_SYSTEM | TRACK_IE_CACHE),如果不是这些目录则开始检查当前文件夹下的配置文件,如果当前访问的文件或者文件夹的当前文件夹不存在配置文件,则检查父目录是否存在配置文件,如果不存在则不对当前访问的对象加解密,如果父目录存在配置文件则在当前上下文中设置TRACK_AUTO_CONFIG标志,在postcreate生成一个配置文件。

2.PostCreate阶段

根据PreCreate阶段分析的结果过设置的标志位,如果标志位是TRACK_AUTO_CONFIG标志,则根据父目录的配置信息,在当前文件夹生成一个配置文件,成功后上下文标志为待加密状态,TRACK_YES标志,以便在IRP_MJ_WRITE派遣例程中判断标志是否加密。如果此文件夹已经存在配置文件,即之前已经访问过此加密文件夹,则直接把加密链表的加密信息复制到当前上下文加密中。

IRP_MJ_WRITE例程

1. extension->Volume.CheckFileCooked(file, &link)

首先检查加密文件对象cooked中是否存在当前文件夹对象,如果不存在直接调用下一层驱动,存在则进行加密操作。

2.extension->Volume.m_context->Tracker().Check(file) &FILFILE_TRACKER_BYPASS

检查当前文件类型是否属于不被加密操作文件类型,不被加密的文件类型,则WriteBypass(extension,irp, &link),直接写文件原文,不加密。

3. WriteAlreadyEncrypted(extension,irp);

检查当前文件是否已经被加密

4.EstimateCaching(extension,irp, file, &link)

如果文件没有被加密,检查IRP是否需要缓存.

5.写文件

根据文件对象是否需要缓存的标志,来采用不同的方式来写

IRP_MJ_READ例程

1. extension->Volume.CheckFileCooked(file, &link)

首先检查文件对象cooked中是否存在当前文件夹对象,如果不存在直接调用下一层驱动,存在则在后续操作中进行解密操作。

2.extension->Volume.m_context->Tracker().Check(file) &FILFILE_TRACKER_BYPASS

   检查当前文件类型是否属于不被加密操作文件类型,不被加密的文件类型,则ReadBypass(extension,irp, &link);直接调用下一层驱动。

3.检查是否读取到文件尾

4.如果没有读取到文件尾部,检查文件是否需要缓存,如果需要则解密读取并缓存

不需要则直接解密文件数据

IRP_MJ_DEVICE_CONTROL例程

应用层代理和驱动层交互例程CFilterEngine::DispatchDeviceControl

1.   IOCTL_FILFILE_GET_STATE

获得驱动的状态,驱动的状态有下面几种

enumDriverState            {  

Unknown,                // 错误未知状态

      NotInstalled,            // 没有被安装

      Active,                    //安装了被激活状态

      Passive,                 // 安装了没有被激活

   };

2. IOCTL_FILFILE_SET_STATE

设置驱动的状态,设置Active激活态和Passive不激活态。

Active激活态:对加密文件夹实施透明加解密

Passive不激活态:不对加密文件夹实施透明加解密

2.   IOCTL_FILFILE_GET_HEADER

获得加密文件头信息

3.   IOCTL_FILFILE_SET_HEADER

设置加密文件头

4.   IOCTL_FILFILE_ENTITY

加密文件夹入口点信息管理链表的信息的添加与删除

5.   IOCTL_FILFILE_ENUM_ENTITIES

从加密文件夹信息管理链表中获得入口点数量及信息。

6.   IOCTL_FILFILE_ENCRYPTION

对指定文件进行加密

7.   IOCTL_FILFILE_CALLBACK_CONNECTION

应用层代理和驱动链接传递一些全局事件,这些事情作用就是用于请求密码的交互,即在

IOCTL_FILFILE_CALLBACK_REQUESTIOCTL_FILFILE_CALLBACK_RESPONSE交互

8.   IOCTL_FILFILE_ADD_CREDIBLE_PROCESS

添加可信进程,可信进程以及其子进程有权访问加密文件夹

9.   IOCTL_FILFILE_CALLBACK_REQUEST

驱动通过激活IOCTL_FILFILE_CALLBACK_CONNECTION传递进来的事件,是应用层发送

此控制码来请求待解密的密码数据

10.IOCTL_FILFILE_CALLBACK_RESPONSE

应用层代码通过IOCTL_FILFILE_CALLBACK_REQUEST请求的密码数据解密所得密码通过此控制码返回密码给驱动

11.IOCTL_FILFILE_OPEN_FILE

调用IoCreateFileSpecifyDeviceObjectHint函数打开文件,此函数打开文件可以直接从下层设备打开而不进入文件系统栈,避免文件系统重入问题

⑵.其他主要功能函数

1.  NTSTATUSCFilterCallback::Connect(HANDLErandom, HANDLE key,

                                                HANDLE notify)

HANDLErandom, HANDLE key, HANDLE notify,从应用层代理传进驱动的三个事件,分别是请求random随机数事件,请求加密解密Key事件,通知回调事件。

2.  应用层与驱动进行Key请求交互的函数

请求key函数

NTSTATUSCFilterCallback::FireKey(ULONGflags, FILFILE_TRACK_CONTEXT *track)

NTSTATUSCFilterCallback::RequestKey(ULONGflags, FILFILE_CONTROL_OUT *request,ULONG *requestSize)

NTSTATUSCFilterCallback::Request(ULONGflags, FILFILE_CONTROL_OUT *request,ULONG *requestSize)

返回key函数

NTSTATUSCFilterCallback::Response(ULONGcookie, UCHAR *response,ULONG responseSize)

3.  注册回调IoRegisterFsRegistrationChange

当一个文件系统激活或者解注册过滤驱动会得到一个通知,注册的回调函数FileSystemRegister,在此函数中实现了对FILE_DEVICE_DISK_FILE_SYSTEM磁盘文件系统的挂载,并生成了设备驱动的扩展设备设备,扩展设备结构为

structFILFILE_COMMON_EXTENSION

{

   USHORT        Type;

   USHORT        Size;

   DEVICE_OBJECT*    Device;

};

structFILFILE_VOLUME_EXTENSION

{

   FILFILE_COMMON_EXTENSION Common;//自己设备

   LIST_ENTRY               Link;

   DEVICE_OBJECT*             Real;//真实设备

   DEVICE_OBJECT*             Lower;

   ULONG                    LowerType;

   UNICODE_STRING             LowerName;

   CFilterVolume            Volume;

   bool                     System;

};

4.  NTSTATUSCFilterCipherManager::RecognizeHeader(

FILE_OBJECT *file,

CFilterHeader *header,

ULONGflags)

识别文件头的功能函数在检查文件夹存在一个pgpFs.INI配置文件后,首先就要检查加密文件头是否是本设备对象所识别的加密文件头。

文件头的结构如下:

structFILFILE_HEADER_BLOCK

{

   ULONG         Magic;       // 文件头标志: FilF;

   ULONG         Version;     // 文件头版本

   ULONG         Cipher;          //加密核心算法选择分为AES128 AES256 AES192

   ULONG         BlockSize;   //当前文件头Block大小

   ULONG         PayloadSize; //文件头bloak后的payload大小

   ULONG         PayloadCrc;  //Payloadcrc32校验和   

ULONG        Deepness;  // AutoConfig files only: Deepness of correspondig Entity [~0u:=INFINITE, 0:=1, ..., N:=N+1]

   ULONG         Reserved;    // not used yet

   LARGE_INTEGER Nonce;       // Nonce, unique for each file, combined with file Offset forms an IV

   UCHAR         FileKey[32]; // 驱动请求解密key的密码

};

加密文件开始即以上的FILFILE_HEADER_BLOCK结构,在这段结构之后即payload,两者加在一起是4K的大小。

验证文件头块的过程中首先验证文件头的Magic标志,如果标志位不是FilF,则是无效文件头,再次验证payloadcrc32校验和,计算payload校验和和FILFILE_HEADER_BLOCK. PayloadCrc不相等则是无效头文件,最后验证Cipher的高位和低位,高位必须是0xF,低位必须是{123}中的一个值,否则就是无效文件头,有效的文件头才可以实施透明加解密。

5. NTSTATUSCFilterBase::CreateFile(DEVICE_OBJECT*     device,

                                    UNICODE_STRING* path,

                                    ULONG           access,

                                    ULONG           share,

                                    ULONG           options,                                   ULONG           attribs,

                                    FILE_OBJECT**   file,

                                    HANDLE*      fileHandle)

设备驱动打开文件,函数中调用了IoCreateFileSpecifyDeviceObjectHint函数,此函数打开文件可以直接从下层设备打开而不进入文件系统栈,解决文件系统重入问题

6.NTSTATUSCFilterBase::ReadWrite(DEVICE_OBJECT *device,

FILE_OBJECT *file,

FILFILE_READ_WRITEconst* readWrite)

FILFILE_READ_WRITE结构如下

structFILFILE_READ_WRITE

{

              UCHAR*       Buffer;

              MDL*         Mdl;

              LARGE_INTEGEROffset;   

              ULONG        Length;

              ULONG        Flags;

              UCHAR        Major;

              BOOLEAN          Wait;

};

利用IRP同步转发的技术实现文件的同步读写,等待device设备返回结果,使用IoAllocateIrp分配IRP,根据FILFILE_READ_WRITE传入的参数设置IRP相关参数,最后通过IoCallDriver调用转发IRP到下一层设备中读取文件,跳过当前设备栈,设置等待事件,达到同步的目的,通过IoSetCompletionRoutine设置回调通知事件态,重新获得IRP的控制权,而获得读取或者写入文件数据。

7.CFilterVolume::IsSpecific(FILFILE_TRACK_CONTEXT *track,

ULONG flags)

检查一些特别目录的函数,如"//Documents and Settings//""//Local Settings//Temporary Internet Files//Content.IE5//"//Wndows等系统特有的目录则不进行加密,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值