吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6408|回复: 19
收起左侧

[其他原创] [c]minifilter文件过滤驱动--实现查看文本内容替换为指定文本

  [复制链接]
白影33 发表于 2020-12-23 14:27
本帖最后由 白影33 于 2020-12-28 17:35 编辑

0x1前言
                写这篇文章不仅仅只为介绍功能的实现,也是为了作为一篇笔记来备忘,因此我会写的比较详细。
文中的注释有的来自微软官方的解释翻译,有的来自Windows内核安全与驱动开发书中的解释,也有的来自我个人的理解。
代码是在Windows内核安全与驱动开发第13章中minifilter代码的基础上完成的(我实现的功能源码中没有)。

0x2功能介绍
     MyMinifilter.sys:实现根据应用层软件输入,选择是否文本内容替换,过滤readbuffer内容,禁止notepad打开。
    MyDriverR3:系统驱动没有交互的界面,通过MyDriverR3与驱动进行交互。


       捕获a.PNG
    默认情况下:安装驱动后,读取true.txt的内容会被替换为false.txt的内容。(false.txt里全为0,
ture.txt全为1)

   
捕获b.PNG
    当在MyDriverR3输入52pojie:读取true.txt,就是ture.txt。
    再次启动MyDriverR3输入0:读取true.txt的内容会被替换为false.txt的内容。


0x3特殊说明
         大家应该注意到了,要过滤文本内容,为什么要禁止打开notepad,原因是filemap方式(解决办法我发评论)
我在实践中,使用debugview查看打印替换或的缓冲区内容,显示替换成false.txt,然而打开notepad却还是true.txt里的内容,
我又在网上下了个EditPlus测试,用EditPlus打开查看为false.txt,替换成功,我又下了个notepad++测试,也是替换成功,所以有了这么一个折中的办法,禁止打开notepad,这个很简单对create进行过滤,是打开notepad就让它失败,(评论里我发了一个好点的办法,具体看评论)
0x4难点攻克
               这里说明我遇到的难点,以及解决办法。
难点:对目标文件打开后无IRP_MJ_READ的IRP。
解决方案:通过查阅书籍,发现为window文件缓冲机制导致的问题
152010wkjsfj9bsjcs9fj9.png
window文件缓冲机制是:


window读文件会首先从文件缓冲中读取,如果文件缓冲中没有,
就会触发缺页异常从而发送IRP_MJ_READ从硬盘里读取,放入文件缓冲中。


如果文件缓冲中有,那就直接从内存中读取,不会发送IRP_MJ_READ。


对于这个问题书籍里用CcPurgeCacheSection然后和一些函数清除文件缓冲,
不知道是不是因为我的是minifilter而他的是普通的文件过滤驱动的区别,我调用该函数即使返回显示成功
依然没有IRP_MJ_READ,书上的办法对于我来说,行不通。


在一次测试中发现:如果对文件内容进行修改,点击保存就会有IRP_MJ_READ,
据此猜想,window在每次对原文件的修改保存后,会发送IRP_MJ_READ从硬盘上重新读取内容
同步到文件缓冲里,这样我就有了一个大胆的想法。


在DriverEntry里用ZwWriteFile对文件写入空格(注意重入问题),这样就会触发read的irp,我就把false.txt内容替换到
文件缓冲,
然后在NPMiniMessage与应用层交互的函数里,也对文件进行写入触发read的irp,根据应用层输入的字符串,来判断替换为那个文件的内容
0x4蓝屏日志
       这里是记录自己在写驱动过程中遇到的问题,以及解决办法。

问题1:驱动安装蓝屏,windbg调试后发现FltRegisterFilter注册函数失败
解决办法:minifilter需要修改注册表,我用Windows内核安全与驱动开发的minifilter的inf文件右键安装后,再用drivermonitor安装FltRegisterFilter就返回成功

问题2:minifilter读后操作回调例程 里的PAGED_CODE();断下,PAGED_CODE();检查irql是否低于或等于APC_LEVEL,不成立就中断
130906m2cb51c0zd1acfi9.png
解决办法:通过查阅微软官方文档发现minifilter后操作回调例程可以运行在高于APC_LEVEL的irql,不需要用PAGED_CODE来检查。


问题3:FltGetFileNameInformation会不时蓝屏

