freeotfe.c

来自「文件驱动加密,功能强大,可产生加密分区,支持AES,MD2,MD4,MD5MD2」· C语言 代码 · 共 1,966 行 · 第 1/5 页

C
1,966
字号
// Description: FreeOTFE Device Driver
// By Sarah Dean
// Email: sdean12@sdean12.org
// WWW:   http://www.FreeOTFE.org/
//
// -----------------------------------------------------------------------------
//


// #defines for debug purposes:
//
// #define DBG_CREATEINITDISKS 4
//   - If defined, then when the driver starts, it will automatically create the specified
//     number of disk devices
//   - Should all be COMMENTED OUT for release





#include <ntddk.h>
#include <stdio.h>

// Required for std disk device driver I/O control (IOCTL) codes
#include <ntdddisk.h>
// Required for std CDROM IOCTLs and structs (e.g. IOCTL_CDROM_READ_TOC)
#include <ntddcdrm.h>

#include <ntverp.h>  // Needed for VER_PRODUCTBUILD

#include "IFSRelated.h"

#include "FreeOTFEDebug.h"
#include "FreeOTFENULLGUID.h"
#include "FreeOTFEDriverlib.h"
#include "FreeOTFEDriverConstsCommon.h"
#include "FreeOTFElib.h"
#include "FreeOTFEGenerateBlockIV.h"
#include "FreeOTFECallModuleFn.h"
#include "FreeOTFEPlatform.h"

#include "FreeOTFE.h"
#include "FreeOTFEAPI.h"

#include "FreeOTFEHashAPI.h"
#include "FreeOTFECypherAPI.h"

// MAC implementations
#include "FreeOTFEMACHash.h"
#include "FreeOTFEMACHMAC.h"

// KDF implementations
#include "FreeOTFEKDFHashSaltedPassword.h"
#include "FreeOTFEKDFPBKDF2.h"

// Globals.
// Not nice, but...
HANDLE DirFreeOTFERoot  = NULL;
HANDLE DirFreeOTFEDisks = NULL;


// =========================================================================
// This routine is the driver's entry point, called by the I/O system
// to load the driver.  The driver's entry points are initialized.
// In DBG mode, this routine also examines the registry for special
// debug parameters.
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING devDirName;
    OBJECT_ATTRIBUTES dirObjAttribs;
    PDEVICE_OBJECT mainDevObj;
    PDEVICE_EXTENSION mainDevExt;
#ifdef DBG_CREATEINITDISKS
    int i;   
    PDEVICE_OBJECT dbgTmpDevObj;
#endif
    
    // The following debug handling was ripped from the MS DDK "floppy.c"
    // example
#if DBG
    // We use this to query into the registry as to whether we
    // should break at driver entry.
    RTL_QUERY_REGISTRY_TABLE paramTable[3];
    ULONG default_ShouldBreak = 0;           // Default to 0; no break
//    ULONG default_DebugLevel  = 0xFFFFFFFF;  // Default to all on
    ULONG default_DebugLevel  = 0x0000001F;  // All except verbose debug
    ULONG debugLevel = 0;
    ULONG shouldBreak = 0;
    PWCHAR path;
    ULONG pathLength;
    
    // Since the registry path parameter is a "counted" UNICODE string, it
    // might not be zero terminated.  For a very short time allocate memory
    // to hold the registry path zero terminated so that we can use it to
    // delve into the registry.
    //
    // NOTE NOTE!!!! This is not an architected way of breaking into
    // a driver.  It happens to work for this driver because the original
    // DDK example code for DriverEntry happened to be written in this manner.
    pathLength = RegistryPath->Length + sizeof(WCHAR);

    if (path = ExAllocatePool(PagedPool, pathLength)) {

        SecZeroMemory(&paramTable[0], sizeof(paramTable));
        SecZeroMemory(path, pathLength);
        RtlMoveMemory(path, RegistryPath->Buffer, RegistryPath->Length);

        paramTable[0].Flags         = RTL_QUERY_REGISTRY_DIRECT;
        paramTable[0].Name          = L"BreakOnEntry";
        paramTable[0].EntryContext  = &shouldBreak;
        paramTable[0].DefaultType   = REG_DWORD;
        paramTable[0].DefaultData   = &default_ShouldBreak;
        paramTable[0].DefaultLength = sizeof(ULONG);

        paramTable[1].Flags         = RTL_QUERY_REGISTRY_DIRECT;
        paramTable[1].Name          = L"DebugLevel";
        paramTable[1].EntryContext  = &debugLevel;
        paramTable[1].DefaultType   = REG_DWORD;
        paramTable[1].DefaultData   = &default_DebugLevel;
        paramTable[1].DefaultLength = sizeof(ULONG);

        if (!(NT_SUCCESS(RtlQueryRegistryValues(
                            RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
                            path,
                            &paramTable[0],
                            NULL,
                            NULL)))) {

            shouldBreak = default_ShouldBreak;
            debugLevel = default_DebugLevel;
        }

        ExFreePool(path);
    }

