刺激战场
六合彩
贵宾厅
  • 2381阅读
  • 2回复

Scanner(用户文件过滤驱动 Minifilter) [复制链接]

上一主题 下一主题
离线天道酬勤
 

只看楼主 倒序阅读 使用道具 楼主  发表于: 2016-02-15



/*++


--*/

#include <fltKernel.h>#include <dontuse.h>
#include <suppress.h>

/////////////////////////////////////////////////////////////////////////////////////////////这是和用户层共用的.

#define SCANNER_READ_BUFFER_SIZE   1024 //相信目录的长度不会超过这个数.

typedef struct _SCANNER_NOTIFICATION {
    ULONG BytesToScan;    ULONG Reserved;             // for quad-word alignement of the Contents structure
    UCHAR Contents[SCANNER_READ_BUFFER_SIZE];    } SCANNER_NOTIFICATION, *PSCANNER_NOTIFICATION;

typedef struct _SCANNER_REPLY {
    BOOLEAN SafeToOpen;    } SCANNER_REPLY, *PSCANNER_REPLY;
///////////////////////////////////////////////////////////////////////////////////////////

#define TAG 'tset' //本驱动在内存中的标志:test

PFLT_FILTER gFilterHandle;PFLT_PORT g_ServerPort;
PFLT_PORT g_ClientPort;

FLT_POSTOP_CALLBACK_STATUS CreatePostOperation (__inout PFLT_CALLBACK_DATA Data,__in PCFLT_RELATED_OBJECTS FltObjects,                                                __in_opt PVOID CompletionContext,__in FLT_POST_OPERATION_FLAGS Flags)
{    PFLT_FILE_NAME_INFORMATION    pfni;
    NTSTATUS                      status;

    UNREFERENCED_PARAMETER( CompletionContext );    UNREFERENCED_PARAMETER( Flags );
        if ( !NT_SUCCESS( Data->IoStatus.Status ) || ( STATUS_REPARSE == Data->IoStatus.Status ) ) // If we have an error then just exit
    {        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    status = FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &pfni);        if (!NT_SUCCESS( status )) // If we could not get the name information then exit
    {        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    FltParseFileNameInformation(pfni);

    if ( Data->IoStatus.Information == FILE_CREATED ) //如果是新建操作。    {
        BOOLEAN  IsDirectory = FALSE ;        status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDirectory);
        if (NT_SUCCESS(status) && IsDirectory) //如果是目录.        {  
            PSCANNER_NOTIFICATION notification = NULL;            ULONG replyLength = 0;
                        notification = ExAllocatePoolWithTag( NonPagedPool, sizeof( SCANNER_NOTIFICATION ), TAG);
            if (notification == NULL) {                DbgPrint("ExAllocatePoolWithTag fail with status 0x%X\n", status);
                //退出处理.            }

            notification->BytesToScan = min(pfni->Name.Length, SCANNER_READ_BUFFER_SIZE );                        
            try  {//  The buffer can be a raw user buffer. Protect access to it                RtlCopyMemory(&notification->Contents, pfni->Name.Buffer, notification->BytesToScan);
            } except( EXCEPTION_EXECUTE_HANDLER ) {//出错处理. GetExceptionCode() ;                                DbgPrint("RtlCopyMemory Exception!\n");
            }

            //  Send message to user mode.            //  We don't have to synchronize between the send and close of the handle as FltSendMessage takes care of that.
            replyLength = sizeof(SCANNER_REPLY);            status = FltSendMessage(gFilterHandle, &g_ClientPort, notification, sizeof(SCANNER_NOTIFICATION), notification, &replyLength, NULL);
            if (STATUS_SUCCESS != status) {//Couldn't send message. This sample will let the i/o through.                DbgPrint("couldn't send message to user-mode, status 0x%X\n", status);
            }

            ExFreePoolWithTag( notification, TAG);        }
    }

    FltReleaseFileNameInformation(pfni);              
    return FLT_POSTOP_FINISHED_PROCESSING;}

CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
    { IRP_MJ_CREATE, 0, 0, CreatePostOperation},    { IRP_MJ_OPERATION_END }
};