解决办法:通过对比官方代码,发现一些失败的情况没有直接返回,把而是失败的irp的数据给FltGetFileNameInformation会蓝屏,加上代码
if (!NT_SUCCESS( Data->IoStatus.Status ) ||  (STATUS_REPARSE == Data->IoStatus.Status))
{
return FLT_POSTOP_FINISHED_PROCESSING;
   }
检查,如果失败就直接返回,不调用FltGetFileNameInformation。



问题4:ZwReadFile/ZwWriteFile蓝屏
解决办法: 参数 8_In_opt_ PLARGE_INTEGER ByteOffset,不能直接给数,
例如:错误ZwReadFile(myhand2, NULL, NULL, NULL, &BLOCK2, str2, 500, 50, NULL);
正确    LARGE_INTEGER size2.QuadPart = 0;
        status = ZwReadFile(myhand2, NULL, NULL, NULL, &BLOCK2, str2, 500, &size2, NULL);
(血的教训,蓝了我一下午)

问题5:RtlCopyMemory蓝屏
捕获.PNG

解决办法:我是在post回调函数中使用这个函数,post函数IRQL高一些,
微软官方的解释的意思是如果在高IRQL使用,原地址和目标地址的内存最好都是非分页内存。

问题6:DriverEntry的ZwReadFile蓝屏,
解决办法:调用ZwReadFile读取目标文件内容用于替换,而我又过滤了read的,read里面又需要用到这个ZwReadFile读取的内容
此时为空,导致蓝屏,解决办法用一个变量,读完后给它赋值,而后在read过滤时检查,如果变量没有赋值,就不过滤。


