8.4 Windows驱动开发:文件微过滤驱动入门

MiniFilter 微过滤驱动是相对于SFilter传统过滤驱动而言的,传统文件过滤驱动相对来说较为复杂,且接口不清晰并不符合快速开发的需求,为了解决复杂的开发问题,微过滤驱动就此诞生,微过滤驱动在编写时更简单,多数IRP操作都由过滤管理器(FilterManager或Fltmgr)所接管,因为有了兼容层,所以在开发中不需要考虑底层IRP如何派发,更无需要考虑兼容性问题,用户只需要编写对应的回调函数处理请求即可,这极大的提高了文件过滤驱动的开发效率。

接下来将进入正题,讲解微过滤驱动的API定义规范以及具体的使用流程,并最终实现一个简单的过滤功能,首先你必须在VS上做如下配置,依次打开配置菜单,并增加驱动头文件。

  • 配置属性 > 连接器 > 输入> 附加依赖 > fltMgr.lib
  • 配置属性 > C/C++ > 常规 > 设置 关闭所有警告 (警告视为错误关闭)

未过滤驱动的使用非常容易,在使用之前第一件事就是要向过滤管理器宣告我们的微过滤驱动的存在,我们以DriverEntry入口函数为例,首先在入口处需要使用FltRegisterFilter函数注册一个过滤器组件,另外则需要通过FltStartFiltering开启过滤功能,而当我们想要关闭时则需要调用FltUnregisterFilter注销过滤组件,首先来看一下入口处是如何初始化的;

NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{NTSTATUS status;DbgPrint("Hello lyshark \n");// FltRegisterFilter 向过滤管理器注册过滤器// 参数1:本驱动驱动对象// 参数2:微过滤驱动描述结构// 参数3:返回注册成功的微过滤驱动句柄status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle);if (NT_SUCCESS(status)){// 开启过滤status = FltStartFiltering(gFilterHandle);DbgPrint("[过滤器] 开启监控.. \n");if (!NT_SUCCESS(status)){// 如果启动失败,则取消注册并退出FltUnregisterFilter(gFilterHandle);DbgPrint("[过滤器] 取消注册.. \n");}}return status;
}

如上代码中我们最需要关注的是FltRegisterFilter函数的第二个参数FilterRegistration它用于宣告注册信息,这个结构内包含了过滤器的所有信息,想要注册成功则我们必须更具要求正确的填写FLT_REGISTRATION微过滤器注册结构,该结构体的微软定义如下所示;

typedef struct _FLT_REGISTRATION {USHORT                                      Size;USHORT                                      Version;FLT_REGISTRATION_FLAGS                      Flags;const FLT_CONTEXT_REGISTRATION              *ContextRegistration;const FLT_OPERATION_REGISTRATION            *OperationRegistration;PFLT_FILTER_UNLOAD_CALLBACK                 FilterUnloadCallback;PFLT_INSTANCE_SETUP_CALLBACK                InstanceSetupCallback;PFLT_INSTANCE_QUERY_TEARDOWN_CALLBACK       InstanceQueryTeardownCallback;PFLT_INSTANCE_TEARDOWN_CALLBACK             InstanceTeardownStartCallback;PFLT_INSTANCE_TEARDOWN_CALLBACK             InstanceTeardownCompleteCallback;PFLT_GENERATE_FILE_NAME                     GenerateFileNameCallback;PFLT_NORMALIZE_NAME_COMPONENT               NormalizeNameComponentCallback;PFLT_NORMALIZE_CONTEXT_CLEANUP              NormalizeContextCleanupCallback;PFLT_TRANSACTION_NOTIFICATION_CALLBACK      TransactionNotificationCallback;PFLT_NORMALIZE_NAME_COMPONENT_EX            NormalizeNameComponentExCallback;PFLT_SECTION_CONFLICT_NOTIFICATION_CALLBACK SectionNotificationCallback;
} FLT_REGISTRATION, *PFLT_REGISTRATION;

当然如上的这些字段并非都要去填充,我们只需要填充自己所需要的部分即可,例如我们代码中只填充了如下这些必要的部分,其他部分可以省略掉,当使用如下结构体注册时,只要实例发生了变化就会根据如下配置路由到不同的函数上面做处理。

// 过滤驱动数据结构
CONST FLT_REGISTRATION FilterRegistration =
{sizeof(FLT_REGISTRATION),         //  结构大小(默认)FLT_REGISTRATION_VERSION,           //  结构版本(默认)0,                                  //  过滤器标志NULL,                               //  上下文Callbacks,                          //  注册回调函数集Unload,                             //  驱动卸载函数InstanceSetup,                      //  实例安装回调函数InstanceQueryTeardown,              //  实例销毁回调函数InstanceTeardownStart,              //  实例解除绑定时触发InstanceTeardownComplete,           //  实例解绑完成时触发NULL,                               //  GenerateFileNameNULL,                               //  GenerateDestinationFileNameNULL                                //  NormalizeNameComponent
};

如上结构中我们最需要注意的是Callbacks字段,该字段是操作回调函数集注册,我们对文件的各种操作的回调事件都会被写入到此处,而此处我们只需要增加我们所需要的回调事件即可,以IRP_MJ_CREATE为例,后面紧跟的是PreOperation事前回调,以及PostOperation事后回调,一般在要进行监控时通常在PreOperation()回调中处理,如果时监视则一般在PostOperation()中处理。

// 回调函数集
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{// 创建时触发 PreOperation(之前回调函数) / PostOperation(之后回调函数){ IRP_MJ_CREATE, 0, PreOperation, PostOperation },// 读取时触发{ IRP_MJ_READ, 0, PreOperation, PostOperation },// 写入触发{ IRP_MJ_WRITE, 0, PreOperation, PostOperation },// 设置时触发{ IRP_MJ_SET_INFORMATION, 0, PreOperation, PostOperation },// 结束标志{ IRP_MJ_OPERATION_END }
};

如下完整代码实现了监视当前系统下所有的文件操作,如创建,读取,写入,修改,加载后则会监视系统下所有的文件操作,当然如果是监控则需要在PreOperation事前回调做文章,而如果仅仅只是监视则事前事后都是可以的。

#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>PFLT_FILTER gFilterHandle;// ----------------------------------------------------------------------------------------
// 声明部分
// ----------------------------------------------------------------------------------------
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject,_In_ PUNICODE_STRING RegistryPath);NTSTATUS
InstanceSetup(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_SETUP_FLAGS Flags,
_In_ DEVICE_TYPE VolumeDeviceType,
_In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType
);VOID
InstanceTeardownStart(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);VOID
InstanceTeardownComplete(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags
);NTSTATUS
Unload(
_In_ FLT_FILTER_UNLOAD_FLAGS Flags
);NTSTATUS
InstanceQueryTeardown(
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
);FLT_PREOP_CALLBACK_STATUS
PreOperation(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
);
FLT_POSTOP_CALLBACK_STATUS
PostOperation(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_opt_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
);// ----------------------------------------------------------------------------------------
// 回调函数
// ----------------------------------------------------------------------------------------// 当实例被安装时触发
NTSTATUS InstanceSetup(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_SETUP_FLAGS Flags, _In_ DEVICE_TYPE VolumeDeviceType, _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType)
{DbgPrint("[LyShark] 安装 MiniFilter \n");return STATUS_SUCCESS;
}// 当实例被销毁时触发
NTSTATUS InstanceQueryTeardown(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{DbgPrint("[LyShark] 销毁 MiniFilter \n");return STATUS_SUCCESS;
}// 实例解除绑定时触发
VOID InstanceTeardownStart(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags)
{DbgPrint("[LyShark] 解绑 MiniFilter \n");return STATUS_SUCCESS;
}// 实例解绑完成时触发
VOID InstanceTeardownComplete(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_TEARDOWN_FLAGS Flags)
{DbgPrint("[LyShark] 解绑完成 MiniFilter \n");return STATUS_SUCCESS;
}// 驱动关闭时卸载监控
NTSTATUS Unload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags)
{DbgPrint("[LyShark] 卸载 MiniFilter \n");FltUnregisterFilter(gFilterHandle);return STATUS_SUCCESS;
}// 回调函数集
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{// 创建时触发 PreOperation(之前回调函数) / PostOperation(之后回调函数){ IRP_MJ_CREATE, 0, PreOperation, PostOperation },// 读取时触发{ IRP_MJ_READ, 0, PreOperation, PostOperation },// 写入触发{ IRP_MJ_WRITE, 0, PreOperation, PostOperation },// 设置时触发{ IRP_MJ_SET_INFORMATION, 0, PreOperation, PostOperation },// 结束标志{ IRP_MJ_OPERATION_END }
};// 过滤驱动数据结构
CONST FLT_REGISTRATION FilterRegistration =
{sizeof(FLT_REGISTRATION),           //  结构大小(默认)FLT_REGISTRATION_VERSION,           //  结构版本(默认)0,                                  //  过滤器标志NULL,                               //  上下文Callbacks,                          //  注册回调函数集Unload,                             //  驱动卸载函数InstanceSetup,                      //  实例安装回调函数InstanceQueryTeardown,              //  实例销毁回调函数InstanceTeardownStart,              //  实例解除绑定时触发InstanceTeardownComplete,           //  实例解绑完成时触发NULL,                               //  GenerateFileNameNULL,                               //  GenerateDestinationFileNameNULL                                //  NormalizeNameComponent
};// ----------------------------------------------------------------------------------------
// 功能函数
// ----------------------------------------------------------------------------------------// 预操作回调函数(在执行过滤操作之前先执行此处)
FLT_PREOP_CALLBACK_STATUS PreOperation(_Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Flt_CompletionContext_Outptr_ PVOID *CompletionContext)
{NTSTATUS status;// 获取文件路径UCHAR MajorFunction = Data->Iopb->MajorFunction;PFLT_FILE_NAME_INFORMATION lpNameInfo = NULL;// 得到文件名相关信息status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &lpNameInfo);if (NT_SUCCESS(status)){status = FltParseFileNameInformation(lpNameInfo);if (NT_SUCCESS(status)){// 创建if (IRP_MJ_CREATE == MajorFunction){DbgPrint("[创建文件时] %wZ", &lpNameInfo->Name);// 拒绝创建// STATUS_INSUFFICIENT_RESOURCES                 提示不是有效的资源// STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY  静默拒绝// STATUS_ACCESS_DENIED                          提示访问拒绝// return STATUS_ACCESS_DENIED;// return FLT_PREOP_COMPLETE;}// 读取else if (IRP_MJ_READ == MajorFunction){DbgPrint("[读取文件时] %wZ", &lpNameInfo->Name);// return FLT_PREOP_COMPLETE;}// 文件写入else if (IRP_MJ_WRITE == MajorFunction){DbgPrint("[写入文件时] %wZ", &lpNameInfo->Name);// return FLT_PREOP_COMPLETE;}// 修改文件信息else if (IRP_MJ_SET_INFORMATION == MajorFunction){DbgPrint("[修改文件] %wZ", &lpNameInfo->Name);// return FLT_PREOP_COMPLETE;}}}return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}// 后操作回调函数 (在执行过滤之后运行此处)
FLT_POSTOP_CALLBACK_STATUS PostOperation(_Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _In_opt_ PVOID CompletionContext, _In_ FLT_POST_OPERATION_FLAGS Flags)
{return FLT_POSTOP_FINISHED_PROCESSING;
}// ----------------------------------------------------------------------------------------
// 入口函数
// ----------------------------------------------------------------------------------------
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{NTSTATUS status;DbgPrint("Hello lyshark \n");// FltRegisterFilter 向过滤管理器注册过滤器// 参数1:本驱动驱动对象// 参数2:微过滤驱动描述结构// 参数3:返回注册成功的微过滤驱动句柄status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle);if (NT_SUCCESS(status)){// 开启过滤status = FltStartFiltering(gFilterHandle);DbgPrint("[过滤器] 开启监控.. \n");if (!NT_SUCCESS(status)){// 如果启动失败,则取消注册并退出FltUnregisterFilter(gFilterHandle);DbgPrint("[过滤器] 取消注册.. \n");}}return status;
}

过滤驱动的安装方式有多种,可以通过函数注册或者使用INF文件像系统注册驱动,首先以INF为例安装,通过修改INF中的ServiceName以及DriverName并将其改为WinDDK,将文件保存为install.inf鼠标右键选择安装即可。

[Version]
Signature   = "$Windows NT$"     
Class       = "ActivityMonitor"  ;指明了驱动的分组,必须指定.
ClassGuid   = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}  ;GUID 每个分组都有固定的GUID
Provider    = %Msft% ;变量值 从STRING节中可以看到驱动提供者的名称 
DriverVer   = 06/16/2007,1.0.0.1 ;版本号
CatalogFile = passthrough.cat    ;inf对应的cat 文件 可以不需要[DestinationDirs]
DefaultDestDir          = 12    ;告诉我们驱动拷贝到哪里 13代表拷贝到%windir%
MiniFilter.DriverFiles  = 12            ;%windir%\system32\drivers[DefaultInstall]
OptionDesc          = %ServiceDescription%
CopyFiles           = MiniFilter.DriverFiles[DefaultInstall.Services]
AddService          = %ServiceName%,,MiniFilter.Service[DefaultUninstall]
DelFiles   = MiniFilter.DriverFiles[DefaultUninstall.Services]
DelService = %ServiceName%,0x200      ;Ensure service is stopped before deleting[MiniFilter.Service]                 ;服务的一些信息
DisplayName      = %ServiceName%
Description      = %ServiceDescription%
ServiceBinary    = %12%\%DriverName%.sys        ;%windir%\system32\drivers\
Dependencies     = "FltMgr"                     ;服务的依赖
ServiceType      = 2                            ;SERVICE_FILE_SYSTEM_DRIVER
StartType        = 3                            ;SERVICE_DEMAND_START
ErrorControl     = 1                            ;SERVICE_ERROR_NORMAL
LoadOrderGroup   = "FSFilter Activity Monitor"  ;文件过滤分组
AddReg           = MiniFilter.AddRegistry       ;文件过滤注册表需要添加的高度值等信息[MiniFilter.AddRegistry]
HKR,,"DebugFlags",0x00010001 ,0x0
HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance%
HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude%
HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags%[MiniFilter.DriverFiles]
%DriverName%.sys[SourceDisksFiles]
passthrough.sys = 1,,[SourceDisksNames]
1 = %DiskId1%,,,[Strings]
Msft                    = "Microsoft Corporation"
ServiceDescription      = "WinDDK Mini-Filter Driver"
ServiceName             = "WinDDK"
DriverName              = "WinDDK"
DiskId1                 = "WinDDK Device Installation Disk"DefaultInstance         = "WinDDK Instance"
Instance1.Name          = "WinDDK Instance"
Instance1.Altitude      = "370030"
Instance1.Flags         = 0x0              ; Allow all attachments

