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等系統特有的目錄則不進行加密,

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章