0x6驱动源码及注释
[C] 纯文本查看 复制代码
#include "minifilter.h"
NTSTATUS
DriverEntry(
__in PDRIVER_OBJECT DriverObject,  //PDRIVER_OBJECT 驱动数据结构(驱动对象)的指针
__in PUNICODE_STRING RegistryPath//PUNICODE_STRING 内核字符串数组,驱动以服务的形式加载,这个字符串为驱动在注册表的路径
)
{
        NTSTATUS status;              //返回值状态
        PSECURITY_DESCRIPTOR sd;     //安全描述符。
        OBJECT_ATTRIBUTES oa;        //对象属性
        UNICODE_STRING uniString;                //用于通信端口名称

        UNREFERENCED_PARAMETER(RegistryPath);//避免编译器关于未引用参数的警告


        // 注册FilterRegistration,告诉系统我设置的回调例程
        //第1个参数是本驱动的驱动对象,是在入口函数DriverEntry 中作为参数传入的。
        //第2个参数就是一个注册信息的结构,这个结构内含描述这个过滤器的所有信息
        //第3个参数 是一个返回参数,返回注册成功的微过滤器句柄,在下面调用函数FltStartFiltering时会用到
        //DbgPrint("statuswww=\n");
        status = FltRegisterFilter(DriverObject,
                &FilterRegistration,
                &gFilterHandle);

        ASSERT(NT_SUCCESS(status));//检查结果是否成功,失败后触发异常被调试器接管

        if (NT_SUCCESS(status)) {//检查结果是否成功,

                //
                //  开始函数,只有一个参数为之前获取的句柄
                //

                status = FltStartFiltering(gFilterHandle);

                if (!NT_SUCCESS(status)) {
                        //如果失败就取消注册,只有一个参数为之前获取的句柄
                        FltUnregisterFilter(gFilterHandle);
                }
        }

        //FltBuildDefaultSecurityDescriptor构建一个默认的安全描述符,用于FltCreateCommunicationPort。
        //参数1指向调用方分配的变量的指针,该变量接收到指向新创建的不透明指针
        //参数2指定调用者需要对端口对象的访问类型的标志的位掩码。系统定义的DesiredAccess标志集确定了minifilter驱动程序通信端口对象的以下特定访问权限。
        status = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS);

        if (!NT_SUCCESS(status)) {//检查结果是否成功,未成功就跳向最终处理部分
                goto final;
        }

        //函数初始化Unicode字符的计数字符串
        RtlInitUnicodeString(&uniString, MINISPY_PORT_NAME);

        //宏初始化不透明的OBJECT_ATTRIBUTES结构,该结构将对象句柄的属性指定给打开句柄的例程。
        //参数1为要被初始化的结构体,参数2一个指向Unicode字符串的指针,该字符串包含要为其打开句柄的对象的名称。
        //这必须是一个完全限定的对象名,或者由RootDirectory参数指定的对象目录的相对路径名。
        //参数3标志位,此处指定为只在内核模式访问,与对大小写不区分
        //参数4在ObjectName参数中指定的路径名的根对象目录句柄。如果ObjectName是完全限定的对象名称,
        //则RootDirectory为空。使用ZwCreateDirectoryObject获得对象目录的句柄。
        //参数5指定创建对象时应用于该对象的安全描述符。此参数是可选的。驱动程序可以指定NULL来接受对象的默认安全性。
        InitializeObjectAttributes(&oa,
                &uniString,
                OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
                NULL,
                sd);

        //创建一个通信服务器端口,minifilter驱动程序可以在该端口上接收来自用户模式应用程序的连接请求。
        // 参数1调用者的不透明过滤器指针
        //参数2指向调用方分配的变量的指针,该变量接收通信服务器端口的不透明端口句柄。minifilter驱动程序使用这个句柄来监听来自用户模式应用程序的连接请求。
        //参数3指向OBJECT_ATTRIBUTES结构的指针,该结构指定通信服务器端口的属性。
        //此结构必须由之前的InitializeObjectAttributes调用初始化。此参数是必需的,不能为空。通信端口对象的此结构的成员包括以下内容。
        //参数4指向由minifilter驱动程序定义的上下文信息的指针。这个信息可以用来区分由相同的minifilter驱动程序创建的多个通信服务器端口。
        //过滤器管理器将这个上下文指针作为参数传递给ConnectNotifyCallback例程。该参数是可选的,可以为NULL。
        //参数5 NPMiniConneet是用户态与内核态建立连接时内核会调用到的函数。
        //参数6 NPMiniDisconnect 是用户态与内核态连接结束时内核会调用到的函数。。
        //参数7 NPMiniMessage是用户态与内核态传送数据时内核会调用到的函数
        //参数8此服务器端口所允许的最大并发客户端连接数。此参数是必需的,且必须大于零。
        status = FltCreateCommunicationPort(gFilterHandle,
                &gServerPort,
                &oa,
                NULL,
                NPMiniConnect,
                NPMiniDisconnect,
                NPMiniMessage,
                1);
        //释放分配的安全描述符
        FltFreeSecurityDescriptor(sd);

        if (!NT_SUCCESS(status)) {
                goto final;
        }

        // 返回值

        // 首先初始化含有文件路径的OBJECT_ATTRIBU
        UNICODE_STRING mytext1;  //文件名字符串
        OBJECT_ATTRIBUTES ATTRIBUTES1;
        IO_STATUS_BLOCK BLOCK1;//可拥有的控制权  
        LARGE_INTEGER size1;  //写的偏移大小

        str1 = ExAllocatePool(NonPagedPool, 500);//分配500的非分页内存
        RtlZeroMemory(str1, 500);//清0内存

        RtlInitUnicodeString(&mytext1, L"\\??\\C:\\true.txt");//初始化文件名  
        memset(&ATTRIBUTES1, 0, sizeof(OBJECT_ATTRIBUTES));                        //对象属性清空  
        size1.QuadPart = 0;

        InitializeObjectAttributes(&ATTRIBUTES1, &mytext1, OBJ_CASE_INSENSITIVE, NULL, NULL);//对象属性关键是文件名字 不区分大小写 ,参数意义同上

        //打开目标文件获取句柄
        //参数1:一个指向句柄变量的指针,该句柄用于接收文件的句柄。
        //参数2:指定ACCESS_MASK值,该值确定请求对对象的访问。除了为所有类型的对象定义的访问权限之外,调用者还可以指定以下特定于文件的访问权限。
        //参数3:OBJECT_ATTRIBUTES结构的指针,该结构指定对象名和其他属性。使用InitializeObjectAttributes初始化该结构。
        //参数4:用于接收最终完成状态和请求操作的其他信息
        //参数5:它包含创建或覆盖的文件的初始分配大小,可以为Null
        //参数6:表示创建或覆盖文件时要设置的文件属性。调用者通常指定FILE_ATTRIBUTE_NORMAL,它设置默认属性
        //参数7:共享访问的类型,
        //参数8:指定在文件存在或不存在时执行的操作
        //参数9:指定驱动程序创建或打开文件时应用的选项
        //参数10:对于设备和中间驱动程序,此参数必须为空指针
        //参数11:对于设备和中间驱动程序,此参数必须为零。
        status = ZwCreateFile(&myhandl, GENERIC_ALL, &ATTRIBUTES1, &BLOCK1, NULL, FILE_ATTRIBUTE_NORMAL,
                FILE_SHARE_READ, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, NULL, 0);

        //通过句柄读取目标文件放入str1
        if (!NT_SUCCESS(status))
        {
                FirsT = 0;
                goto final;
        }
        else
        {
                status = ZwReadFile(myhandl, NULL, NULL, NULL, &BLOCK1, str1, 500, &size1, NULL);
                FirsT = 1;//防止重入
                DbgPrint("status=%X\n", status);

        }

        //以下内容基本同上只是文件的对象不一样
        UNICODE_STRING mytext2;
        OBJECT_ATTRIBUTES ATTRIBUTES2;
        IO_STATUS_BLOCK BLOCK2;//可拥有的控制权  
        LARGE_INTEGER size2;
        str2 = ExAllocatePool(NonPagedPool, 500);
        RtlZeroMemory(str2, 500);
        RtlInitUnicodeString(&mytext2, L"\\??\\C:\\false.txt");//初始化文件名  
        memset(&ATTRIBUTES2, 0, sizeof(OBJECT_ATTRIBUTES));                        //对象属性清空  
        size2.QuadPart = 0;
        InitializeObjectAttributes(&ATTRIBUTES2, &mytext2, OBJ_CASE_INSENSITIVE, NULL, NULL);//对象属性关键是文件名字 不区分大小写  
        status = ZwCreateFile(&myhand2, GENERIC_ALL, &ATTRIBUTES2, &BLOCK2, NULL, FILE_ATTRIBUTE_NORMAL,
                FILE_SHARE_READ, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, NULL, 0);
        if (!NT_SUCCESS(status))
        {
                FirsT = 0;
                goto final;
        }
        else
        {
                status = ZwReadFile(myhand2, NULL, NULL, NULL, &BLOCK2, str2, 500, &size2, NULL);
                DbgPrint("status2=%X\n", status);

        }



        //对目标文件进行写入,从而触发read
        PVOID str3 = ExAllocatePool(PagedPool, 10);
        RtlZeroMemory(str3, 6);
        RtlCopyMemory(str3, "...", strlen("..."));
        size1.HighPart = 0;
        size1.QuadPart = 500;
        status = ZwWriteFile(myhandl, NULL, NULL, NULL, &BLOCK1, str3, 6, &size1, NULL);


        //关闭句柄
        ZwClose(myhandl);
        ZwClose(myhand2);
        final ://失败处理处

        if (!NT_SUCCESS(status)) {

                if (NULL != gServerPort) {
                        //关闭过滤器驱动程序的通信服务器端口
                        FltCloseCommunicationPort(gServerPort);
                }

                if (NULL != gFilterHandle) {
                        //取消注册
                        FltUnregisterFilter(gFilterHandle);
                }
        }
        return status;
}
FLT_PREOP_CALLBACK_STATUS
MyPostRead(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_In_opt_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{

        UNREFERENCED_PARAMETER(Flags);
        UNREFERENCED_PARAMETER(CompletionContext);
        char FileName[260] = "X:";//存放解析后的文件名字

        NTSTATUS status;  //返回值状态
        PFLT_FILE_NAME_INFORMATION nameInfo; //名称信息
        //
        // 对失败的irp进行过滤,如果失败了,就不用继续
        if (!NT_SUCCESS(Data->IoStatus.Status) ||
                (STATUS_REPARSE == Data->IoStatus.Status)) {

                return FLT_POSTOP_FINISHED_PROCESSING;
        }



        //FltGetFileNameInformation例程返回文件或目录的名称信息。                                                                               
        status = FltGetFileNameInformation(Data,//PFLT_CALLBACK_DATA结构的指针,它是I/O操作的回调数据结构。此参数是必需的,不能为空。
                FLT_FILE_NAME_NORMALIZED |//使nameInfo参数接收包含文件规范化名称的结构的地址。
                FLT_FILE_NAME_QUERY_DEFAULT,//如果查询文件系统以获取文件名目前还不安全,则FltGetFileNameInformation将不执行任何操作。
                //否则,FltGetFileNameInformation查询过滤器管理器的名称缓存以获取文件名信息。
                //如果在缓存中没有找到该名称,则FltGetFileNameInformation查询文件系统并缓存结果。
                &nameInfo);//包含文件名信息。

        if (NT_SUCCESS(status))
        {
                //解析FLT_FILE_NAME_INFORMATION结构的内容。
                status = FltParseFileNameInformation(nameInfo);


                //参数1大小写转换,后放入参数2
                if (NPUnicodeStringToChar(&nameInfo->Name, FileName))
                {
                        //DbgPrint("FileName is %s\n", FileName);
                        if (strstr(FileName, "TRUE.TXT") > 0)
                        {
                                PUCHAR buf1;

                                if (Data->Iopb->Parameters.Read.MdlAddress != 0)
                                {
                                        //如果为mdl方式读取文件,就获取地址
                                        buf1 = MmGetSystemAddressForMdl(Data->Iopb->Parameters.Read.MdlAddress);

                                }
                                else
                                {
                                        //如果为ReadBuffer就直接给指针
                                        buf1 = Data->Iopb->Parameters.Read.ReadBuffer;
                                }
                                //判断应用层发来的指令是否为显示true.txt
                                if (command == 2)
                                {
                                        if (FirsT == 1)
                                        {
                                                //复制内存,填写长度
                                                RtlCopyMemory(buf1, str1, 500);
                                                Data->IoStatus.Information = Data->Iopb->Parameters.Read.Length;
                                        }
                                }
                                else
                                {
                                        //DbgBreakPoint();
                                        if (FirsT == 1)
                                        {
                                                //复制内存,填写长度
                                                RtlCopyMemory(buf1, str2, 500);
                                                Data->IoStatus.Information = Data->Iopb->Parameters.Read.Length;
                                        }

                                }
                                DbgPrint("ReadBuffed=%s", buf1);
                                //释放文件名信息结构体的内存
                                FltReleaseFileNameInformation(nameInfo);
                                return FLT_POSTOP_FINISHED_PROCESSING;
                        }
                }

                FltReleaseFileNameInformation(nameInfo);
        }

        return FLT_POSTOP_FINISHED_PROCESSING;

}

NTSTATUS
NPMiniMessage(
__in PVOID ConnectionCookie,
__in_bcount_opt(InputBufferSize) PVOID InputBuffer,
__in ULONG InputBufferSize,
__out_bcount_part_opt(OutputBufferSize, *ReturnOutputBufferLength) PVOID OutputBuffer,
__in ULONG OutputBufferSize,
__out PULONG ReturnOutputBufferLength
)
{
        //写入文件需要的各种参数,意义同dirverEntry
        NTSTATUS status;
        UNICODE_STRING mytext1;
        OBJECT_ATTRIBUTES ATTRIBUTES1;
        IO_STATUS_BLOCK BLOCK1;//可拥有的控制权  
        LARGE_INTEGER size1;
        PVOID str4 = ExAllocatePool(PagedPool, 40);
        RtlZeroMemory(str4, 40);
        RtlInitUnicodeString(&mytext1, L"\\??\\C:\\true.txt");//初始化文件名  
        memset(&ATTRIBUTES1, 0, sizeof(OBJECT_ATTRIBUTES));                        //对象属性清空  
        size1.QuadPart = 0;


        PAGED_CODE();
        //分配内存,存储字符串,用于和应用层字符串比较
        PVOID test;
        test = ExAllocatePool(PagedPool, 10);
        RtlCopyMemory(test, "0", strlen("0"));
        PVOID test2;
        test2 = ExAllocatePool(PagedPool, 50);
        RtlCopyMemory(test2, "52pojie", strlen("52pojie"));


        UNREFERENCED_PARAMETER(ConnectionCookie);
        UNREFERENCED_PARAMETER(OutputBufferSize);
        UNREFERENCED_PARAMETER(OutputBuffer);

        //通过应用层输入的字符串,来显示相应的文本
        if (strcmp(InputBuffer, test) == 0)
        {
                command = 1;
        }
        else if (strcmp(InputBuffer, test2) == 0)
        {
                command = 2;
        }
        else
        {
                status = STATUS_INVALID_PARAMETER;

        }
        //向文件写入,来触发read,由于需要内容不同,所以通过改变ONOROFF,实现两种写入依次执行
        if (ONOROFF == 0)
        {
                //向文件写入空格
                ONOROFF = ONOROFF + 1;
                InitializeObjectAttributes(&ATTRIBUTES1, &mytext1, OBJ_CASE_INSENSITIVE, NULL, NULL);//对象属性关键是文件名字 不区分大小写  
                status = ZwCreateFile(&myhandl, GENERIC_ALL, &ATTRIBUTES1, &BLOCK1, NULL, FILE_ATTRIBUTE_NORMAL,
                        FILE_SHARE_READ, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, NULL, 0);
                RtlCopyMemory(str4, "    ", strlen("    "));
                size1.HighPart = 0;
                size1.QuadPart = 500;
                status = ZwWriteFile(myhandl, NULL, NULL, NULL, &BLOCK1, str4, 8, &size1, NULL);
                ZwClose(myhandl);
        }
        else
        {
                //向文件写入"****",
                ONOROFF = ONOROFF - 1;
                InitializeObjectAttributes(&ATTRIBUTES1, &mytext1, OBJ_CASE_INSENSITIVE, NULL, NULL);//对象属性关键是文件名字 不区分大小写  
                status = ZwCreateFile(&myhandl, GENERIC_ALL, &ATTRIBUTES1, &BLOCK1, NULL, FILE_ATTRIBUTE_NORMAL,
                        FILE_SHARE_READ, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, NULL, 0);
                RtlCopyMemory(str4, "****", strlen("****"));
                size1.HighPart = 0;
                size1.QuadPart = 500;
                status = ZwWriteFile(myhandl, NULL, NULL, NULL, &BLOCK1, str4, 8, &size1, NULL);
                ZwClose(myhandl);
        }

        //释放内存
        ExFreePool(str4);
        ExFreePool(test);
        ExFreePool(test2);
        return STATUS_SUCCESS;
}

BOOLEAN NPUnicodeStringToChar(PUNICODE_STRING UniName, char Name[])
{
        ANSI_STRING        AnsiName;
        NTSTATUS        ntstatus;
        char*                nameptr;

        __try {
                ntstatus = RtlUnicodeStringToAnsiString(&AnsiName, UniName, TRUE);

                if (AnsiName.Length < 260) {
                        nameptr = (PCHAR)AnsiName.Buffer;
                        //转换成大写和复制到缓冲区
                        strcpy(Name, _strupr(nameptr));
                        //DbgPrint("NPUnicodeStringToChar : %s\n", Name);        
                }
                RtlFreeAnsiString(&AnsiName);
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
                DbgPrint("NPUnicodeStringToChar EXCEPTION_EXECUTE_HANDLER\n");
                return FALSE;
        }
        return TRUE;
}

NTSTATUS NPInstanceSetup(
        __in PCFLT_RELATED_OBJECTS FltObjects,
        __in FLT_INSTANCE_SETUP_FLAGS Flags,
        __in DEVICE_TYPE VolumeDeviceType,
        __in FLT_FILESYSTEM_TYPE VolumeFilesystemType
        )
{
        UNREFERENCED_PARAMETER(FltObjects);
        UNREFERENCED_PARAMETER(Flags);
        UNREFERENCED_PARAMETER(VolumeDeviceType);
        UNREFERENCED_PARAMETER(VolumeFilesystemType);

        PAGED_CODE();



        return STATUS_SUCCESS;
}


NTSTATUS
NPInstanceQueryTeardown(
__in PCFLT_RELATED_OBJECTS FltObjects,
__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
)
{
        UNREFERENCED_PARAMETER(FltObjects);
        UNREFERENCED_PARAMETER(Flags);

        PAGED_CODE();


        return STATUS_SUCCESS;
}


VOID NPInstanceTeardownStart(
        __in PCFLT_RELATED_OBJECTS FltObjects,
        __in FLT_INSTANCE_TEARDOWN_FLAGS Flags
        )
{
        UNREFERENCED_PARAMETER(FltObjects);
        UNREFERENCED_PARAMETER(Flags);

        PAGED_CODE();


}


VOID NPInstanceTeardownComplete(
        __in PCFLT_RELATED_OBJECTS FltObjects,
        __in FLT_INSTANCE_TEARDOWN_FLAGS Flags
        )
{
        UNREFERENCED_PARAMETER(FltObjects);
        UNREFERENCED_PARAMETER(Flags);

        PAGED_CODE();


}

NTSTATUS
NPUnload(
__in FLT_FILTER_UNLOAD_FLAGS Flags
)
{
        UNREFERENCED_PARAMETER(Flags);

        PAGED_CODE();


        ExFreePool(str1);
        ExFreePool(str2);
        FltCloseCommunicationPort(gServerPort);

        FltUnregisterFilter(gFilterHandle);

        return STATUS_SUCCESS;
}

FLT_PREOP_CALLBACK_STATUS
NPPreCreate(
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
        char FileName[260] = "X:";

        NTSTATUS status;
        PFLT_FILE_NAME_INFORMATION nameInfo;

        UNREFERENCED_PARAMETER(FltObjects);
        UNREFERENCED_PARAMETER(CompletionContext);

        PAGED_CODE();


        status = FltGetFileNameInformation(Data,
                FLT_FILE_NAME_NORMALIZED |
                FLT_FILE_NAME_QUERY_DEFAULT,
                &nameInfo);
        if (NT_SUCCESS(status)) {

                if (1) {
                        FltParseFileNameInformation(nameInfo);
                        if (NPUnicodeStringToChar(&nameInfo->Name, FileName)) {

                                if (strstr(FileName, "NOTEPAD.EXE") > 0) {


                                        FltReleaseFileNameInformation(nameInfo);
                                        return FLT_PREOP_COMPLETE;
                                }
                        }
                }
                FltReleaseFileNameInformation(nameInfo);
        }

        return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}




NTSTATUS
NPMiniConnect(
__in PFLT_PORT ClientPort,
__in PVOID ServerPortCookie,
__in_bcount(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
)
{
        DbgPrint("[mini-filter] NPMiniConnect");
        PAGED_CODE();

        UNREFERENCED_PARAMETER(ServerPortCookie);
        UNREFERENCED_PARAMETER(ConnectionContext);
        UNREFERENCED_PARAMETER(SizeOfContext);
        UNREFERENCED_PARAMETER(ConnectionCookie);

        ASSERT(gClientPort == NULL);
        gClientPort = ClientPort;
        return STATUS_SUCCESS;
}

VOID
NPMiniDisconnect(
__in_opt PVOID ConnectionCookie
)
{
        PAGED_CODE();
        UNREFERENCED_PARAMETER(ConnectionCookie);
        DbgPrint("[mini-filter] NPMiniDisconnect");

        //  Close our handle
        FltCloseClientPort(gFilterHandle, &gClientPort);
}


0x7应用层源码
及注释
[C] 纯文本查看 复制代码
#include "windows.h"
#include <stdio.h>
#include <FltUser.h>

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "fltLib.lib")

extern HANDLE g_hPort;

#define NPMINI_NAME            L"MYminifilter"
#define NPMINI_PORT_NAME       L"\\MYMiniPort"
HANDLE g_hPort = INVALID_HANDLE_VALUE;
#ifdef _MANAGED
#pragma managed(push, off)
#endif
#ifdef _MANAGED
#pragma managed(pop)
#endif

int InitialCommunicationPort(void)
{
        DWORD hResult = FilterConnectCommunicationPort(
                NPMINI_PORT_NAME,
                0,
                NULL,
                0,
                NULL,
                &g_hPort);

        if (hResult != S_OK) {
                return hResult;
        }
        return 0;
}

int NPSendMessage(PVOID InputBuffer)
{
        DWORD bytesReturned = 0;
        DWORD hResult = 0;
        

        hResult = FilterSendMessage(
                g_hPort,
                InputBuffer,
                sizeof(InputBuffer),
                NULL,
                NULL,
                &bytesReturned);

        if (hResult != S_OK) {
                return hResult;
        }
        return 0;
}
void main()
{
        int errorCode=InitialCommunicationPort();
        if (errorCode!=0)
        {
                printf("errorCode is %x\n", errorCode);
        }
        printf("enter your code:");
        char string[20] = { 0 };
        
        scanf("%s", string);
        PVOID s1 = 0;
        s1 = &string;
        NPSendMessage(s1);
        system("pause");
}

0x8文件及使用

     使用我发的文件里的inf安装驱动,然后用drivermonitor启动,过滤的文件位置默认为c盘,就是c:\\,
想放在其他位置修改源码里的路径就行,true.txt和false.txt复制到这个路径就行了,当然你也可以自己创建这两个文件,
过滤目标文件也可以通过修改源码里的名字进行修改,由于版规不能发成品,所以你需要自己编译,
编译环境:vs2013+wdk8.1,测试成功系统:win7x64
所有的文件链接:https://pan.baidu.com/s/1eyOwGI7XoCok1KN00_xPEg
提取码:ras6
解压密码:52pojie

免费评分

参与人数 27威望 +1 吾爱币 +78 热心值 +24 收起 理由
大根君爱打牌 + 1 + 1 热心回复!
Bizhi-1024 + 1 热心回复!
hxtlcc + 1 我很赞同!
文姐姐 + 1 我很赞同!
Max陳大發 + 1 + 1 谢谢@Thanks!
fengbolee + 1 + 1 用心讨论,共获提升!
后悔莫及 + 1 + 1 我很赞同!
5omggx + 1 + 1 用心讨论,共获提升!
海水很咸 + 1 + 1 用心讨论,共获提升!
lookerJ + 1 + 1 用心讨论,共获提升!
zhoumeto + 1 + 1 用心讨论,共获提升!
塞活 + 1 + 1 我很赞同!
一点丶心动 + 1 热心回复!
女萝岩 + 1 + 1 我很赞同!
gaosld + 1 + 1 谢谢@Thanks!
soyiC + 2 + 1 用心讨论,共获提升!
ZXL_zx + 1 + 1 我很赞同!
笙若 + 1 + 1 谢谢@Thanks!
Yennfer_ + 1 + 1 用心讨论,共获提升!
独行风云 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
我要学外挂 + 1 + 1 点赞
asdiopss + 3 + 1 谢谢@Thanks!牛B上天了!
非典型男 + 1 + 1 我很赞同!
小叮当萌新 + 1 + 1 我很赞同!
hjthack + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
苏紫方璇 + 1 + 50 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lsz7575 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

5omggx 发表于 2021-1-1 17:23
In another thread within the last few months, it was pointed out that
NotePad uses memory mapping to access its files, so IRP_MJ_READ/WRITE will
never be seen. It is always safe to assume that any file, at any time,
might be memory-mapped.
joe
请楼主看看能否解决目前遇到的问题:https://community.osr.com/discussion/243780/minifilter-encrypt-vs-notepad
 楼主| 白影33 发表于 2021-1-2 17:35
5omggx 发表于 2021-1-1 17:23
In another thread within the last few months, it was pointed out that
NotePad uses memory mapping t ...

能不能你自己试一下,宁外notepad是用filemaping的方式,好像是read过滤不倒,好点的办法让返回失败,看看我发的第一个评论
lsz7575 发表于 2020-12-23 19:37
hjthack 发表于 2020-12-24 08:36
感谢楼主分享。
红叶落尽 发表于 2020-12-25 08:07
感谢大牛的分享 虽然看不大懂 学习一下思路也是极好的
一切已过都还好 发表于 2020-12-25 19:15
感谢楼主分享,支持一下!
巴黎街头的阳光 发表于 2020-12-25 19:59

感谢楼主分享!!!!!
20000721yy 发表于 2020-12-26 14:56
感谢楼主分享,支持一下!
回的一手好帖 发表于 2020-12-28 17:19
支持 支持 感谢分享
 楼主| 白影33 发表于 2020-12-28 17:34
完善有个简单的办法,就不修改或者发新贴了,直接评论里说一下,直接让打开这个的irp返回失败就行了,射是那个irp我还没找到。
屏幕截图 2020-12-28 171510.png

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
5omggx + 1 + 1 用心讨论,共获提升!

查看全部评分

fengbolee 发表于 2020-12-29 14:12
感谢精彩原创分享。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-26 22:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表