第二种安装方式则是通过字写驱动加载工具实现,本人更推荐使用此方式安装,此种方式的原理同样是向注册表中写出子健,但同时具备有启动与关闭驱动的功能,比INF安装更灵活易于使用,完整代码如下所示;

#include <Windows.h>
#include <iostream>
#include <winsvc.h>
#include <winioctl.h>// 安装MiniFinter
BOOL InstallDriver(const char* lpszDriverName, const char* lpszDriverPath, const char* lpszAltitude)
{char szTempStr[MAX_PATH];HKEY hKey;DWORD dwData;char szDriverImagePath[MAX_PATH];if (NULL == lpszDriverName || NULL == lpszDriverPath){return FALSE;}// 得到完整的驱动路径GetFullPathName(lpszDriverPath, MAX_PATH, szDriverImagePath, NULL);SC_HANDLE hServiceMgr = NULL; // SCM管理器的句柄SC_HANDLE hService = NULL;    // NT驱动程序的服务句柄// 打开服务控制管理器hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (hServiceMgr == NULL){// OpenSCManager失败CloseServiceHandle(hServiceMgr);return FALSE;}// OpenSCManager成功  // 创建驱动所对应的服务hService = CreateService(hServiceMgr,lpszDriverName,             // 驱动程序的在注册表中的名字lpszDriverName,             // 注册表驱动程序的DisplayName 值SERVICE_ALL_ACCESS,         // 加载驱动程序的访问权限SERVICE_FILE_SYSTEM_DRIVER, // 表示加载的服务是文件系统驱动程序SERVICE_DEMAND_START,       // 注册表驱动程序的Start 值SERVICE_ERROR_IGNORE,       // 注册表驱动程序的ErrorControl 值szDriverImagePath,          // 注册表驱动程序的ImagePath 值"FSFilter Activity Monitor",// 注册表驱动程序的Group 值NULL,"FltMgr",                   // 注册表驱动程序的DependOnService 值NULL,NULL);if (hService == NULL){if (GetLastError() == ERROR_SERVICE_EXISTS){// 服务创建失败,是由于服务已经创立过CloseServiceHandle(hService);       // 服务句柄CloseServiceHandle(hServiceMgr);    // SCM句柄return TRUE;}else{CloseServiceHandle(hService);       // 服务句柄CloseServiceHandle(hServiceMgr);    // SCM句柄return FALSE;}}CloseServiceHandle(hService);       // 服务句柄CloseServiceHandle(hServiceMgr);    // SCM句柄//-------------------------------------------------------------------------------------------------------// SYSTEM\\CurrentControlSet\\Services\\DriverName\\Instances 子键下的键值项 //-------------------------------------------------------------------------------------------------------strcpy(szTempStr, "SYSTEM\\CurrentControlSet\\Services\\");strcat(szTempStr, lpszDriverName);strcat(szTempStr, "\\Instances");if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szTempStr, 0, "", TRUE, KEY_ALL_ACCESS, NULL, &hKey, (LPDWORD)&dwData) != ERROR_SUCCESS){return FALSE;}// 注册表驱动程序的DefaultInstance 值 strcpy(szTempStr, lpszDriverName);strcat(szTempStr, " Instance");if (RegSetValueEx(hKey, "DefaultInstance", 0, REG_SZ, (CONST BYTE*)szTempStr, (DWORD)strlen(szTempStr)) != ERROR_SUCCESS){return FALSE;}// 刷新注册表RegFlushKey(hKey);RegCloseKey(hKey);//-------------------------------------------------------------------------------------------------------// SYSTEM\\CurrentControlSet\\Services\\DriverName\\Instances\\DriverName Instance 子键下的键值项 //-------------------------------------------------------------------------------------------------------strcpy(szTempStr, "SYSTEM\\CurrentControlSet\\Services\\");strcat(szTempStr, lpszDriverName);strcat(szTempStr, "\\Instances\\");strcat(szTempStr, lpszDriverName);strcat(szTempStr, " Instance");if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szTempStr, 0, "", TRUE, KEY_ALL_ACCESS, NULL, &hKey, (LPDWORD)&dwData) != ERROR_SUCCESS){return FALSE;}// 注册表驱动程序的Altitude 值strcpy(szTempStr, lpszAltitude);if (RegSetValueEx(hKey, "Altitude", 0, REG_SZ, (CONST BYTE*)szTempStr, (DWORD)strlen(szTempStr)) != ERROR_SUCCESS){return FALSE;}// 注册表驱动程序的Flags 值dwData = 0x0;if (RegSetValueEx(hKey, "Flags", 0, REG_DWORD, (CONST BYTE*)&dwData, sizeof(DWORD)) != ERROR_SUCCESS){return FALSE;}// 刷新注册表RegFlushKey(hKey);RegCloseKey(hKey);return TRUE;
}// 启动驱动
BOOL StartDriver(const char* lpszDriverName)
{SC_HANDLE schManager;SC_HANDLE schService;SERVICE_STATUS svcStatus;if (NULL == lpszDriverName){return FALSE;}schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (NULL == schManager){CloseServiceHandle(schManager);return FALSE;}schService = OpenService(schManager, lpszDriverName, SERVICE_ALL_ACCESS);if (NULL == schService){CloseServiceHandle(schService);CloseServiceHandle(schManager);return FALSE;}if (!StartService(schService, 0, NULL)){CloseServiceHandle(schService);CloseServiceHandle(schManager);if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING){// 服务已经开启return TRUE;}return FALSE;}CloseServiceHandle(schService);CloseServiceHandle(schManager);return TRUE;
}// 关闭驱动
BOOL StopDriver(const char* lpszDriverName)
{SC_HANDLE schManager;SC_HANDLE schService;SERVICE_STATUS svcStatus;bool bStopped = false;schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (NULL == schManager){return FALSE;}schService = OpenService(schManager, lpszDriverName, SERVICE_ALL_ACCESS);if (NULL == schService){CloseServiceHandle(schManager);return FALSE;}if (!ControlService(schService, SERVICE_CONTROL_STOP, &svcStatus) && (svcStatus.dwCurrentState != SERVICE_STOPPED)){CloseServiceHandle(schService);CloseServiceHandle(schManager);return FALSE;}CloseServiceHandle(schService);CloseServiceHandle(schManager);return TRUE;
}// 删除驱动
BOOL DeleteDriver(const char* lpszDriverName)
{SC_HANDLE schManager;SC_HANDLE schService;SERVICE_STATUS svcStatus;schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);if (NULL == schManager){return FALSE;}schService = OpenService(schManager, lpszDriverName, SERVICE_ALL_ACCESS);if (NULL == schService){CloseServiceHandle(schManager);return FALSE;}ControlService(schService, SERVICE_CONTROL_STOP, &svcStatus);if (!DeleteService(schService)){CloseServiceHandle(schService);CloseServiceHandle(schManager);return FALSE;}CloseServiceHandle(schService);CloseServiceHandle(schManager);return TRUE;
}int main(int argc, char* argv[])
{InstallDriver("minifilter", ".\\WinDDK.sys", "225864");while (1){char str[20] = "\0";printf("请输入命令: ");gets(str);if (strcmp(str, "start") == 0){printf("[*] 启动驱动 \n");StartDriver("minifilter");}if (strcmp(str, "stop") == 0){printf("[-] 关闭驱动 \n");StopDriver("minifilter");}}return 0;
}