#if DBG
    FreeOTFEDebugLevel = debugLevel;
    DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Debug level   : %d\n", FreeOTFEDebugLevel));
#endif
    DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Driver version: 0x%08x (v%02d.%02d.%04d)\n",
                                     DRIVER_VERSION, 
                                     (DRIVER_VERSION & 0xFF000000) / 0x00FF0000,
                                     (DRIVER_VERSION & 0x00FF0000) / 0x0000FF00,
                                     (DRIVER_VERSION & 0x0000FFFF)
                                    ));
    
    if (shouldBreak == 1)
        {
        DbgBreakPoint();
        }
#endif

    DEBUGOUTMAINDRV(DEBUGLEV_ENTER, ("DriverEntry\n"));
   
    // Create main device dir
    DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Creating dir object (main)...\n"));
    status = CreateDeviceDir(
                DEVICE_FREEOTFE_ROOT,
                &DirFreeOTFERoot
               );
    if (!(NT_SUCCESS(status)))
        {
        DEBUGOUTMAINDRV(DEBUGLEV_ERROR, ("Unable to CreateDeviceDir (main)\n"));
        return status;
        }

    // Create disk device dir
    DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Creating dir object (disks)...\n"));
    status = CreateDeviceDir(
                DEVICE_DISK_DIR_NAME,
                &DirFreeOTFEDisks
               );
    if (!(NT_SUCCESS(status)))
        {
        DEBUGOUTMAINDRV(DEBUGLEV_ERROR, ("Unable to CreateDeviceDir (disks)\n"));
        ZwClose(DirFreeOTFERoot);
        return status;
        }

    // Create main device
    DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Creating main device...\n"));
    status = CreateMainDevice(DriverObject, &mainDevObj);
    if (!(NT_SUCCESS(status)))
        {
        DEBUGOUTMAINDRV(DEBUGLEV_ERROR, ("Call to CreateMainDevice FAILED.\n"));
        return status;
        }

    // Store the device dir handle for closure on unload
    mainDevExt = (PDEVICE_EXTENSION)mainDevObj->DeviceExtension;

#ifdef DBG_CREATEINITDISKS
    // Create initial disk devices
    for (i=1; i<=DBG_CREATEINITDISKS; i++)
        {
        DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Creating disk #%d device...\n", i));
        status = CreateDiskDevice(DriverObject, &dbgTmpDevObj);
        if (!(NT_SUCCESS(status)))
            {
            DEBUGOUTMAINDRV(DEBUGLEV_ERROR, ("Call to CreateDiskDevice FAILED.\n"));
            return status;
            }
        }
#endif    

    // Initialize the driver object with this driver's entry points.
    DriverObject->MajorFunction[IRP_MJ_CREATE] = 
                                            FreeOTFE_MF_DispatchCreate;
                                            
    DriverObject->MajorFunction[IRP_MJ_CLOSE] =
                                            FreeOTFE_MF_DispatchClose;
                                            
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
                                            FreeOTFE_MF_DispatchDeviceControl;
                                            
    DriverObject->MajorFunction[IRP_MJ_READ] =
                                            FreeOTFE_MF_DispatchRead;
                                            
    DriverObject->MajorFunction[IRP_MJ_WRITE] =
                                            FreeOTFE_MF_DispatchWrite;
    
    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = 
                                            FreeOTFE_MF_DispatchFlushBuffers;
    
// xxxop - prevent hibernate, standby, etc if drives are mounted
// xxxop - will finish implementing this once my testbox is configured to handle
//         hibernate & standby
//    DriverObject->MajorFunction[IRP_MJ_POWER] =
//                                            FreeOTFE_MF_DispatchPower;
                                            
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =
                                            FreeOTFE_MF_DispatchSystemControl;
 
    DriverObject->DriverUnload = DriverUnload;


    DEBUGOUTMAINDRV(DEBUGLEV_EXIT, ("DriverEntry\n"));    

    return status;
}


