如何在IRP中获取操作的文件路径?
文件路径
在minifilter中,主要处理的是各种IRP,做DLP也好,做加解密也好。文件路径总是绕不开的。比如在IRP_MJ_WRITE中,绝大多数情况都得知道当前这次操作的文件路径。
普通办法
Minifilter框架有个函数:FltGetFileNameInformation
这个函数可以用来获取文件路径,比如下面是段常用的获取文件路径的代码
UNICODE_STRING ExtractFileName(_In_ PFLT_CALLBACK_DATA Data)
{
NTSTATUS status;
UNICODE_STRING ret = { 0 };
KIRQL irql = KeGetCurrentIrql();
if (irql > APC_LEVEL) {
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("OOOOOOOOOOOOOOPS, IRQL > APC_LEVEL, Can't call FltGetFileNameInformation. current irql: %d\n", irql));
return ret;
}
if (Data)
{
PFLT_FILE_NAME_INFORMATION pNameInfo = NULL;
status = FltGetFileNameInformation(Data,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_DEFAULT,
&pNameInfo); // <= APC_LEVEL
if (NT_SUCCESS(status) && pNameInfo)
{
status = FltParseFileNameInformation(pNameInfo);
if (NT_SUCCESS(status)) // <= APC_LEVEL
{
Init(&ret, pNameInfo->Name.MaximumLength);
CopyUnicodeString(&ret, &(pNameInfo->Name));
}
else {
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("Calling FltParseFileNameInformation() failed, err: %d\n", status));
}
FltReleaseFileNameInformation(pNameInfo); // <= APC_LEVEL
}
}
return ret;
}
ok,那么这么就完了吗?对于普通WRITE请求,确实可以。比如WriteFile触发的IRP.
但是如何是FileMapping,你就会发现FltGetFileNameInformation会失败。
查一下msdn就会发现:
其中有一条,FileGetNameInformation cannot get file name information in the paging I/O path.
好,FileMapping就是paging IO, 所以失败。
如何获取FileMapping操作在IRP_MJ_WRITE等IRP中的文件路径呢?
既然直接获取不到,那么就曲线救国呗。
一般FileMapping的写法如下:
void TestIOFileMapping() {
HANDLE hFile;
hFile = CreateFile(L"testfilemapping.foo",
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return;
}
HANDLE hMapping = CreateFileMapping(hFile,
NULL,
PAGE_READWRITE,
0,
MAX_FILESIZE,
NULL);
if (hMapping == NULL)
{
CloseHandle(hFile);
return;
}
char* puchData = (char*)MapViewOfFile(hMapping,
FILE_MAP_WRITE,
0,
0,
0);
if (puchData == NULL)
{
CloseHandle(hMapping);
CloseHandle(hFile);
return;
}
for (int i = 0; i < 10; i++)
{
OutputDebugStringW(L"Try to write data with memset()");
memset(puchData + i * 1024, 0x41 + i, 1024);
}
UnmapViewOfFile(puchData);
// FlushFileBuffers(hFile);
CloseHandle(hMapping);
CloseHandle(hFile);
}