VOID DisconnectNotifyCallback (_In_opt_ PVOID ConnectionCookie){
    PAGED_CODE();    UNREFERENCED_PARAMETER(ConnectionCookie);
    FltCloseClientPort(gFilterHandle, &g_ClientPort);//应该加判断,如果ConnectionCookie == 我们的值就执行这行.}

NTSTATUS ConnectNotifyCallback (IN PFLT_PORT ClientPort, IN PVOID ServerPortCookie, IN PVOID ConnectionContext, IN ULONG SizeOfContext, OUT PVOID * ConnectionPortCookie)
{    PAGED_CODE();
    UNREFERENCED_PARAMETER( ServerPortCookie );    UNREFERENCED_PARAMETER( ConnectionContext );
    UNREFERENCED_PARAMETER( SizeOfContext);    UNREFERENCED_PARAMETER( ConnectionPortCookie);

    g_ClientPort = ClientPort;//保存以供以后使用.

    return STATUS_SUCCESS;
}

#pragma PAGEDCODENTSTATUS PtInstanceQueryTeardown (__in PCFLT_RELATED_OBJECTS FltObjects,__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( Flags );    return STATUS_SUCCESS;
}

#pragma PAGEDCODE//#pragma alloc_text(PAGE, PtUnload)NTSTATUS PtUnload (__in FLT_FILTER_UNLOAD_FLAGS Flags)
{    UNREFERENCED_PARAMETER( Flags );
    FltCloseCommunicationPort(g_ServerPort);//没有这一行是停止不了驱动的,查询也是永远等待中.    FltUnregisterFilter( gFilterHandle );
    return STATUS_SUCCESS;}

CONST FLT_REGISTRATION FilterRegistration = {
    sizeof( FLT_REGISTRATION ),         //  Size    FLT_REGISTRATION_VERSION,           //  Version
    0,                                  //  Flags    NULL,                               //  Context
    Callbacks,                          //  Operation callbacks    PtUnload,                           //  MiniFilterUnload
    NULL,                               //  InstanceSetup    PtInstanceQueryTeardown,            //  InstanceQueryTeardown
    NULL,                               //  InstanceTeardownStart    NULL,                               //  InstanceTeardownComplete
    NULL,                               //  GenerateFileName    NULL,                               //  GenerateDestinationFileName
    NULL                                //  NormalizeNameComponent};

DRIVER_INITIALIZE DriverEntry;
#pragma alloc_text(INIT, DriverEntry)//#pragma INITCODENTSTATUS DriverEntry (_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{    NTSTATUS status = 0;
    PSECURITY_DESCRIPTOR sd;    OBJECT_ATTRIBUTES oa;
    UNICODE_STRING uniString;

    UNREFERENCED_PARAMETER(RegistryPath);

    KdBreakPoint();

    __try    {
        status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle);         if (!NT_SUCCESS(status)) //;
        {                   __leave;
        }

        status  = FltBuildDefaultSecurityDescriptor(&sd, FLT_PORT_ALL_ACCESS);        if (!NT_SUCCESS( status )) {
            __leave;        }

        RtlInitUnicodeString(&uniString, L"\\CommunicationPort");
        InitializeObjectAttributes( &oa, &uniString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, sd);        status = FltCreateCommunicationPort(gFilterHandle, &g_ServerPort, &oa, NULL, ConnectNotifyCallback, DisconnectNotifyCallback, 0, 1);
        FltFreeSecurityDescriptor( sd );        if (!NT_SUCCESS( status )) {
            __leave;        }

        status = FltStartFiltering(gFilterHandle);//这个结果在下面判断.
    } __finally {        if (!NT_SUCCESS( status ) )
        {            if (NULL != g_ServerPort) {
                FltCloseCommunicationPort(g_ServerPort);            }

            if (NULL != gFilterHandle) {
                FltUnregisterFilter(gFilterHandle);            }
        }           }

    return status;
}
用户层=============================
/*++

--*/

#include <windows.h>#include <stdlib.h>
#include <stdio.h>#include <winioctl.h>
#include <string.h>#include <crtdbg.h>
#include <assert.h>#include <fltuser.h>
#include <dontuse.h>#include <locale.h>

