在PreCreate函数中来完成
FLT_PREOP_CALLBACK_STATUS
FileCreatePreOperation(
_Inout_ PFLT_CALLBACK_DATA Cbd,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
NTSTATUS status;
FLT_PREOP_CALLBACK_STATUS callbackStatus;
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
PAGED_CODE();
status = STATUS_SUCCESS;
callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
NT_ASSERT(Cbd->Iopb->MajorFunction == IRP_MJ_CREATE);
if (FlagOn(Cbd->Iopb->OperationFlags, SL_OPEN_PAGING_FILE)) {
return callbackStatus;
}
//打开卷的操作 不重定位
if (FlagOn(Cbd->Iopb->TargetFileObject->Flags, FO_VOLUME_OPEN)) {
return callbackStatus;
}
//按ID打开的不重定位,因为不知道这种打开方式的意图
if (FlagOn(Cbd->Iopb->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID)) {
return callbackStatus;
}
if (FlagOn(Cbd->Iopb->OperationFlags, SL_OPEN_TARGET_DIRECTORY)) {
return callbackStatus;
}
do
{
status = FltGetFileNameInformation(Cbd,
FLT_FILE_NAME_OPENED |
FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo);
if (!NT_SUCCESS(status))
{
break;
}
status = FltParseFileNameInformation(nameInfo);
if (!NT_SUCCESS(status)) {
FltReleaseFileNameInformation(nameInfo);
break;
}
WCHAR Path[260] = { 0 };
memcpy_s(Path,260, nameInfo->Name.Buffer, nameInfo->Name.Length);
if (wcsstr(Path,L"1.txt")==0)
{
break;
}
//lnk不屏蔽掉 会出问题
if (wcsstr(Path, L"1.txt.lnk"))
{
DbgPrint("打开文件快捷方式%S\n", Path);
break;
}
DbgPrint("打开文件%S\n", Path);
PWCHAR Name = L"\\Device\\HarddiskVolume1\\2.txt";
status = IoReplaceFileObjectName(Cbd->Iopb->TargetFileObject, Name,wcslen(Name)*2);
if (!NT_SUCCESS(status))
{
break;
}
status = STATUS_REPARSE;
} while (FALSE);
if (nameInfo != NULL) {
FltReleaseFileNameInformation(nameInfo);
}
if (status == STATUS_REPARSE) {
//
// Reparse the open
//
Cbd->IoStatus.Status = STATUS_REPARSE;
Cbd->IoStatus.Information = IO_REPARSE;
callbackStatus = FLT_PREOP_COMPLETE;
FltSetCallbackDataDirty(Cbd);
}
return callbackStatus;
}
IoReplaceFileObjectName逆向分析
NTSTATUS IoReplaceFileObjectName(PFILE_OBJECT FileObject, const void *RedirectPath, USHORT Length)
{
USHORT FileObjectLength; // bx
PVOID Buffer; // rbp
FileObjectLength = FileObject->FileName.MaximumLength;
//如果重定向的路径长度小于文件对象路径的长度 直接用原来的buffer 完成拷贝
if (Length <= FileObjectLength)
{
LABEL_2:
//设置长度
FileObject->FileName.Length = Length;
//完成拷贝
memset(FileObject->FileName.Buffer, 0, FileObjectLength);
memmove(FileObject->FileName.Buffer, RedirectPath, Length);
return 0;
}
//这里文件对象路径的长度使用了几个特别的值
FileObjectLength = 0x38; //56
if (Length >= 0x38)
{
FileObjectLength = 0x78; //120
if (Length >= 0x78)
{
FileObjectLength = 0xF8;
if (Length >= 0xF8) //248
{
FileObjectLength = Length;
}
}
}
Buffer = ExAllocatePoolWithTag(PagedPool, FileObjectLength, 0x6D4E6F49);
if (Buffer)
{
if (FileObject->FileName.Buffer)
{
ExFreePoolWithTag(FileObject->FileName.Buffer, 0);
}
FileObject->FileName.Buffer = Buffer;
FileObject->FileName.MaximumLength = FileObjectLength;
goto LABEL_2;
}
return STATUS_INSUFFICIENT_RESOURCES;
}