Windows驱动--创建日志文件

提示:原创不易,未经允许,不可擅自转载


前言

有时候当我们不想用windbg、dbgview等工具查看驱动信息,又想知道一些关键的数据时,我们就可以新建一个log日志用来查看当前驱动的运行状况了。


一、创建日志文件

驱动中创建文件一般会用到NtCreateFile、ZwCreateFile、IoCreateFile这几个函数。这里用ZwCreateFile来举例。

ZwCreateFile函数原型如下:

NTSYSAPI NTSTATUS ZwCreateFile(
  [out]          PHANDLE            FileHandle,
  [in]           ACCESS_MASK        DesiredAccess,
  [in]           POBJECT_ATTRIBUTES ObjectAttributes,
  [out]          PIO_STATUS_BLOCK   IoStatusBlock,
  [in, optional] PLARGE_INTEGER     AllocationSize,
  [in]           ULONG              FileAttributes,
  [in]           ULONG              ShareAccess,
  [in]           ULONG              CreateDisposition,
  [in]           ULONG              CreateOptions,
  [in, optional] PVOID              EaBuffer,
  [in]           ULONG              EaLength
);

代码如下(示例):

RtlInitUnicodeString(&FileName, L"\\??\\C:\\test.log");
InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

Status = ZwCreateFile(
    &FileHandle, 
    GENERIC_WRITE | GENERIC_READ, 
    &ObjectAttributes, 
    &IoStatusBlock, 
    NULL, 
    FILE_ATTRIBUTE_NORMAL, 
    FILE_SHARE_READ, 
    FILE_OPEN_IF, 
    FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_ALERT,
    NULL,
    0);
if (!NT_SUCCESS(Status)) {
    // Handle error.  
    KdPrint(("Test: Failed to ZwCreateFile file.\n"));
    goto done;
}

需要注意的是,这里的文件名要以符号链接名(“\??\C:\test.log”)的形式,即在C盘目录下创建名为test.log的日志文件。还需要将该文件置为内核模式,即设置OBJ_KERNEL_HANDLE。参数CreateOptions也会影响到文件创建成功与否。

二、写入日志文件

驱动中创建文件一般会用到NtWriteFile、ZwWriteFile、IoWriteFile这几个函数。这里用ZwWriteFile来举例。

ZwWriteFile函数原型如下:

NTSYSAPI NTSTATUS ZwWriteFile(
  [in]           HANDLE           FileHandle,
  [in, optional] HANDLE           Event,
  [in, optional] PIO_APC_ROUTINE  ApcRoutine,
  [in, optional] PVOID            ApcContext,
  [out]          PIO_STATUS_BLOCK IoStatusBlock,
  [in]           PVOID            Buffer,
  [in]           ULONG            Length,
  [in, optional] PLARGE_INTEGER   ByteOffset,
  [in, optional] PULONG           Key
);

代码如下(示例):

Status = ZwWriteFile(
    FileHandle, 
    NULL, 
    NULL, 
    NULL, 
    &IoStatusBlock,
    WriteBuffer,
    BufferLen,
    &Offset,
    NULL);
if (!NT_SUCCESS(Status)) {
    // Handle error.
    KdPrint(("Test: Failed to ZwWriteFile file.\n"));  
    goto done;
}

WriteBuffer字符串数据,要写入test.log中的文本信息;BufferLen字符串数据大小;Offset偏移量,即是写入文本中的位置。

三、读取日志文件

驱动中创建文件一般会用到NtReadFile、ZwReadFile、IoReadFile这几个函数。这里用ZwReadFile来举例。

ZwReadFile函数原型如下:

NTSYSAPI NTSTATUS ZwReadFile(
  [in]           HANDLE           FileHandle,
  [in, optional] HANDLE           Event,
  [in, optional] PIO_APC_ROUTINE  ApcRoutine,
  [in, optional] PVOID            ApcContext,
  [out]          PIO_STATUS_BLOCK IoStatusBlock,
  [out]          PVOID            Buffer,
  [in]           ULONG            Length,
  [in, optional] PLARGE_INTEGER   ByteOffset,
  [in, optional] PULONG           Key
);

代码如下(示例):

Status = ZwReadFile(
    FileHandle,
    NULL,
    NULL,
    NULL,
    &IoStatusBlock,
    ReadBuffer,
    BufferLen,
    NULL,
    NULL
);
if (!NT_SUCCESS(Status)) {
    // Handle error.
    KdPrint(("Test: Failed to ZwReadFile file.\n"));
    goto done;
}
KdPrint(("Test: read buffer: %s.\n", ReadBuffer));

ReadBuffer字符串数据,从test.log中读取的文本信息会被保存到该变量中;BufferLen指定读取字符串数据的大小;ByteOffset为null,表示从内容首行开始读取。

全部代码

代码如下(示例):

    NTSTATUS Status;
    HANDLE FileHandle = NULL;
    IO_STATUS_BLOCK IoStatusBlock;
    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING FileName;
    LARGE_INTEGER Offset;
    CHAR WriteBuffer[1024];
    CHAR ReadBuffer[1024];
    ULONG BufferLen;

    RtlInitUnicodeString(&FileName, L"\\??\\C:\\test2.log");
    InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

    Status = ZwCreateFile(
        &FileHandle, 
        GENERIC_WRITE | GENERIC_READ, 
        &ObjectAttributes, 
        &IoStatusBlock, 
        NULL, 
        FILE_ATTRIBUTE_NORMAL, 
        FILE_SHARE_READ, 
        FILE_OPEN_IF, 
        FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_ALERT,
        NULL,
        0);
    if (!NT_SUCCESS(Status)) {
        // Handle error.  
        KdPrint(("Test: Failed to ZwCreateFile file.\n"));
        goto done;
    }
    
    Offset.HighPart = -1;
    Offset.LowPart = FILE_WRITE_TO_END_OF_FILE;// | FILE_USE_FILE_POINTER_POSITION;

    BufferLen = sizeof("Hello World!");
    RtlCopyMemoryNonTemporal(WriteBuffer, "Hello World!\r\n", BufferLen);
    Status = ZwWriteFile(
        FileHandle, 
        NULL, 
        NULL, 
        NULL, 
        &IoStatusBlock,
        WriteBuffer,
        BufferLen,
        &Offset,
        NULL);
    if (!NT_SUCCESS(Status)) {
        // Handle error.
        KdPrint(("Test: Failed to ZwWriteFile file.\n"));  
        goto done;
    }

    Status = ZwReadFile(
        FileHandle,
        NULL,
        NULL,
        NULL,
        &IoStatusBlock,
        ReadBuffer,
        BufferLen,
        NULL,
        NULL
    );
    if (!NT_SUCCESS(Status)) {
        // Handle error.
        KdPrint(("Test: Failed to ZwReadFile file.\n"));
        goto done;
    }
    KdPrint(("Test: read buffer: %s.\n", ReadBuffer));

    ZwClose(FileHandle);

done:
    if (NT_SUCCESS(Status)) {
        KdPrint(("Test: File created successfully.\n"));
    }
    else {
        KdPrint(("Test: Failed to create file. Status = 0x%08X\n", Status));
    }
    return Status;

总结

以上只是对Zw库的对文件操作的API的简单使用,实际驱动开发会更为复杂,应根据实际项目需要选择合适的API。

参考

【1】ZwCreateFile 函数 (wdm.h)
【2】ZwWriteFile 函数 (wdm.h)
【3】ZwReadFile 函数 (wdm.h)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值