首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Minifilter驱动程序、内存映射和记事本

Minifilter驱动程序、内存映射和记事本
EN

Stack Overflow用户
提问于 2012-10-05 04:15:32
回答 1查看 3.8K关注 0票数 4

我将从我的最终目标开始。我希望每个文档(doc、docx、pdf、txt等)在我的系统上将有一个固定的(和用户的)头。例如,字符串"abcde“将被放在每个文档的前面。

为此,我编写了一个微过滤器驱动程序,它执行以下操作:

IRP_MJ_WRITE -如果头部存在,则将偏移量更改为文件的开始位置。

IRP_MJ_READ -如果头部存在,则将偏移量更改为文件的开始位置。

IRP_MJ_QUERY_INFORMATION -如果头部存在,则更改返回的文件大小。

IRP_MJ_DIRECTORY_CONTROL -如果头部存在,则更改返回的文件大小。

IRP_MJ_CREATE -如果标题不存在,则将标题预置到文件中。

除了在MS Word 2003文档(doc、xls、ppt)和记事本上,这种方法工作得很好。我似乎只是没有捕捉到一些读写操作,而notepad显示了标题和文件。

我在http://www.osronline.com/上读了很多书,每一个在那里请求的人都被告知要读一些Nagar的书或者看看他们的档案(这些档案很难搜索到)。我想我已经在那里读到了所有与我的问题相关的东西。

似乎记事本使用内存映射文件,快速IO,分页IO和天知道还有什么。我曾尝试将NtMapViewOfSectionMapViewOfFileMapViewOfFileEx与mHook挂钩,但当我在记事本中打开一些文件并试图找到映射的数据时,我没有运气(但我找到了映射到内存的所有其他字节)。

然后我读到我试图完成的事情不可能使用钩子,只有使用微过滤器驱动,从我认为我丢失了一些要设置的标志。

如果有人能告诉我怎么做才能捕捉到notepad的操作,我会非常感激的。

下面是一些阅读代码示例:

代码语言:javascript
复制
CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
    { IRP_MJ_WRITE,
    0,
    PreWrite,
    PostWrite },

    { IRP_MJ_READ,
    0,
    PreRead,
    PostRead },

    { IRP_MJ_QUERY_INFORMATION,
    0,
    NULL,
    PostQueryInfo },

    { IRP_MJ_DIRECTORY_CONTROL,
    0,
    NULL,
    PostQueryDir },

    { IRP_MJ_CREATE,
    0,
    NULL,
    PostCreate },

    { IRP_MJ_OPERATION_END }
};

FLT_PREOP_CALLBACK_STATUS
    PreRead (
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID *CompletionContext
    )
{
    NTSTATUS status = 0;
    ULONG bytesRead;
    PVOID readBuffer;
    LARGE_INTEGER zero;
    zero.QuadPart = 0;

    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(Data);
    UNREFERENCED_PARAMETER(CompletionContext);

    if(Data->Iopb->Parameters.Read.MdlAddress != NULL){
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    if(!IsFileNeedProccessing(&FltObjects->FileObject->FileName, Data)){
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }


    readBuffer = ExAllocatePool(
        NonPagedPool,
        prefixSize);
    if(readBuffer == NULL)
    {
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    status = FltReadFile(
        FltObjects->Instance,
        FltObjects->FileObject,
        &zero,
        (ULONG)prefixSize,
        readBuffer,
        FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
        &bytesRead,
        NULL,
        NULL);

    if(NT_SUCCESS(status))
    {
        if(IsBuffAPrefixOfBuffB(prefix, readBuffer, prefixSize, (SIZE_T)bytesRead))
        {
            Data->Iopb->Parameters.Read.ByteOffset.QuadPart += prefixSize;
            FltSetCallbackDataDirty(Data);
        }
    }
    ExFreePool(readBuffer);

    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}

 FLT_POSTOP_CALLBACK_STATUS
    PostRead (
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_opt_ PVOID CompletionContext,
    _In_ FLT_POST_OPERATION_FLAGS Flags
    )
 {
    NTSTATUS status;
    ULONG bytesRead;
    PVOID readBuffer;
    FILE_STANDARD_INFORMATION info;
    LONGLONG* currOffset = &Data->Iopb->TargetFileObject->CurrentByteOffset.QuadPart;
    LARGE_INTEGER zero;
    zero.QuadPart = 0;

    UNREFERENCED_PARAMETER(CompletionContext);
    UNREFERENCED_PARAMETER(Flags);
    UNREFERENCED_PARAMETER(Data);
    UNREFERENCED_PARAMETER(FltObjects);

    if(Data->Iopb->Parameters.Read.MdlAddress != NULL)
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    if(!IsFileNeedProccessing(&FltObjects->FileObject->FileName, Data))
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    status = FltQueryInformationFile(
        FltObjects->Instance,
        FltObjects->FileObject,
        &info,
        sizeof(info),
        FileStandardInformation,
        NULL);

    if(NT_SUCCESS(status)
        && info.EndOfFile.QuadPart != *currOffset
        && *currOffset >= (LONGLONG)prefixSize)
    {
        readBuffer = ExAllocatePool(NonPagedPool,
            prefixSize);
        if(readBuffer == NULL)
        {
            return FLT_POSTOP_FINISHED_PROCESSING;
        }

        status = FltReadFile(
            FltObjects->Instance,
            FltObjects->FileObject,
            &zero,
            (ULONG)prefixSize,
            readBuffer,
            FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
            &bytesRead,
            NULL,
            NULL);

        if(NT_SUCCESS(status))
        {
            if(IsBuffAPrefixOfBuffB(prefix, readBuffer, prefixSize, (SIZE_T)bytesRead))
            {
                *currOffset -= prefixSize;
                FltSetCallbackDataDirty(Data);
            }
        }
        ExFreePool(readBuffer);
    }

    return FLT_POSTOP_FINISHED_PROCESSING;
 }

IsFileNeedProccessing检查文件名和请求进程。(一些应用程序可能会看到标题)

如果有人能告诉我怎么做才能捕捉到notepad的操作,我会非常感激的。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-05 12:40:32

正如@Harry jonhston指出的那样,你只用MdlAddress == NULL拦截IRP的检查是不正确的。

代码语言:javascript
复制
if(Data->Iopb->Parameters.Read.MdlAddress != NULL)
{
    return FLT_POSTOP_FINISHED_PROCESSING;
}

很可能记事本和MS Office应用程序因此而失败。

再多几点:

你将不得不处理分页IO appropriately.

  • FltReadFile应该只被称为IRQL PASSIVE_LEVEL.

  • More,重要的是改变文件大小并保持它对文件系统和用户是透明的,这是相当复杂的。建议您不要这样做。使用alternate data stream.时,最好使用

  • 为文件添加特殊数据
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12735169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档