#ifndef _HEADER_HEAD_FILE
#define _HEADER_HEAD_FILE
#pragma once
#include <fltKernel.h>
#include <Ntstrsafe.h>
#ifndef MAX_PATH
#define MAX_PATH 260
#endif
typedef struct _SCANNER_NOTIFICATION {
BOOLEAN bCreate;
ULONG Reserved;
UCHAR ProcessName[MAX_PATH];
} SCANNER_NOTIFICATION, *PSCANNER_NOTIFICATION;
typedef struct _SCANNER_REPLY {
BOOLEAN SafeToOpen;
UCHAR ReplyMsg[MAX_PATH];
} SCANNER_REPLY, *PSCANNER_REPLY;
NTKERNELAPI UCHAR * PsGetProcessImageFileName(__in PEPROCESS Process);
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;
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;
}
VOID DisconnectNotifyCallback(_In_opt_ PVOID ConnectionCookie)
{
PAGED_CODE();
UNREFERENCED_PARAMETER(ConnectionCookie);
FltCloseClientPort(gFilterHandle, &g_ClientPort);
}
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)
{
NTSTATUS status;
ULONG replyLength;
if (Create == FALSE)return;
if (gFilterHandle == NULL || g_ClientPort == NULL)return;
char* pName = GetProcessName16ByProcessId(ProcessId);
if (pName == NULL)return;
KdPrint(("%s\n", pName));
PSCANNER_NOTIFICATION notification = ExAllocatePool(NonPagedPool,sizeof(SCANNER_NOTIFICATION));
if (notification == NULL)return;
RtlZeroMemory(notification, sizeof(SCANNER_NOTIFICATION));
notification->bCreate = Create;
RtlCopyMemory(¬ification->ProcessName, pName,strlen(pName)+1);
SCANNER_REPLY Reply = {0};
replyLength = sizeof(SCANNER_REPLY);
status = FltSendMessage(gFilterHandle,&g_ClientPort,notification,sizeof(SCANNER_NOTIFICATION),&Reply,&replyLength,NULL);
if (NT_SUCCESS(status))
{
KdPrint(("发送成功 %d\n", replyLength));
}
else
{
KdPrint(("发送失败\n"));
}
return;
}
VOID DriverUnload(DRIVER_OBJECT *DriverObject)
{
PsSetCreateProcessNotifyRoutine(CreateProcessNotifyFunction, TRUE);
return;
}
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
PSECURITY_DESCRIPTOR sd;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
KdBreakPoint();
DriverObject->DriverUnload = DriverUnload;
do
{
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, NULL, 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);
}
}
if (NT_SUCCESS(status))
{
PsSetCreateProcessNotifyRoutine(CreateProcessNotifyFunction, FALSE);
}
return status;
}
#pragma pack(1)
typedef struct _SCANNER_NOTIFICATION {
BOOL bCreate;
ULONG Reserved; // for quad-word alignement of the Contents structure
UCHAR ProcessName[MAX_PATH];
} SCANNER_NOTIFICATION, *PSCANNER_NOTIFICATION;
typedef struct _SCANNER_REPLY {
BOOLEAN SafeToOpen;
UCHAR ReplyMsg[MAX_PATH];
} SCANNER_REPLY, *PSCANNER_REPLY;
typedef struct _SCANNER_MESSAGE
{
//
// Required structure header.
//
FILTER_MESSAGE_HEADER MessageHeader;
//
// Private scanner-specific fields begin here.
//
SCANNER_NOTIFICATION Notification;
//
// Overlapped structure: this is not really part of the message
// However we embed it instead of using a separately allocated overlap structure
//
OVERLAPPED Ovlp;
} SCANNER_MESSAGE, *PSCANNER_MESSAGE;
typedef struct _SCANNER_REPLY_MESSAGE {
//
// Required structure header.
//
FILTER_REPLY_HEADER ReplyHeader;
//
// Private scanner-specific fields begin here.
//
SCANNER_REPLY Reply;
} SCANNER_REPLY_MESSAGE, *PSCANNER_REPLY_MESSAGE;
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <winioctl.h>
#include <string.h>
#include <crtdbg.h>
#include <assert.h>
#include <fltuser.h>
#include <dontuse.h>
#include "header.h"
#define SCANNER_DEFAULT_REQUEST_COUNT 5
#define SCANNER_DEFAULT_THREAD_COUNT 2
#define SCANNER_MAX_THREAD_COUNT 64
typedef struct _SCANNER_THREAD_CONTEXT {
HANDLE Port;
HANDLE Completion;
} SCANNER_THREAD_CONTEXT, *PSCANNER_THREAD_CONTEXT;
DWORD ScannerWorker(PSCANNER_THREAD_CONTEXT Context);
int main(void)
{
DWORD requestCount = SCANNER_DEFAULT_REQUEST_COUNT;
DWORD threadCount = SCANNER_DEFAULT_THREAD_COUNT;
HANDLE port, completion;
HRESULT hr;
DWORD threadId;
PSCANNER_MESSAGE msg;
HANDLE threads[SCANNER_MAX_THREAD_COUNT];
SCANNER_THREAD_CONTEXT context;
int i = 0;
hr = FilterConnectCommunicationPort(L"\\CommunicationPort", 0, NULL, 0, NULL, &port);
if (IS_ERROR(hr))
{
printf("ERROR: Connecting to filter port: 0x%08x\n", hr);
getchar();
getchar();
return 2;
}
completion = CreateIoCompletionPort(port,NULL,0,threadCount);
if (completion == NULL)
{
printf("ERROR: Creating completion port: %d\n", GetLastError());
CloseHandle(port);
getchar();
getchar();
return 3;
}
context.Port = port;
context.Completion = completion;
for (i = 0; i < threadCount; i++)
{
threads[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ScannerWorker,&context,0,&threadId);
if (threads[i] == NULL)
{
hr = GetLastError();
printf("ERROR: Couldn't create thread: %d\n", hr);
goto main_cleanup;
}
for (int j = 0; j < requestCount; j++)
{
msg = new SCANNER_MESSAGE[sizeof(SCANNER_MESSAGE)];
if (msg == NULL)
{
hr = ERROR_NOT_ENOUGH_MEMORY;
goto main_cleanup;
}
memset(&msg->Ovlp, 0, sizeof(OVERLAPPED));
hr = FilterGetMessage(port,&msg->MessageHeader,FIELD_OFFSET(SCANNER_MESSAGE, Ovlp),&msg->Ovlp);
if (hr != HRESULT_FROM_WIN32(ERROR_IO_PENDING))
{
delete msg;
goto main_cleanup;
}
}
}
hr = S_OK;
WaitForMultipleObjectsEx(i, threads, TRUE, INFINITE, FALSE);
main_cleanup:
printf("Scanner: All done. Result = 0x%08x\n", hr);
CloseHandle(port);
CloseHandle(completion);
getchar();
getchar();
return 0;
}
DWORD ScannerWorker(PSCANNER_THREAD_CONTEXT Context)
{
BOOL result;
DWORD outSize;
LPOVERLAPPED pOvlp;
ULONG_PTR key;
HRESULT hr;
PSCANNER_MESSAGE message;
PSCANNER_NOTIFICATION notification;
SCANNER_REPLY_MESSAGE replyMessage;
while (TRUE)
{
result = GetQueuedCompletionStatus(Context->Completion, &outSize, &key, &pOvlp, INFINITE);
message = CONTAINING_RECORD(pOvlp, SCANNER_MESSAGE, Ovlp);
if (!result)
{
printf("GetQueuedCompletionStatus error \n");
break;
}
notification = &message->Notification;
printf("%d %s %d\n", notification->bCreate, notification->ProcessName, pOvlp->InternalHigh);
ZeroMemory(&replyMessage, sizeof(SCANNER_REPLY_MESSAGE));
replyMessage.ReplyHeader.Status = 0;
replyMessage.ReplyHeader.MessageId = message->MessageHeader.MessageId;
replyMessage.Reply.SafeToOpen = 6;
CopyMemory(replyMessage.Reply.ReplyMsg, "12345678ab", 10);
hr = FilterReplyMessage(Context->Port, (PFILTER_REPLY_HEADER)&replyMessage, sizeof(replyMessage));
if (SUCCEEDED(hr))
{
printf("Replied message\n");
}
else
{
printf("Scanner: Error replying message. Error = 0x%X\n", hr);
break;
}
memset(&message->Ovlp, 0, sizeof(OVERLAPPED));
hr = FilterGetMessage(Context->Port, &message->MessageHeader, FIELD_OFFSET(SCANNER_MESSAGE, Ovlp), &message->Ovlp);
if (hr != HRESULT_FROM_WIN32(ERROR_IO_PENDING))
{
printf("线程 FilterGetMessage error\n");
break;
}
}
printf("线程结束\n");
delete message;
return 0;
}