简体   繁体   中英

Log to a txt file from a Windows 10 Kernel Mode driver

I am looking to do some logging from a Windows 10 Kernel mode driver (C). I have lots of logging inside the driver however in this instance I can't attach a kernel debugger so I would like to dump the debug strings to a txt file (or event log even).

Eg here is an example

#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);
}

However I get

 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 

I've included stdio.h, is there something else I have to do to get this linked?

Or is because this is a kernel driver I cannot use these libraries and must perform a different low level procedure to write to a log file?

edit: It appears I can't use fopen from a kernel driver.

I tried this, however nothing gets written to the file. I based the code on this example:

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

All I changed was setting the flag to FILE_OPEN_IF to append the file if it already exists. I know that opening and closing the handle everytime is very inefficient however I am simply testing right now.

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);
    }
}

If you really need to do logging from a kernel mode driver, I recommend that you look into WMI/WPP tracing. This will be able to log fast enough that it can keep up with most kernel events, which loging to a file or the debugger is not great for. It will also allow you to have tracing in your production/release driver without impacting performance so that you can enable customers to gather the logs and you can analyze them.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM