EXE和SYS通訊MiniFilter基於事件方式
阿新 • • 發佈:2019-01-27
#ifndef _HEADER_HEAD_FILE #define _HEADER_HEAD_FILE #pragma once #include <ntifs.h> #include <ntddk.h> #include <fltKernel.h> #include <Ntstrsafe.h> #ifndef MAX_PATH #define MAX_PATH 260 #endif NTKERNELAPI UCHAR * PsGetProcessImageFileName(__in PEPROCESS Process); //驅動控制程式碼 #define IOCTL_START CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810,METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_STOP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811,METHOD_BUFFERED, FILE_ANY_ACCESS) NTSTATUS PtUnload(__in FLT_FILTER_UNLOAD_FLAGS Flags); NTSTATUS PtInstanceQueryTeardown(__in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags); CONST FLT_REGISTRATION FilterRegistration = { sizeof(FLT_REGISTRATION), // Size FLT_REGISTRATION_VERSION, // Version 0, // Flags NULL, // Context NULL, // Operation callbacks PtUnload, // MiniFilterUnload NULL, // InstanceSetup PtInstanceQueryTeardown, // InstanceQueryTeardown NULL, // InstanceTeardownStart NULL, // InstanceTeardownComplete NULL, // GenerateFileName NULL, // GenerateDestinationFileName NULL // NormalizeNameComponent }; #endif
#include "Header.h" PFLT_FILTER gFilterHandle; PFLT_PORT g_ServerPort; PFLT_PORT g_ClientPort; //同步事件物件 PRKEVENT g_pEventObject = NULL; //控制代碼資訊 OBJECT_HANDLE_INFORMATION g_ObjectHandleInfo; char g_szOutBuf[MAX_PATH] = { 0 }; /* 這裡要注意:1.資料地址的對齊. 2.文件建議使用:try/except處理. 3.如果是64位的驅動要考慮32位的EXE發來的請求. */ NTSTATUS MessageNotifyCallback(IN PVOID PortCookie, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, OUT PULONG ReturnOutputBufferLength) { NTSTATUS status = 0; PAGED_CODE(); UNREFERENCED_PARAMETER(PortCookie); //返回使用者一些資訊. RtlCopyMemory(OutputBuffer, g_szOutBuf, strlen(g_szOutBuf) + 1); return status; } VOID DisconnectNotifyCallback(_In_opt_ PVOID ConnectionCookie) { PAGED_CODE(); UNREFERENCED_PARAMETER(ConnectionCookie); FltCloseClientPort(gFilterHandle, &g_ClientPort); } NTSTATUS ConnectNotifyCallback(IN PFLT_PORT ClientPort, IN PVOID ServerPortCookie, IN PVOID ConnectionContext, IN ULONG SizeOfContext, OUT PVOID * ConnectionPortCookie) { PAGED_CODE(); UNREFERENCED_PARAMETER(ServerPortCookie); UNREFERENCED_PARAMETER(ConnectionContext); UNREFERENCED_PARAMETER(SizeOfContext); UNREFERENCED_PARAMETER(ConnectionPortCookie); g_ClientPort = ClientPort; return STATUS_SUCCESS; } NTSTATUS PtInstanceQueryTeardown(__in PCFLT_RELATED_OBJECTS FltObjects, __in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags) { return STATUS_SUCCESS; } NTSTATUS PtUnload(__in FLT_FILTER_UNLOAD_FLAGS Flags) { FltCloseCommunicationPort(g_ServerPort); FltUnregisterFilter(gFilterHandle); return STATUS_SUCCESS; } //設定登錄檔鍵值 NTSTATUS SetValueKey(PUNICODE_STRING pRegPath, PUNICODE_STRING pValueName, ULONG Type, wchar_t ValueData[MAX_PATH]) { //定義變數 size_t pcch = 0; OBJECT_ATTRIBUTES objectAttribues; HANDLE hRegister = NULL; NTSTATUS ntstatus; USHORT cbszSize = 0; //引數效驗 if (pRegPath == NULL || pValueName == 0 || ValueData == NULL)return FALSE; switch (Type) { case REG_SZ: { //獲取長度 RtlStringCchLengthW(ValueData, MAX_PATH, &pcch); if (pcch <= 0)return FALSE; cbszSize = (USHORT)(pcch * sizeof(wchar_t)) + sizeof(wchar_t); } break; case REG_DWORD: { cbszSize = sizeof(ULONG); } break; default: return STATUS_UNSUCCESSFUL; } //設定變數 InitializeObjectAttributes(&objectAttribues, pRegPath, OBJ_CASE_INSENSITIVE, NULL, NULL); //開啟登錄檔 ntstatus = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &objectAttribues); if (!NT_SUCCESS(ntstatus) || hRegister == NULL)return FALSE; //設定REG_SZ子健 ntstatus = ZwSetValueKey(hRegister, pValueName, 0, Type, ValueData, cbszSize); ZwClose(hRegister); return ntstatus; } //註冊MiniFilter NTSTATUS RegisterMiniFilter(PDRIVER_OBJECT DriverObject, PUNICODE_STRING pRegistryPath) { UNICODE_STRING UnicodeDriverServerName; UNICODE_STRING UnicodeValue; UNICODE_STRING UnicodeSzText; UNICODE_STRING UnicodeSzServerNameInstances; ULONG ulValue; HANDLE hRegister; ULONG ulResult; NTSTATUS ntStatus; static wchar_t szInstances[MAX_PATH] = { 0 }; static wchar_t szServerNameInstances[MAX_PATH] = { 0 }; //初始化objectAttributes OBJECT_ATTRIBUTES objectAttributes; wchar_t* pFind = NULL; ULONG nAltitude = 399998; int i = 0; //引數效驗 if (DriverObject == NULL)return STATUS_UNSUCCESSFUL; if (pRegistryPath == NULL || pRegistryPath->Length <= 0)return STATUS_UNSUCCESSFUL; InitializeObjectAttributes(&objectAttributes, pRegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL); //建立或開啟登錄檔專案 ntStatus = ZwCreateKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes, 0, NULL, (ULONG)REG_OPTION_NON_VOLATILE, &ulResult); if (hRegister == NULL || ntStatus != STATUS_SUCCESS) return STATUS_UNSUCCESSFUL; ZwClose(hRegister); //DependOnService RtlInitUnicodeString(&UnicodeValue, L"DependOnService"); SetValueKey(pRegistryPath, &UnicodeValue, REG_SZ, L"FltMgr"); //Instances RtlStringCbPrintfExW(szServerNameInstances, sizeof(szServerNameInstances), NULL, NULL, STRSAFE_FILL_BEHIND_NULL, L"%wZ\\Instances", pRegistryPath); RtlInitUnicodeString(&UnicodeSzServerNameInstances, szServerNameInstances); InitializeObjectAttributes(&objectAttributes, &UnicodeSzServerNameInstances, OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwCreateKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, &ulResult); if (hRegister == NULL || ntStatus != STATUS_SUCCESS) return STATUS_UNSUCCESSFUL; ZwClose(hRegister); //獲取服務名 pFind = wcsrchr(pRegistryPath->Buffer, '\\'); if (pFind) RtlInitUnicodeString(&UnicodeDriverServerName, pFind + sizeof(char)); else return STATUS_UNSUCCESSFUL; //DefaultInstance RtlInitUnicodeString(&UnicodeValue, L"DefaultInstance"); RtlStringCbPrintfExW(szInstances, sizeof(szInstances), NULL, NULL, STRSAFE_FILL_BEHIND_NULL, L"%wZ Instance", &UnicodeDriverServerName); SetValueKey(&UnicodeSzServerNameInstances, &UnicodeValue, REG_SZ, szInstances); //ProtectFile Instance RtlStringCbPrintfExW(szInstances, sizeof(szInstances), NULL, NULL, STRSAFE_FILL_BEHIND_NULL, L"%wZ\\%wZ Instance", &UnicodeSzServerNameInstances, &UnicodeDriverServerName); RtlInitUnicodeString(&UnicodeSzText, szInstances); InitializeObjectAttributes(&objectAttributes, &UnicodeSzText, OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwCreateKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, &ulResult); if (hRegister == NULL || ntStatus != STATUS_SUCCESS) return STATUS_UNSUCCESSFUL; ZwClose(hRegister); //Altitude RtlInitUnicodeString(&UnicodeValue, L"Altitude"); SetValueKey(&UnicodeSzText, &UnicodeValue, REG_SZ, L"399999"); //Flags RtlInitUnicodeString(&UnicodeValue, L"Flags"); ulValue = 0; SetValueKey(&UnicodeSzText, &UnicodeValue, REG_DWORD, (wchar_t*)&ulValue); return ntStatus; } //獲取程序名 PCHAR GetProcessName16ByProcessId(HANDLE ProcessId) { //定義變數 NTSTATUS status = STATUS_UNSUCCESSFUL; PEPROCESS ProcessObj = NULL; PUCHAR ProcessName = NULL; //程序ID和返回一個引用指標的過程EPROCESS結構 status = PsLookupProcessByProcessId(ProcessId, &ProcessObj); if (NT_SUCCESS(status)) { // ImageFileName : [16] "SogouExplorer.e" //使用這個函式,只能獲取程序名稱是16的長度,後面的被截取了。。。 ProcessName = PsGetProcessImageFileName(ProcessObj); ObfDereferenceObject(ProcessObj); } return ProcessName; } VOID CreateProcessNotifyFunction(IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create) { if (Create) { char* pName=GetProcessName16ByProcessId(ProcessId); if (pName) { RtlZeroMemory(g_szOutBuf, sizeof(g_szOutBuf)); RtlCopyMemory(g_szOutBuf, pName, strlen(pName)+1); //設定事件為有訊號,通知應用層 KeSetEvent(g_pEventObject, 0, FALSE); } } return; } VOID DriverUnload(DRIVER_OBJECT *DriverObject) { PsSetCreateProcessNotifyRoutine(CreateProcessNotifyFunction, TRUE); UNICODE_STRING Win32Device; RtlInitUnicodeString(&Win32Device, L"\\DosDevices\\KernelHandle"); IoDeleteSymbolicLink(&Win32Device); IoDeleteDevice(DriverObject->DeviceObject); return; } NTSTATUS KernelHandleCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS KernelHandleClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Irp->IoStatus.Status; } NTSTATUS KernelHandleDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; ULONG ulReturn = 0; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG ulCtrlCode = stack->Parameters.DeviceIoControl.IoControlCode; PVOID InputBuffer = (PVOID)Irp->AssociatedIrp.SystemBuffer; PVOID OutputBuffer = (PVOID)Irp->AssociatedIrp.SystemBuffer; ULONG ulInputBufferSize = stack->Parameters.DeviceIoControl.InputBufferLength; ULONG ulOutputBufferSize = stack->Parameters.DeviceIoControl.OutputBufferLength; switch (ulCtrlCode) { case IOCTL_START: { //設定同步事件 if (InputBuffer == NULL || ulInputBufferSize < sizeof(HANDLE)) { KdPrint(("Set Event Error~!\n")); break; } //取得控制代碼物件 HANDLE hEvent = *(HANDLE*)InputBuffer; status = ObReferenceObjectByHandle(hEvent, GENERIC_ALL, NULL, KernelMode, (PVOID*)&g_pEventObject, &g_ObjectHandleInfo); PsSetCreateProcessNotifyRoutine(CreateProcessNotifyFunction, FALSE); break; } case IOCTL_STOP: { //移除程序建立通知函式 PsSetCreateProcessNotifyRoutine(CreateProcessNotifyFunction, TRUE); //釋放物件引用 if (g_pEventObject != NULL) { ObDereferenceObject(g_pEventObject); g_pEventObject = NULL; } break; } default: break; } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = ulOutputBufferSize; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Irp->IoStatus.Status; } NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) { NTSTATUS status; PDEVICE_OBJECT DeviceObject = NULL; UNICODE_STRING DeviceName; UNICODE_STRING Win32Device; KdBreakPoint(); DriverObject->DriverUnload = DriverUnload; RtlInitUnicodeString(&DeviceName, L"\\Device\\KernelHandle"); RtlInitUnicodeString(&Win32Device, L"\\DosDevices\\KernelHandle"); DriverObject->MajorFunction[IRP_MJ_CREATE] = KernelHandleCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = KernelHandleClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KernelHandleDefaultHandler; status = IoCreateDevice(DriverObject,0,&DeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&DeviceObject); if (!NT_SUCCESS(status)) return status; if (!DeviceObject) return STATUS_UNEXPECTED_IO_ERROR; DeviceObject->Flags |= DO_DIRECT_IO; DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; status = IoCreateSymbolicLink(&Win32Device, &DeviceName); DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; do { PSECURITY_DESCRIPTOR sd; OBJECT_ATTRIBUTES oa; UNICODE_STRING uniString; status = RegisterMiniFilter(DriverObject, RegistryPath); if (!NT_SUCCESS(status))break; status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle); if (!NT_SUCCESS(status))break; status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS); if (!NT_SUCCESS(status))break; RtlInitUnicodeString(&uniString, L"\\CommunicationPort"); InitializeObjectAttributes(&oa, &uniString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, sd); status = FltCreateCommunicationPort(gFilterHandle, &g_ServerPort, &oa, NULL, ConnectNotifyCallback, DisconnectNotifyCallback, MessageNotifyCallback, 1); FltFreeSecurityDescriptor(sd); if (!NT_SUCCESS(status))break; status = FltStartFiltering(gFilterHandle); if (!NT_SUCCESS(status))break; } while (FALSE); if (!NT_SUCCESS(status)) { if (NULL != g_ServerPort) { FltCloseCommunicationPort(g_ServerPort); } if (NULL != gFilterHandle) { FltUnregisterFilter(gFilterHandle); } } return STATUS_SUCCESS; }
#include <windows.h> #include <tchar.h> #include <stdio.h> //這兩個檔案在VS中沒有,在WDK中有. //如果要用VS編譯要拷貝相應的檔案到相應的目錄或者改變目錄的設定等. #include <fltuser.h> #pragma comment(lib, "fltLib.lib") HANDLE hDevice; HANDLE g_hKernelEvent = NULL; HANDLE g_hPort; #define NPMINI_PORT_NAME L"\\CommunicationPort" //驅動控制程式碼 #define IOCTL_START CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810,METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_STOP CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811,METHOD_BUFFERED, FILE_ANY_ACCESS) DWORD WINAPI ThreadProc(LPVOID lpParameter) { printf("執行緒開始執行\n"); HRESULT hResult; while (WaitForSingleObject(g_hKernelEvent, INFINITE) == WAIT_OBJECT_0) { printf("收到狀態\n"); wchar_t InBuffer[] = L"test"; char OutBuffer[MAX_PATH] = { 0 }; DWORD bytesReturned = 0; hResult = FilterSendMessage(g_hPort, InBuffer, lstrlen(InBuffer), OutBuffer, sizeof(OutBuffer), &bytesReturned); if (IS_ERROR(hResult)) { printf("FilterSendMessage fail!\n"); } else { printf("FilterSendMessage ok!\n"); } printf("從核心發來的資訊是:%s\n", OutBuffer); //設定同步事件為無訊號,等待下一次通知 ResetEvent(g_hKernelEvent); } printf("執行緒結束\n"); return 0; } int main(void) { //建立手動重置的事件 g_hKernelEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //開啟驅動的符號連結 hDevice = CreateFile(L"\\\\.\\KernelHandle", GENERIC_READ | GENERIC_WRITE, 0,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hDevice) { printf("CreateFile fail!\n"); getchar(); getchar(); return FALSE; } DWORD dwRet; DeviceIoControl(hDevice, IOCTL_START, &g_hKernelEvent, sizeof(g_hKernelEvent), NULL, NULL, &dwRet, NULL); HRESULT hResult = S_OK; hResult = FilterConnectCommunicationPort(NPMINI_PORT_NAME, 0, NULL, 0, NULL, &g_hPort); if (IS_ERROR(hResult)) { printf("FilterConnectCommunicationPort fail!\n"); getchar(); getchar(); return hResult; } printf("FilterConnectCommunicationPort\n"); HANDLE hThread =CreateThread(NULL, NULL, ThreadProc, NULL, NULL, NULL); CloseHandle(hThread); getchar(); getchar(); CloseHandle(g_hPort); DeviceIoControl(hDevice, IOCTL_STOP, NULL, 0, NULL, NULL, &dwRet, NULL); CloseHandle(hDevice); return 0; }