// =========================================================================
// Unload the driver from the system
VOID
DriverUnload(
    IN PDRIVER_OBJECT DriverObject
)
{
    PDEVICE_EXTENSION devExt;
    PDEVICE_OBJECT devObj;
    NTSTATUS status;
    
    DEBUGOUTMAINDRV(DEBUGLEV_ENTER, ("DriverUnload\n"));
    
    // TODOzzz: Dismount all first!!!???
    
    // Walk through all the device objects, shutting them down and deleting
    // them
    devObj = DriverObject->DeviceObject;
    while (devObj != NULL)
        {
        DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Found a device to destroy; destroying it...\n"));
        devObj = DestroyDevice(devObj);
        }

    status = ZwClose(DirFreeOTFERoot);
    status = ZwClose(DirFreeOTFEDisks);

    DEBUGOUTMAINDRV(DEBUGLEV_EXIT, ("DriverUnload\n"));

    return;
}


// =========================================================================
// Overwrite sensitive parts of the specified device's extension
// Given a device object, cleardown, free off and overwrite all sensitive
// parts of it's device extension which relate to DISK DEVICES
// (e.g. encryption/decryption keys, etc)
// !!! WARNING !!!
// This must only ever be called on a disk device which has been UNMOUNTED,
// with nothing remaining to be processed on it's thread's IRP queue
// Returns: Status
NTSTATUS
OverwriteDeviceSensitive(
  IN  PDEVICE_OBJECT devObj
)
{
    NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_EXTENSION devExt;
    NTSTATUS tmpStatus;
    IO_STATUS_BLOCK ioStatusBlock;

    DEBUGOUTMAINDRV(DEBUGLEV_ENTER, ("OverwriteDeviceSensitive\n"));

    devExt = (PDEVICE_EXTENSION)devObj->DeviceExtension;


    devExt->Mounted = FALSE;
    devExt->DismountPending = FALSE;
    

    // Tear down any filename...
    DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("(Filename)...\n"));  
    if (devExt->zzFilename.Buffer != NULL)
        {
        DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Freeing off filename unicode buffer...\n")); 
        SecZeroMemory(
                        devExt->zzFilename.Buffer,
                        sizeof(devExt->zzFilename.MaximumLength)
                       );
        ExFreePool(devExt->zzFilename.Buffer);
        devExt->zzFilename.Buffer = NULL;
        DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("OK.\n"));   
        }

    // File object pointer
    if (devExt->FileObject != NULL)
        {
        DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("Dereferencing file object...\n")); 
        ObDereferenceObject(devExt->FileObject);
        devExt->FileObject = NULL;
        DEBUGOUTMAINDRV(DEBUGLEV_INFO, ("OK.\n"));      
        }

    // Closedown any open
    // Return value ignored
    FileClose(
              &devExt->FileHandle,
              devExt->FileAttributesStored,
              &devExt->FileAttributes,
              &ioStatusBlock
             );

    // Timestamps/file attributes
    devExt->FileAttributesStored = FALSE;
    SecZeroMemory(
                  &devExt->FileAttributes,
                  sizeof(devExt->FileAttributes)
                 );

    // Information required for impersonation
    // Return value ignored
    ClientSecurityDestroy(&devExt->ClientContext);

    // Offset
    devExt->DataOffset.QuadPart = 0;

    // Encrypted block size
    devExt->EncryptionBlockSize = 0;

    // Simulated disk geometry
    devExt->HiddenSectors = 0;
    SecZeroMemory(
                  &devExt->DiskGeometry,
                  sizeof(devExt->DiskGeometry)
                 );
    SecZeroMemory(
                  &devExt->DiskSize,
                  sizeof(devExt->DiskSize)
                 );
    SecZeroMemory(
                  &devExt->PartitionSize,
                  sizeof(devExt->PartitionSize)
                 );

    // Readonly flag
    devExt->ReadOnly = TRUE;
    
    // Mount source (e.g. the volume file is a partition or file)
    devExt->MountSource = MNTSRC_UNKNOWN;

    // Storage media type (i.e. the type of device emulated)
    devExt->StorageMediaType = Unknown;

    // Prevent media removal; for removable disks only
    devExt->PreventMediaRemoval = FALSE;       


    // Tear down any IV hash related...
    FreeDeviceDetailsHash(&devExt->IVHash);

    // Tear down any IV cypher related...
    FreeDeviceDetailsCypher(&devExt->IVCypher);

    // Tear down any main cypher related...
    FreeDeviceDetailsCypher(&devExt->MainCypher);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?