至此分别编译驱动程序,以及应用层下的安装程序,并将两者放入到同一目录下,运行客户端程序lyshark.exe并输入start启动驱动,输入stop则是关闭,启动后会看到如下信息;

这里简单介绍一下如何摘除微过滤驱动回调函数,其实摘除回调的方法有多种,常用的第一种通过向过滤驱动中写出一个返回命令让其不被执行从而实现绕过,另一种是找到回调函数并替换为我们自己的回调,而在自己的回调中什么也不做。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/197032.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全网最牛最“刑”的Fiddler移动端抓包

本篇文章&#xff0c;博主想使用通俗易懂的话语&#xff0c;让大家明白以下内容&#xff1a; 什么是抓包哪些场景需要用到抓包Fiddler抓包的原理怎样使用Fiddler进行移动端抓包 抓包 包 (Packet) 是TCP/IP协议通信传输中的数据单位&#xff0c;一般也称“数据包”。 我们平常…

无人机智慧工地:助力工地管理的未来之选

在现代工地管理中&#xff0c;无人机凭借其小巧、轻便和多角度拍摄等特点得到广泛应用&#xff0c;尤其在智慧工地的现场管理中发挥着重要作用。 一、无人机代替人工巡检省时省力 以往&#xff0c;施工现场检查主要依赖人工巡检方式&#xff0c;需要较长时间。而现在&#xff…

