从Windows 10内核模式驱动程序登录到txt文件

时间:2018-03-04 02:44:58

标签: c logging linker windows-kernel

我希望从Windows 10内核模式驱动程序(C)进行一些日志记录。我在驱动程序中有很多日志记录但是在这个实例中我无法附加内核调试器,因此我想将调试字符串转储到txt文件(或甚至是事件日志)。

例如,这是一个例子

#include <stdio.h>
#include <stdlib.h>
VOID Log(char * text) {
    FILE *f = fopen("c:\\temp\\logger.txt", "a+");
    if (f == NULL) return;

    fprintf(f, "%s\n", text);

    fclose(f);
}

但是我得到了

driver.obj : error LNK2019: unresolved external symbol fclose referenced in function Log
driver.obj : error LNK2019: unresolved external symbol fopen referenced in function Log
tdriver.obj : error LNK2019: unresolved external symbol fprintf referenced in function Log

我已经包含了stdio.h,还有什么我需要做的才能将其链接起来吗?

或者是因为这是一个内核驱动程序我不能使用这些库并且必须执行不同的低级别过程才能写入日志文件?

编辑:看来我无法使用内核驱动程序中的fopen。

我尝试了这个,但没有任何内容写入文件。我根据这个例子编写了代码:

https://support.microsoft.com/en-us/help/891805/how-to-open-a-file-from-a-kernel-mode-device-driver-and-how-to-read-fr

我改变的是将标志设置为FILE_OPEN_IF以附加文件(如果文件已存在)。我知道每次打开和关闭手柄都是非常低效的,但我现在只是在测试。

VOID Log(char* text) {

    UNICODE_STRING     uniName;
    OBJECT_ATTRIBUTES  objAttr;

    RtlInitUnicodeString(&uniName, L"\\SystemRoot\\example.txt");  // or L"\\SystemRoot\\example.txt"
    InitializeObjectAttributes(&objAttr, &uniName,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        NULL, NULL);

    HANDLE   handle;
    NTSTATUS ntstatus;
    IO_STATUS_BLOCK    ioStatusBlock;

    // Do not try to perform any file operations at higher IRQL levels.
    // Instead, you may use a work item or a system worker thread to perform file operations.

    if (KeGetCurrentIrql() != PASSIVE_LEVEL) return;
        //return STATUS_INVALID_DEVICE_STATE;

    ntstatus = ZwCreateFile(&handle,
        GENERIC_WRITE,
        &objAttr, &ioStatusBlock, NULL,
        FILE_ATTRIBUTE_NORMAL,
        0,
        FILE_OPEN_IF,
        FILE_SYNCHRONOUS_IO_NONALERT,
        NULL, 0);

    CHAR     buffer[BUFFER_SIZE];
    size_t  cb;

    if (NT_SUCCESS(ntstatus)) {
        ntstatus = RtlStringCbPrintfA(buffer, sizeof(buffer), text, 0x0);
        if (NT_SUCCESS(ntstatus)) {
            ntstatus = RtlStringCbLengthA(buffer, sizeof(buffer), &cb);
            if (NT_SUCCESS(ntstatus)) {
                ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock,
                    buffer, (ULONG)cb, NULL, NULL);
            }
        }
        ZwClose(handle);
    }
}

1 个答案:

答案 0 :(得分:2)

如果您确实需要从内核模式驱动程序进行日志记录,我建议您查看WMI / WPP跟踪。这将能够足够快地记录,以便能够跟上大多数内核事件,这些事件记录到文件或调试器不是很好。它还允许您在生产/发布驱动程序中进行跟踪而不影响性能,这样您就可以让客户收集日志并进行分析。

https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/wpp-software-tracing