能力值:
( LV2,RANK:10 )
|
-
-
2 楼
但一些大型点的程序启动会有问题 首先,你应该去确认是出了什么问题,报了什么错。 可以跟踪一下应用程序。
知道了问题,再对应的去修改。 你现在感觉就是在猜。
|
能力值:
( LV3,RANK:20 )
|
-
-
3 楼
mark一个,同求
|
能力值:
( LV3,RANK:20 )
|
-
-
4 楼
我已经确定需要合并目录了,过滤IRP_MJ_DIRECTORY_CONTROL.IRP_MN_QUERY_DIRECTORY 目前做法是这样的:
过滤原有查询,当原有查询返回 STATUS_NO_MORE_FILES 时,打开定向目录,并将返回结果改为 STATUS_SUCCESS。据调试如果返回 STATUS_SUCCESS 上层应该是会继续查询的,当继续查询被我们捕获到后,我们再查询定向的目录,一个细节是原目录和定向目录中都有一个文件时,将原目录中文件隐藏。
如原目录 C:\test 下有 a.txt b.txt 定向目录 D:\ 下有 b.txt c.txt,当查询到 a.txt b.txt 时将 b.txt 擦除,继续查询 D:\ 得到 b.txt c.txt 则总的结果是 a.txt b.txt c.txt
整个合并过程在XP上工作观察是稳定的,但在 win7 上将返回值改为 STATUS_SUCCESS 后上层并没有继续查,原因不明。
核心代码如下:
static
FLT_PREOP_CALLBACK_STATUS
_SbPreDirectoryControl(
IN PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
IN PVOID* CompletionContext
)
{
FLT_PREOP_CALLBACK_STATUS FltStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
UNICODE_STRING Volume = {0};
do
{
PSB_FILEOBJ_DESC FileobjDesc = NULL;
if (IRP_MN_QUERY_DIRECTORY != Data->Iopb->MinorFunction)
{
break;
}
if (!SbIsSandboxProcess((ULONG)PsGetCurrentProcessId()))
{
break;
}
// 如果记录的有定向目录,则说明已经在合并中了,让后回调去完成查询
FileobjDesc = _SbGetFileobjDesc(Data->Iopb->TargetFileObject);
if (FileobjDesc && FileobjDesc->DirectoryHandle)
{
KdPrint(("found merge query, send to post callback\n"));
FltStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;
break;
}
if (!NT_SUCCESS(IoVolumeDeviceToDosName(Data->Iopb->TargetFileObject->DeviceObject, &Volume)) ||
Volume.Length < 4 ||
Volume.Buffer[1] != L':'
)
{
break;
}
// 沙箱中文件查询则 passthrough
if (SbIsSandboxVolume(Volume.Buffer[0]))
{
break;
}
// 否则就让它走 Post Callback (好合并目录和隐藏原目录中文件)
FltStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;
} while (FALSE);
if (Volume.Buffer)
{
ExFreePool((VOID*)Volume.Buffer);
}
return FltStatus;
}
static
NTSTATUS
_SbPrepareMergeDirectory(
IN OUT PFLT_CALLBACK_DATA Data,
IN WCHAR SbVolume,
IN PUNICODE_STRING OriginalDirectory
)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PSB_FILEOBJ_DESC FileobjDesc = NULL;
do
{
IO_STATUS_BLOCK IoStatus = {0};
OBJECT_ATTRIBUTES ObjAttrib = {0};
FileobjDesc = (PSB_FILEOBJ_DESC)ExAllocatePoolWithTag(NonPagedPool, sizeof(SB_FILEOBJ_DESC), SB_MEM_TAG);
if (!FileobjDesc)
{
break;
}
RtlZeroMemory(FileobjDesc, sizeof(SB_FILEOBJ_DESC));
FileobjDesc->FileObject = Data->Iopb->TargetFileObject;
RtlInitEmptyUnicodeString(&(FileobjDesc->OriginalPath), FileobjDesc->OriginalBuff, SB_MAX_NAME_LEN * sizeof(WCHAR));
RtlInitEmptyUnicodeString(&(FileobjDesc->RedirectPath), FileobjDesc->RedirectBuff, SB_MAX_NAME_LEN * sizeof(WCHAR));
RtlUnicodeStringCopy(&(FileobjDesc->OriginalPath), OriginalDirectory);
_SbGetRedirectPath(OriginalDirectory, SbVolume, &(FileobjDesc->RedirectPath));
InitializeObjectAttributes(&ObjAttrib, &(FileobjDesc->RedirectPath), OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
Status = ZwCreateFile(
&(FileobjDesc->DirectoryHandle),
GENERIC_READ,
&ObjAttrib,
&IoStatus,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE,
NULL,
0
);
} while (FALSE);
if (!NT_SUCCESS(Status))
{
if (FileobjDesc)
{
ExFreePoolWithTag((PVOID)FileobjDesc, SB_MEM_TAG);
}
}
else
{
_SbRecordFileObject(FileobjDesc);
}
return Status;
}
static
FLT_POSTOP_CALLBACK_STATUS
_SbPostDirectoryControl(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
IN PVOID CompletionContext,
IN FLT_POST_OPERATION_FLAGS Flags
)
{
FLT_POSTOP_CALLBACK_STATUS FltStatus = FLT_POSTOP_FINISHED_PROCESSING;
PFLT_FILE_NAME_INFORMATION NameInfo = NULL;
PVOID SafeBuffer = NULL;
do
{
PSB_FILEOBJ_DESC FileobjDesc = NULL;
BOOLEAN IsDirectory = FALSE;
WCHAR FirstSbVolume = SbFirstSandboxVolume();
if (!FirstSbVolume)
{
break;
}
if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass != FileBothDirectoryInformation &&
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass != FileIdBothDirectoryInformation
)
{
break;
}
if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName &&
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName->Length
)
{
USHORT Index = 0;
BOOLEAN ContainsAsterisk = FALSE;
for (Index = 0; Index < Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName->Length / 2; ++Index)
{
if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName->Buffer[Index] == L'*')
{
ContainsAsterisk = TRUE;
break;
}
}
// 没有 * 说明找的非常精确,如就找 C:\ 下的 a.txt ,精确查找时,直接放过
if (!ContainsAsterisk)
{
break;
}
}
// 如果有映射目录句柄,则说明已经在合并目录,则直接查询定向目录即可
FileobjDesc = _SbGetFileobjDesc(Data->Iopb->TargetFileObject);
if (FileobjDesc && FileobjDesc->DirectoryHandle)
{
KdPrint(("query redirect path\n"));
Data->IoStatus.Status = ZwQueryDirectoryFile(
FileobjDesc->DirectoryHandle,
NULL,
NULL,
NULL,
&Data->IoStatus,
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer,
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length,
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass,
FALSE,
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileName,
FALSE
);
break;
}
if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress != NULL)
{
SafeBuffer = MmGetSystemAddressForMdlSafe(
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.MdlAddress,
NormalPagePriority
);
}
else
{
SafeBuffer = Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;
}
if (!SafeBuffer)
{
break;
}
if (!NT_SUCCESS(FltGetFileNameInformation(
Data,
FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_DEFAULT,
&NameInfo
)))
{
break;
}
KdPrint(("_SbPostDirectoryControl %wZ\n", &NameInfo->Name));
if (STATUS_NO_MORE_FILES == Data->IoStatus.Status)
{
// 原查询结束了,准备开始定向目录的合并工作
KdPrint(("Original Query finished\n"));
if (NT_SUCCESS(_SbPrepareMergeDirectory(Data, FirstSbVolume, &NameInfo->Name)))
{
// 将状态置为 STATUS_SUCCESS 则系统会继续往下查
Data->IoStatus.Status = STATUS_SUCCESS;
// 如果设置为成功,则本次的缓冲区仍会被上层使用,会导致查询结果叠加,应设置本次返回长度为0
// Data->IoStatus.Information = 0;
// 经调试设置 Data->IoStatus.Information = 0; 还不行,将文件查询相关结构清零似乎可以
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length = 0;
if (FileBothDirectoryInformation == Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass)
{
RtlZeroMemory(SafeBuffer, sizeof(FILE_BOTH_DIR_INFORMATION));
}
else
{
RtlZeroMemory(SafeBuffer, sizeof(FILE_ID_BOTH_DIR_INFORMATION));
}
}
break;
}
else if (!NT_SUCCESS(Data->IoStatus.Status))
{
break;
}
// 从原来的查询结果中隐藏沙箱中已经有的部分
if (Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass == FileBothDirectoryInformation)
{
_SbProcessFileBothDirectoryInformation(
FirstSbVolume,
&NameInfo->Name,
(PFILE_BOTH_DIR_INFORMATION)SafeBuffer,
Data
);
}
else
{
_SbProcessFileIdBothDirectoryInformation(
FirstSbVolume,
&NameInfo->Name,
(PFILE_ID_BOTH_DIR_INFORMATION)SafeBuffer,
Data
);
}
} while (FALSE);
if (NameInfo)
{
FltReleaseFileNameInformation(NameInfo);
}
return FltStatus;
}
|
能力值:
( LV3,RANK:20 )
|
-
-
5 楼
找到办法了
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
什么办法,能不能说一下,我也在做类似的问题,一直不能实现很好的合并。如果能给我一份代码就更好了。将万分感谢
|