链表【2】

文章目录 &#x1f95d;24. 两两交换链表中的节点&#x1f951;题目&#x1f33d;算法原理&#x1f96c;代码实现 &#x1f34e;143. 重排链表&#x1f352;题目&#x1f345;算法原理&#x1f353;代码实现 &#x1f95d;24. 两两交换链表中的节点 &#x1f951;题目 题目链接…

KMP字符串

试题传送门&#xff1a;831. KMP字符串 给定一个字符串 S&#xff0c;以及一个模式串 P&#xff0c;所有字符串中只包含大小写英文字母以及阿拉伯数字。 模式串 P 在字符串 S 中多次作为子串出现。 求出模式串 P 在字符串 S 中所有出现的位置的起始下标。 输入格式 第一行输入…

Azure Machine Learning - Azure AI 搜索中的索引器

在 Azure AI 搜索中&#xff0c;搜索索引是可搜索的内容&#xff0c;可供搜索引擎用于索引编制、全文搜索和筛选后查询。 索引由架构定义并保存到搜索服务中&#xff0c;第二步是数据导入。 除了在主数据存储中&#xff0c;此内容也存在于搜索服务中&#xff0c;这是在新式应用…

由11月27日滴滴崩溃到近两个月国内互联网产品接二连三崩溃引发的感想

文章目录 知乎文分析微信聊天截图微信公众号 滴滴技术 发文k8s 官方文档滴滴官方微博账号 近两个月国内互联网产品“崩溃”事件2023-10-23 语雀崩溃2023-11-12 阿里云崩溃2023-11-27 滴滴崩溃2023-12-03 腾讯视频崩溃总结 我的感想 知乎文分析 最近连续加班&#xff0c;打车较…

todesk连接ubuntu显示当前系统并无桌面环境,或无显示器,无法显示远程桌面,您需要自行安装X11桌面环境,或者使用终端文件功能

ToDesk远程遇到的问题如上图&#xff0c;换向日葵直接黑屏&#xff1b; 问题原因 截止发文时间&#xff0c;Todesk只支持X11协议&#xff0c;没有适配最新的Wayland协议&#xff0c;所以我们需要把窗口系统调整为X11才可以。 解决方法 修改配置文件&#xff0c;关闭wayland su…

【模电】基本共射放大电路的工作原理及波形分析

