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) とメモ帳を除いて、うまく機能します。読み取りおよび書き込み操作の一部をキャッチしていないようで、メモ帳にはファイルだけでなくヘッダーも表示されます。

私はhttp://www.osronline.com/でたくさん読んだことがありますが、そこに尋ねる人は誰でも、Nagar の本を読むか、アーカイブを見るように言われます (検索するのは大変です)。私の問題に関連するすべてを読んだと思います。

メモ帳はメモリ マップ ファイル、Fast IO、Pagged IO を使用しているようです。mHook を使用してフックしようとしましたが、メモ帳でファイルを開いてマップされたデータを見つけようとしたときに、運がありませんでした (ただし、メモリにマップされた他のすべてのバイトが見つかりましNtMapViewOfSectionた) MapViewOfFileMapViewOfFileEx

次に、達成しようとしていることはフックでは不可能であり、ミニフィルタードライバーでのみ可能であり、設定するフラグがいくつか不足していると考えたことを読みました。

メモ帳の操作をキャッチするために何をすべきかを誰かが教えてくれたら、本当に感謝します。

読み取りのコード例を次に示します。

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ファイル名と要求プロセスをチェックします。(一部のアプリではヘッダーが表示されます)

メモ帳の操作をキャッチするために何をすべきかを誰かが教えてくれたら、本当に感謝します。

ありがとう。

4

1 に答える 1

2

@Harry johston が指摘したように、IRP をインターセプトするだけのチェックMdlAddress == NULLは正しくありません。

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

ほとんどの場合、これが原因でメモ帳と MS Office アプリケーションが失敗します。

さらにいくつかのポイント:

  • ページング IO を適切に処理する必要があります。
  • FltReadFileIRQL のみを呼び出す必要がありますPASSIVE_LEVEL
  • さらに重要なことは、ファイル サイズを変更し、Windows ファイル システムとユーザーに対して透明性を維持することは非常に複雑なことです。そうしないことをお勧めします。
  • ファイルに特別なデータを追加するには、代替データ ストリームを使用する方がよい場合があります。
于 2012-10-05T04:40:31.653 に答える