Windwos内核层写日志到文件

Windwos内核层写日志到文件

作者: yym439 时间: 2022-01-17

一、使用说明

  1. sources文件添加编译源码
  2. 在DriverEntry()函数中调用:Dbg_LoadInit()函数进行初始化
  3. DbgKeLog()打日志到文件

二、源码

1.头文件

#ifndef __CTLOG_Kx_File_H__
#define __CTLOG_Kx_File_H__

NTSTATUS Dbg_LoadInit();

BOOLEAN DbgKeLog(const char *lpszLog, ...);

#endif

2.源文件

#include "stdafx.h"

#define MAX_PROC_NAME_LEN 256

//
// Enable log event: for synchronization
//
static KEVENT gs_eventEnableKeLog;

static ULONG ProcessNameOffset = 0;


static ULONG GetProcessNameOffset(VOID)
{
    PEPROCESS curproc;
    int i;
    curproc = PsGetCurrentProcess();
    //
    // Scan for 12KB, hopping the KPEB never grows that big!
    //
    for (i = 0; i < 3 * PAGE_SIZE; i++)
    {
        if (!strncmp("System", (PCHAR)curproc + i, strlen("System")))
        {
            return i;
        }
    }
    //
    // Name not found - oh, well
    //
    return 0;
}


//---------------------------------------------------------
//
// initialize the ProcessNameOffset when the driver is loading.
// (Call in DriverEntry())
//
NTSTATUS ProcessInfo_LoadInit()
{
    ProcessNameOffset = GetProcessNameOffset();
    return STATUS_SUCCESS;
}

//---------------------------------------------------------
//
// initialization interface
//
//---------------------------------------------------------
//
// initialize the global data structures, when the driver is loading.
// (Call in DriverEntry())
NTSTATUS Dbg_LoadInit()
{
    // Initialize the event
    KeInitializeEvent(&gs_eventEnableKeLog, SynchronizationEvent, TRUE);
    ProcessInfo_LoadInit();
    return STATUS_SUCCESS;
}

static void WaitForWriteMutex()
{
    // Wait for enable log event
    KeWaitForSingleObject(&gs_eventEnableKeLog, Executive, KernelMode, TRUE, 0);
    KeClearEvent(&gs_eventEnableKeLog);
}

static void ReleaseWriteMutex()
{
    // Set enable log event
    KeSetEvent(&gs_eventEnableKeLog, 0, FALSE);
}

//----------------------------------------------------------------------
//
// GetCurrentTimeString
//
// Get current time string. (format: %d-%02d-%02d %02d:%02d:%02d)
//
//----------------------------------------------------------------------
static PCHAR GetCurrentTimeString()
{
    static CHAR szTime[128];
    LARGE_INTEGER SystemTime;
    LARGE_INTEGER LocalTime;
    TIME_FIELDS timeFiled;

    KeQuerySystemTime(&SystemTime);
    ExSystemTimeToLocalTime(&SystemTime, &LocalTime);
    RtlTimeToTimeFields(&LocalTime, &timeFiled);
    sprintf(szTime, "%d-%02d-%02d %02d:%02d:%02d", timeFiled.Year, timeFiled.Month, timeFiled.Day, timeFiled.Hour, timeFiled.Minute, timeFiled.Second);

    return szTime;
}


//----------------------------------------------------------------------
//
// GetCurrentProcessName
//
// Uses undocumented data structure offsets to obtain the name of the
// currently executing process.
//
//----------------------------------------------------------------------
static PCHAR GetCurrentProcessName()
{
    PEPROCESS curproc;
    char *nameptr;
    ULONG i;
    static CHAR szName[MAX_PROC_NAME_LEN];
    //
    // We only try and get the name if we located the name offset
    //
    if (ProcessNameOffset)
    {
        //
        // Get a pointer to the current process block
        //
        curproc = PsGetCurrentProcess();
        //
        // Dig into it to extract the name. Make sure to leave enough room
        // in the buffer for the appended process ID.
        //
        nameptr = (PCHAR)curproc + ProcessNameOffset;
        strncpy(szName, nameptr, MAX_PROC_NAME_LEN - 1);
        szName[MAX_PROC_NAME_LEN - 1] = 0;
        /* for 64 bit system
#if defined(_M_IA64)
        sprintf( szName + strlen(szName), ":%I64d", PsGetCurrentProcessId());
#else
        sprintf( szName + strlen(szName), ":%d", (ULONG) PsGetCurrentProcessId());
#endif
  //*/
    }
    else
    {

        strcpy(szName, "???");
    }
    return szName;
}

//----------------------------------------------------------------------
//
// DbgKeLog
//
// Trace to file.
//
//----------------------------------------------------------------------
BOOLEAN DbgKeLog(const char *lpszLog, ...)
{
    L_INFO("===========DbgKeLog=========%s\n",lpszLog);
    if (KeGetCurrentIrql() > PASSIVE_LEVEL)
    {
        KdPrint(("TKeHook: KeLog: IRQL too hight.../n"));
        return FALSE;
    }
    WaitForWriteMutex();

    __try
    {
        IO_STATUS_BLOCK IoStatus;
        OBJECT_ATTRIBUTES objectAttributes;
        NTSTATUS status;
        HANDLE FileHandle;
        UNICODE_STRING fileName;
        static WCHAR s_szLogFile[] = L"\\??\\D:\\1.LOG";
        LPCWSTR lpszLogFile = s_szLogFile;

        PAGED_CODE();
        if (lpszLogFile == NULL)
            lpszLogFile = s_szLogFile;

        //get a handle to the log file object
        fileName.Buffer = NULL;
        fileName.Length = 0;
        fileName.MaximumLength = (wcslen(lpszLogFile) + 1) * sizeof(WCHAR);
        fileName.Buffer = (PWCHAR)ExAllocatePool(PagedPool, fileName.MaximumLength);
        if (!fileName.Buffer)
        {
            ReleaseWriteMutex();
            KdPrint(("TKeHook: KeLog: ExAllocatePool Failed.../n"));
            return FALSE;
        }
        RtlZeroMemory(fileName.Buffer, fileName.MaximumLength);
        status = RtlAppendUnicodeToString(&fileName, (PWSTR)lpszLogFile);

        InitializeObjectAttributes(&objectAttributes,
                                   (PUNICODE_STRING)&fileName,
                                   OBJ_CASE_INSENSITIVE,
                                   NULL,
                                   NULL);

        status = ZwCreateFile(&FileHandle,
                              FILE_APPEND_DATA,
                              &objectAttributes,
                              &IoStatus,
                              0,
                              FILE_ATTRIBUTE_NORMAL,
                              FILE_SHARE_WRITE,
                              FILE_OPEN_IF,
                              FILE_SYNCHRONOUS_IO_NONALERT,
                              NULL,
                              0);

        if (NT_SUCCESS(status))
        {
            static CHAR szBuffer[1024];
            PCHAR pszBuffer = szBuffer;
            ULONG ulBufSize;
            int nSize;
            va_list pArglist;

            // add process name and time string
            sprintf(szBuffer, "[%s][%16s:%d] ", GetCurrentTimeString(), GetCurrentProcessName(), (ULONG)PsGetCurrentProcessId());
            pszBuffer = szBuffer + strlen(szBuffer);

            va_start(pArglist, lpszLog);
            // The last argument to wvsprintf points to the arguments
            nSize = _vsnprintf(pszBuffer, 1024 - 32, lpszLog, pArglist);
            // The va_end macro just zeroes out pArgList for no good reason
            va_end(pArglist);
            if (nSize > 0)
            {
                pszBuffer[nSize] = 0;
            }
            else
            {
                pszBuffer[0] = 0;
            }

            ulBufSize = strlen(szBuffer);
            ZwWriteFile(FileHandle,
                        NULL,
                        NULL,
                        NULL,
                        &IoStatus,
                        szBuffer,
                        ulBufSize,
                        NULL,
                        NULL);
            ZwClose(FileHandle);
        }
        if (fileName.Buffer)
            ExFreePool(fileName.Buffer);

        ReleaseWriteMutex();
        return TRUE;
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        ReleaseWriteMutex();
        KdPrint(("TKeHook: DbgKeLog() except: %0xd !!/n", GetExceptionCode()));
        return FALSE;
    }
}


NTSTATUS
	CreateFileTest(IN PUNICODE_STRING nFilePath)
{
	HANDLE lhFile = NULL;
	NTSTATUS lstatus;
	IO_STATUS_BLOCK Io_Status_Block;
	CHAR      *Content;
 
	//init filepath
	OBJECT_ATTRIBUTES obj_attrib;
	do 
	{
		InitializeObjectAttributes(&obj_attrib,nFilePath,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
			NULL,NULL);
		
		//create file
		lstatus = ZwCreateFile(&lhFile,GENERIC_ALL,&obj_attrib,&Io_Status_Block,NULL,
			FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ,
			FILE_OPEN_IF,FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT,
			NULL,0);
 
		if (!NT_SUCCESS(lstatus))
		{
            L_INFO("ZwCreateFile faile \n");
			lstatus = Io_Status_Block.Status;
			break;	
		}
		Content  = "这是要写入的数据";
		lstatus  = ZwWriteFile( lhFile,
			NULL,
			NULL,
			NULL,
			&Io_Status_Block,
			Content,
			strlen(Content),
			NULL,
			NULL);
		if( !NT_SUCCESS( lstatus ) )
		{
            L_INFO("ZwWriteFile faile \n");

			lstatus = Io_Status_Block.Status;
		}
		lstatus = STATUS_SUCCESS;
		
	} while (FALSE);
 
	if (lhFile)
	{
		ZwClose(lhFile);
	}
	return lstatus;
}

void  DbgTest()
{
    NTSTATUS lstatus;
	UNICODE_STRING lstrFilePath;
	RtlInitUnicodeString(&lstrFilePath,L"\\??\\D:\\a.txt");
	lstatus = CreateFileTest(&lstrFilePath);
	if (NT_SUCCESS(lstatus))
	{
		KdPrint(("Createfile Success!\n"));
	} 
	else
	{
		KdPrint((" Createfile Error(%08x)!\n",lstatus));
	}
}