///////////////////////////////////////////////////////////////////////////////////////////
//这是和内核共用的.

#define SCANNER_READ_BUFFER_SIZE   1024

typedef struct _SCANNER_NOTIFICATION {    ULONG BytesToScan;
    ULONG Reserved;             // for quad-word alignement of the Contents structure    WCHAR Contents[SCANNER_READ_BUFFER_SIZE];    
} SCANNER_NOTIFICATION, *PSCANNER_NOTIFICATION;

typedef struct _SCANNER_REPLY {    BOOLEAN SafeToOpen;    
} SCANNER_REPLY, *PSCANNER_REPLY;///////////////////////////////////////////////////////////////////////////////////////////

#pragma pack(1)

typedef struct _SCANNER_MESSAGE {
    FILTER_MESSAGE_HEADER MessageHeader;//必须定义的.  Required structure header.    SCANNER_NOTIFICATION Notification;//  Private scanner-specific fields begin here.
    OVERLAPPED Ovlp;//  Overlapped structure: this is not really part of the message, However we embed it instead of using a separately

allocated overlap structure    } SCANNER_MESSAGE, *PSCANNER_MESSAGE;

typedef struct _SCANNER_REPLY_MESSAGE {
    FILTER_REPLY_HEADER ReplyHeader;//必须定义的.  Required structure header.    SCANNER_REPLY Reply;//  Private scanner-specific fields begin here.
} SCANNER_REPLY_MESSAGE, *PSCANNER_REPLY_MESSAGE;

typedef struct _SCANNER_THREAD_CONTEXT {//  Context passed to worker threads    HANDLE Port;
    HANDLE Completion;} SCANNER_THREAD_CONTEXT, *PSCANNER_THREAD_CONTEXT;



DWORD WorkerThread(_In_ PSCANNER_THREAD_CONTEXT Context)/*++
Routine Description    This is a worker thread that
Arguments    Context  - This thread context has a pointer to the port handle we use to send/receive messages,
               and a completion port handle that was already associated with the comm. port by the callerReturn Value
    HRESULT indicating the status of thread exit.--*/
{        PSCANNER_MESSAGE message = 0;    
    HRESULT hr;//返回值.    

#pragma warning(push)#pragma warning(disable:4127) // conditional expression is constant
    while (TRUE)     {
#pragma warning(pop)        
        LPOVERLAPPED pOvlp = 0;        DWORD outSize = 0;
        ULONG_PTR key = 0;        BOOL result = GetQueuedCompletionStatus(Context->Completion, &outSize, &key, &pOvlp, INFINITE);//等待信息.Poll for messages from

the filter component to scan.
        if (!result) {//  An error occured.            hr = HRESULT_FROM_WIN32( GetLastError() );
            break;        }
        //printf( "收到%d个字节的消息\n", pOvlp->InternalHigh );

        //  Obtain the message: note that the message we sent down via FltGetMessage() may NOT be the one dequeued off the completion

queue: this is solely because there are multiple        //  threads per single port handle. Any of the FilterGetMessage() issued messages can be completed in random order - and we will

just dequeue a random one.
        message = CONTAINING_RECORD(pOvlp, SCANNER_MESSAGE, Ovlp);//此时已经有内容.根据pOvlp取得message的值,依据是这两个变量的类型在结构中

的关系.        PSCANNER_NOTIFICATION notification = &message->Notification;//此时已经有内容.
        assert(notification->BytesToScan <= SCANNER_READ_BUFFER_SIZE);        _Analysis_assume_(notification->BytesToScan <= SCANNER_READ_BUFFER_SIZE);
        notification->Contents[(notification->BytesToScan) / sizeof(wchar_t)] = 0;//不显示垃圾数据.        wprintf(L"新建的目录是:%s\n", notification->Contents);

        SCANNER_REPLY_MESSAGE replyMessage;
        replyMessage.ReplyHeader.Status = 0;        replyMessage.ReplyHeader.MessageId = message->MessageHeader.MessageId;        
        replyMessage.Reply.SafeToOpen = !result;//Need to invert the boolean -- result is true if found foul language,in which case

SafeToOpen should be set to false.        //printf( "Replying message, SafeToOpen: %d\n", replyMessage.Reply.SafeToOpen );
        hr = FilterReplyMessage(Context->Port, (PFILTER_REPLY_HEADER) &replyMessage, sizeof(replyMessage));//获取驱动的答复信息.此函数调用

不能去掉.        if (SUCCEEDED( hr )) {
            //printf( "回复消息!\n" );        } else {
            printf( "Error replying message. Error = 0x%X\n", hr );            break;
        }

        memset (&message->Ovlp, 0, sizeof(OVERLAPPED));        hr = FilterGetMessage(Context->Port, &message->MessageHeader, FIELD_OFFSET(SCANNER_MESSAGE, Ovlp), &message->Ovlp);//获取信息.此函

数调用不能去掉.
        if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING )) {            break;
        }

        //此时:message->Notification.Contents里面的就是内容.        //wprintf(L"新建的目录是:%s\n", message->Notification.Contents);
    }

    if (!SUCCEEDED( hr )) {        if (hr == HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE )) {//port disconncted.
            printf( "Scanner: Port is disconnected, probably due to scanner filter unloading.\n" );        } else {
            printf( "Scanner: Unknown error occured. Error = 0x%X\n", hr );        }
    }

    free( message );    return hr;
}

