关于 TrueCrypt 第4集

08.09.05
 
昨天看了下在 应用层 与 驱动 进行通信的方法, 回想一下
1、CreateFile 打开设备
2、DeviceIoControl 发设备发送控制指令
3、CloseHandle 关闭设备
 
今天应该看下在 驱动.sys 需要做哪些东西,才可以在应用层使用 "设备路径" 来访问了
首先写一个不能再简单的驱动先!
 
simpledriver.c
#include  < ntddk.h >

#define  DEVICE_NAME      L"\\SimpleDriver"
#define  DEVICE_LINK_NAME L"\\SimpleDriver_Link"

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
VOID     DriverUnload(IN PDRIVER_OBJECT DriverObject);

#pragma code_seg(
" INIT " )

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{   
    NTSTATUS status 
= STATUS_SUCCESS; 
    UNICODE_STRING uniNameString;
    UNICODE_STRING uniLinkString;
    DEVICE_OBJECT 
*pCDO = NULL;
    
    KdPrint((
"SimpleDriver!DriverEntry \n"));
    
    RtlInitUnicodeString(
&uniNameString, DEVICE_NAME);
    status 
= IoCreateDevice(DriverObject, 0&uniNameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &pCDO);

    
if!NT_SUCCESS(status) )
        
return status; 
    
    RtlInitUnicodeString(
&uniLinkString, DEVICE_LINK_NAME);
    status 
= IoCreateSymbolicLink(&uniLinkString, &uniNameString);

    
if(!NT_SUCCESS(status))
        
return status;                                          

    DriverObject
->DriverUnload = DriverUnload;

    
return STATUS_SUCCESS;
}


#pragma code_seg(
" PAGE " )

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING uniNameString;

    PAGED_CODE();
    
    KdPrint((
"SimpleDriver!DriverUnload \n"));

    RtlInitUnicodeString(
&uniNameString, DEVICE_LINK_NAME);
    IoDeleteSymbolicLink(
&uniNameString);

    IoDeleteDevice(DriverObject
->DeviceObject);
}


#pragma code_seg()


sources
TARGETNAME = simpledriver
TARGETPATH
= OBJ
TARGETTYPE
= DRIVER
SOURCES
= simpledriver.c \

makefile
#
# DO NOT EDIT THIS FILE
!!!  Edit .\sources. If you want to add a  new  source
# file to 
this  component. This file merely indirects to the real make file
# that 
is  shared by all the driver components of the Windows NT DDK
#

! INCLUDE $(NTMAKEENV)\makefile.def

为了让 应用层 可以用 DeviceIoControl() 与应用程序通信,我们需要在 DriverEntry() 里设置
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;

NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS status 
= STATUS_SUCCESS;
    ULONG nIoCtrlCodes 
= 0;  // IO控制码
    PIO_STACK_LOCATION IrpStack = NULL;   //IRP堆栈
    
    KdPrint((
"SimpleDriver!DeviceControl \n"));
    
    
//得到当前调用者的IRP 
    IrpStack = IoGetCurrentIrpStackLocation(Irp);   
    
    nIoCtrlCodes 
= IrpStack->Parameters.DeviceIoControl.IoControlCode;
    
    KdPrint((
"SimpleDriver!DeviceControl IoControlCode = %d\n", nIoCtrlCodes));
    
    status 
= Irp->IoStatus.Status; 
    IoCompleteRequest(Irp, IO_NO_INCREMENT); 
    
return status; 
}


应用层的代码为:

#include  < windows.h >
#include 
< winioctl.h >
#include 
< stdio.h >
  
BOOL talkWithDriver()
{
    HANDLE hDevice;    
    BOOL bResult;      
    DWORD junk;        
  
    hDevice 
= CreateFile("\\SimpleDriver",  // drive to open
                    0,                // no access to the drive
                    FILE_SHARE_READ | // share mode
                    FILE_SHARE_WRITE,
                    NULL,             
// default security attributes
                    OPEN_EXISTING,    // disposition
                    0,                // file attributes
                    NULL);            // do not copy file attributes
  
    
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
  printf(
"CreateFile Error ErrCode = %d", ::GetLastError());
        
return (FALSE);
    }

  
    bResult 
