我将从最终目标开始。
我希望系统上的每个文档(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)和记事本上除外。 我似乎无法捕获某些读取和写入操作,并且记事本显示标题以及文件。
我在http://www.osronline.com/上阅读了很多,每个人都被告知要阅读一些Nagar书籍或查看他们的档案(这些档案很难搜索)。我认为我已经阅读了与我的问题相关的所有内容。
看起来记事本使用内存映射文件、快速IO、分页IO和其他诸如此类的技术。我已经尝试使用mHook钩取
然后我读到,我正在尝试实现的目标无法通过钩子实现,只能通过minifilter驱动程序实现,而且我发现我缺少一些需要设置的标志。
如果有人能告诉我如何捕获记事本操作,我将非常感激。
以下是一些读取的代码示例:
为了实现这一点,我编写了一个迷你过滤器驱动程序,执行以下操作:
IRP_MJ_WRITE - 如果存在头部,则更改偏移量以使其位于文件开头。
IRP_MJ_READ - 如果存在头部,则更改偏移量以使其位于文件开头。
IRP_MJ_QUERY_INFORMATION - 如果存在头部,则更改返回的文件大小。
IRP_MJ_DIRECTORY_CONTROL - 如果存在头部,则更改返回的文件大小。
IRP_MJ_CREATE - 如果不存在头部,则在文件前面添加头部。
这很有效,但是在MS Word 2003文档(doc,xls,ppt)和记事本上除外。 我似乎无法捕获某些读取和写入操作,并且记事本显示标题以及文件。
我在http://www.osronline.com/上阅读了很多,每个人都被告知要阅读一些Nagar书籍或查看他们的档案(这些档案很难搜索)。我认为我已经阅读了与我的问题相关的所有内容。
看起来记事本使用内存映射文件、快速IO、分页IO和其他诸如此类的技术。我已经尝试使用mHook钩取
NtMapViewOfSection
、MapViewOfFile
和MapViewOfFileEx
,但是当我打开记事本中的某个文件并尝试查找映射的数据时,我没有成功(但我找到了映射到内存的每个其他字节)。然后我读到,我正在尝试实现的目标无法通过钩子实现,只能通过minifilter驱动程序实现,而且我发现我缺少一些需要设置的标志。
如果有人能告诉我如何捕获记事本操作,我将非常感激。
以下是一些读取的代码示例:
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
检查文件名和请求进程。(一些应用程序可以看到标头)
如果有人能告诉我如何捕获记事本的操作,我将非常感激。
谢谢。
Parameters.Read.MdlAddress != NULL
的调用呢?这似乎是错误的。 - Harry Johnston