int _cdecl main ()//_In_ int argc, _In_reads_(argc) char *argv[]{
    //DebugBreak();    MessageBox(0,L"请附加调试器",L"调试断点",0);

    setlocale(LC_CTYPE, ".936");

    printf( "Connecting to the filter ...\n" );
    HANDLE port;    HRESULT hr = FilterConnectCommunicationPort(L"\\CommunicationPort", 0, NULL, 0, NULL, &port);//Open a commuication channel to the

filter
    if (IS_ERROR( hr )) {        printf( "ERROR: Connecting to filter port: 0x%08x\n", hr );
        return 2;    }
    HANDLE completion = CreateIoCompletionPort(port, NULL, 0, 1);//Create a completion port to associate with this handle.    if (completion == NULL) {
        printf( "ERROR: Creating completion port: %d\n", GetLastError() );        CloseHandle( port );
        return 3;    }
    printf( "Port = 0x%p Completion = 0x%p\n", port, completion );

    SCANNER_THREAD_CONTEXT context;    context.Port = port;
    context.Completion = completion;    HANDLE threads[3];//线程句柄的数组.
    DWORD threadId;    threads[0] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) WorkerThread, &context, 0, &threadId);
    if (threads[0] == NULL) {//  Couldn't create thread.        hr = GetLastError();
        printf( "ERROR: Couldn't create thread: %d\n", hr );        goto main_cleanup;
    }

#pragma prefast(suppress:__WARNING_MEMORY_LEAK, "msg will not be leaked because it is freed in WorkerThread")    PSCANNER_MESSAGE msg = (PSCANNER_MESSAGE)malloc( sizeof( SCANNER_MESSAGE ) );//  Allocate the message.
    if (msg == NULL) {        hr = ERROR_NOT_ENOUGH_MEMORY;
        goto main_cleanup;    }
    memset( &msg->Ovlp, 0, sizeof(OVERLAPPED) );    hr = FilterGetMessage(port, &msg->MessageHeader, FIELD_OFFSET(SCANNER_MESSAGE, Ovlp), &msg->Ovlp);//此函数调用不能去掉.Request messages

from the filter driver.
    if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING )) {//此时整个msg的值都会变.        free( msg );
        goto main_cleanup;    }

    hr = S_OK;
    WaitForMultipleObjectsEx(1, threads, TRUE, INFINITE, FALSE );

main_cleanup:    printf( "All done. Result = 0x%08x\n", hr );
    CloseHandle(port);    CloseHandle(completion);
    return hr;}


离线im86165507

只看该作者 沙发  发表于: 2016-02-15
离线v2680267313

只看该作者 板凳  发表于: 2016-04-30
用户被禁言,该主题自动屏蔽!
快速回复
限100 字节
批量上传需要先选择文件,再选择上传
 
上一个 下一个