基本共射放大电路的工作原理及波形分析 在上图所示的基本放大电路中&#xff0c;静态时的 I B Q I\tiny BQ IBQ、 I C Q I\tiny CQ ICQ、 U C E Q U\tiny CEQ UCEQ如下图( b )、( c )中虚线所标注。 &#xff08; a &#xff09; u i 的波形&#xff08; b &#xff09; i B …

LeetCode:1038. 从二叉搜索树到更大和树(反向中序遍历 C++、Java)

目录 1038. 从二叉搜索树到更大和树 题目描述&#xff1a; 实现代码与解析&#xff1a; dfs 原理思路&#xff1a; 1038. 从二叉搜索树到更大和树 题目描述&#xff1a; 给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所…

JDK8新特性——Stream流

文章目录 一、Stream流体验二、Stream流的创建三、Stream流中间方法四、Stream流终究方法 Stream流&#xff08;也叫Stream API&#xff09;。它是从JDK8以后才有的一个新特性&#xff0c;是专业用于对集合或者数组进行便捷操作的 一、Stream流体验 需求&#xff1a;有一个Lis…

linux远程桌面管理工具(xrdp)、向日葵

Windows远程桌面 linux远程桌面 使用向日葵远程桌面&#xff08;手机端同理&#xff09; Windows远程桌面 微软自带Remote Desktop Connection Manager &#xff08;RDCMan&#xff09;远程控制管理软件介绍 远程桌面连接管理器 v2.93 linux远程桌面 Windows远程桌面Ubunt…

JVM 运行时内存(三)

Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年代。 1. 新生代 是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象&#xff0c;所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、…

Android Framework 电池提醒相关Dialog熄屏消失的问题

记录一下花了三四天干一天就能完成的需求的傻事。 说在前头&#xff0c;这篇文章记录了电池提醒dialog相关&#xff0c;弹出dialog且熄屏再亮屏dialog不会消失的代码&#xff0c;这篇废话比较多&#xff0c;看正常代码直接跳到代码3。 故事背景 需求要求添加非法电池的弹窗&a…

[多线程]阻塞队列和生产者消费者模型

目录 1.阻塞队列 1.1引言 1.2Java标准库中的阻塞队列 1.3自主通过Java代码实现一个阻塞队列(泛型实现) 2.生产者消费者模型 1.阻塞队列 1.1引言 阻塞队列是多线程部分一个重要的概念,它相比于一般队列,有两个特点: 1.线程是安全的 2.带有阻塞功能 1) 队列为空,出队列就会阻…

语义分割 DeepLab V1网络学习笔记 (附代码)

论文地址&#xff1a;https://arxiv.org/abs/1412.7062 代码地址&#xff1a;GitHub - TheLegendAli/DeepLab-Context 1.是什么&#xff1f; DeepLab V1是一种基于VGG模型的语义分割模型&#xff0c;它使用了空洞卷积和全连接条件随机&#xff08;CRF&#xff09;来提高分割…

JAVA-作业7-画一个笑脸

要求如题 代码如下&#xff1a; SmileFace01: import java.awt.Color; import java.awt.Graphics;import javax.swing.JPanel;public class SmileFace01 extends JPanel {Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);int width getWidth(…

代码随想录刷题题Day5

刷题的第五天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C / Python Day5 任务 ● 哈希表理论基础 ● 242.有效的字母异位词 ● 349. 两个数组的交集 ● 202. 快乐数 ● 1. 两数之和 1 哈希表理…

MT8390商显广告机主板_MTK联发科安卓主板方案开发

商显广告机采用MediaTek 联发科平台主板方案。安卓主板具有更高的性能、更丰富的接口、更多的存储空间以及更为便捷的网络连接方式&#xff0c;可以满足更为复杂的开发和应用需求使其应用领域更加多元化&#xff0c;被广泛应用于各行各业。 商显广告机主板基于联发科MT8390八核…

智能AI系统ChatGPT网站系统源码+Midjourney绘画+支持DALL-E3文生图,支持最新GPT-4-Turbo模型

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

Ubuntu18.04安装Ipopt-3.12.8流程

本文主要介绍在Ubuntu18.04中安装Ipopt库的流程&#xff0c;及过程报错的解决方法&#xff0c;已经有很多关于Ipopt安装的博客&#xff0c;但经过我的测试&#xff0c;很多都失效了&#xff0c;经过探索&#xff0c;找到可流畅的安装Ipopt的方法&#xff0c;总结成本篇博客。 …