= DeviceIoControl(hDevice,     // device to be queried
                              IOCTL_DISK_GET_DRIVE_GEOMETRY,     // operation to perform
                              NULL, 0,               // no input buffer
                              NULL, 0,     // output buffer
                              &junk,                 // # bytes returned
                              (LPOVERLAPPED) NULL);  // synchronous I/O
 
 
if ( !bResult )
 
{
  printf(
"CreateFile Error ErrCode = %d", ::GetLastError());
  
return FALSE;
 }

  
    CloseHandle(hDevice);
  
    
return (bResult);
}

  
int  main( int  argc,  char   * argv[])
{  
 talkWithDriver ();
  
    
return 0;
}


编译后的驱动 .sys 用 OSRLOADER.exe 工具加载成功
运行应用层的 .exe 时,则显示 CreateFile Error ErrCode = 2

找不到路径

尝试将应用层的CreateFile 的路径改为
\\SimpleDriver
\\\\SimpleDriver
\\\\.\\SimpleDriver
还是显示 CreateFile Error ErrCode = 2

CreateFile 打开失败的原因未知!编译后的驱动 .sys 用 OSRLOADER.exe 工具加载成功
运行应用层的 .exe 时,则显示 CreateFile Error ErrCode = 2

找不到路径

尝试将应用层的CreateFile 的路径改为
\\\\SimpleDriver
\\\\.\\SimpleDriver
\\\\.\\SimpleDriver:
\\SimpleDriver
\\.\\SimpleDriver

结果还是显示 CreateFile Error ErrCode = 2

Google到了一个驱动的例子,按照例子里面的路径修改了一下
sys修改为:
#define DEVICE_NAME      L"\\DosDevices\\SimpleDriver"

app修改为:
CreateFile("\\\\.\\SimpleDriver"

结果 CreateFile 调用后,GetLastErrorCode 得到的是 1,  (Incorrect function. )
再次 Google 才知道,需要写 IRP_MJ_CREATE 例程,才可以 CreateFile 成功
于是把代码改了一下 

.sys 代码

#include  < ntddk.h >

#define  DEVICE_NAME      L"\\DosDevices\\SimpleDriver"
#define  DEVICE_LINK_NAME L"\\SimpleDriver_Link"

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
VOID     DriverUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DeviceCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

#pragma code_seg(
" INIT " )

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{   
    NTSTATUS status 
= STATUS_SUCCESS; 
    UNICODE_STRING uniNameString;
    UNICODE_STRING uniLinkString;
    DEVICE_OBJECT 
*pCDO = NULL;
    
    KdPrint((
"SimpleDriver!DriverEntry \n"));
    
    RtlInitUnicodeString(
&uniNameString, DEVICE_NAME);
    status 
= IoCreateDevice(DriverObject, 0&uniNameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &pCDO);

    
if!NT_SUCCESS(status) )
        
return status; 
    
    RtlInitUnicodeString(
&uniLinkString, DEVICE_LINK_NAME);
    status 
= IoCreateSymbolicLink(&uniLinkString, &uniNameString);

    
if(!NT_SUCCESS(status))
        
return status;                                          

    DriverObject
->DriverUnload = DriverUnload;
    DriverObject
->MajorFunction[IRP_MJ_CREATE]         = DeviceCreateClose;
    DriverObject
->MajorFunction[IRP_MJ_CLOSE]          = DeviceCreateClose;
    DriverObject
->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
    

    
return STATUS_SUCCESS;
}


#pragma code_seg(
" PAGE " )

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING uniNameString;

    PAGED_CODE();
    
    KdPrint((
"SimpleDriver!DriverUnload \n"));

    RtlInitUnicodeString(
&uniNameString, DEVICE_LINK_NAME);
    IoDeleteSymbolicLink(
&uniNameString);

    IoDeleteDevice(DriverObject
->DeviceObject);
}


NTSTATUS DeviceCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    PAGED_CODE();

    KdPrint((
"SimpleDriver!DeviceCreateClose \n"));

    Irp
->IoStatus.Status = STATUS_SUCCESS;
    Irp
->IoStatus.Information = FILE_OPENED;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    
return STATUS_SUCCESS;
}


NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS status 
= STATUS_SUCCESS;
    ULONG nIoCtrlCodes 
= 0;  // IO控制码
    PIO_STACK_LOCATION IrpStack = NULL;   //IRP堆栈
    
    KdPrint((
"SimpleDriver!DeviceControl \n"));
    
    
//得到当前调用者的IRP 
    IrpStack = IoGetCurrentIrpStackLocation(Irp);   
    
    nIoCtrlCodes 
= IrpStack->Parameters.DeviceIoControl.IoControlCode;
    
    KdPrint((
"SimpleDriver!DeviceControl IoControlCode = 0x%X\n", nIoCtrlCodes));
    
    status 
= Irp->IoStatus.Status; 
    IoCompleteRequest(Irp, IO_NO_INCREMENT); 

    
return status; 

}


#pragma code_seg()

应用层 exe 代码
#include  < windows.h >
#include 
< winioctl.h >
#include 
< stdio.h >
  
BOOL talkWithDriver()
{
    HANDLE hDevice;    
    BOOL bResult;      
    DWORD junk;        
  
    hDevice 
= CreateFile("\\\\.\\SimpleDriver",  // drive to open
                    0,                // no access to the drive
                    FILE_SHARE_READ | // share mode
                    FILE_SHARE_WRITE,
                    NULL,             
// default security attributes
                    OPEN_EXISTING,    // disposition
                    0,                // file attributes
                    NULL);            // do not copy file attributes
  
    
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    {
        printf(
"\\\\.\\SimpleDriver CreateFile Error ErrCode = %d", ::GetLastError());
        
return (FALSE);
    }

  
    bResult 
= DeviceIoControl(hDevice,     // device to be queried
                              IOCTL_DISK_GET_DRIVE_GEOMETRY,     // operation to perform
                              NULL, 0,               // no input buffer
                              NULL, 0,     // output buffer
                              &junk,                 // # bytes returned
                              (LPOVERLAPPED) NULL);  // synchronous I/O
 
    
if ( !bResult )
    
{
        printf(
"DeviceIoControl Error ErrCode = %d", ::GetLastError());
        
return FALSE;
    }

        

    
if!CloseHandle(hDevice) );
    
{
        printf(
"CloseHandle Error ErrCode = %d", ::GetLastError());
        
return FALSE;
    }


    
return (bResult);
}

  
int  main( int  argc,  char   * argv[])
{  
    talkWithDriver ();
  
    
return 0;
}


重新用 OSRLOADER.exe 加载驱动,终于 CreateFile 成功了
Windbg 调试显示

SimpleDriver!DriverEntry
SimpleDriver!DeviceCreateClose
SimpleDriver!DeviceControl
SimpleDriver!DeviceControl IoControlCode = 0x70000
SimpleDriver!DeviceCreateClose
SimpleDriver!DriverUnload

但让我奇怪的是
应用层显示:
CloseHandle Error ErrCode = 0

CloseHandle 返回 FALSE, 但 GetLastError 得到的是 0

1、驱动层与应用层 的设备路径是如何对应的?
     驱动层创建的设备路径是
\\DosDevices\\SimpleDriver
     而对应的应用层的路径是 \\\\.\\SimpleDriver
     为何会跟驱动层的不一致?
--  Thx 网友 Bill Gates

    你完全理解错了device name和symbolic link name的意义。
    用winobj看下你机器上的kernel namespace。

    应用层如果用CreateFile,只能访问到\\??下的路径。如果用ZwCreateFile,可以访问整个命名空间。

2、CloseHandle() 为何会调用失败,而返回的 LastErrorCode 为0 ?
-- 未解决

你可能感兴趣的:(关于 TrueCrypt 第4集)