需要帮助从 Minifilter 中的用户模式应用程序获得回复

问题描述

我在从 kernel to user-mode. 通信时遇到问题 我的要求是在 postCreate 中将进程路径发送到用户模式并从用户模式应用程序获得回复。 处理路径并返回布尔值的用户模式进程。

系统在步骤 GetQueuedCompletionStatus() 挂起并重新启动。我不知道为什么,也想不通。

我也尝试过 scanner 示例,但在该示例中 GetQueuedCompletionStatus() 阻止执行并且不返回任何内容

我完全迷失了,无法弄清楚系统挂起并重新启动的原因。

我已经使用 FltSendMessage 将路径发送到用户模式并超时。

请帮我让它工作。我会非常感谢你。

结构信息:

typedef struct _MINISPY_NOTIFICATION {
    
        BOOLEAN flag; 
        ULONG Reserved;             // for quad-word alignement of the Contents structure
        UCHAR Processpath[MINISPY_PROCESS_PATH_SIZE]; //Todo: 260?
        UCHAR filePath[MINISPY_PROCESS_PATH_SIZE]; //Drive FilePath 
    
    } MINISPY_NOTIFICATION,* PMINISPY_NOTIFICATION;
    


 typedef struct _MINISPY_REPLY {
        
            BOOLEAN res;     // if res is true then BLOCK otherwise ALLOW
        
        } MINISPY_REPLY,* PMINISPY_REPLY;

typedef struct _MINISPY_THREAD_CONTEXT {
    
        HANDLE Port;
        HANDLE Completion;
    
    } MINISPY_THREAD_CONTEXT,* PMINISPY_THREAD_CONTEXT;

typedef struct _MINISPY_MESSAGE {

    FILTER_MESSAGE_HEADER MessageHeader;

    MINISPY_NOTIFICATION Notification;

    OVERLAPPED Ovlp;

} MINISPY_MESSAGE,* PMINISPY_MESSAGE;

typedef struct _MINISPY_REPLY_MESSAGE {

    FILTER_REPLY_HEADER ReplyHeader;

    MINISPY_REPLY Reply;

} MINISPY_REPLY_MESSAGE,*PMINISPY_REPLY_MESSAGE;

用户模式代码

DWORD
RetrieveMsgAndReplyToKernel(
    _In_ LPVOID lpParameter
) {
   
    PMINISPY_THREAD_CONTEXT context = (PMINISPY_THREAD_CONTEXT)lpParameter;

    MINISPY_REPLY_MESSAGE response;

    MINISPY_MESSAGE notificatioBuffer;
    PMINISPY_MESSAGE notification;

    RtlZeroMemory(&notificatioBuffer.Ovlp,sizeof(OVERLAPPED));
    notification = &notificatioBuffer;

    HRESULT hr;
    BOOL resultBool;

    while (TRUE) {
        NTSTATUS status;
        BOOL success;
        DWORD outSize;
        ULONG_PTR key;
        LPOVERLAPPED overlapped;
        UCHAR responseFlags;
       
        UINT errorCode;

        printf("\nWaiting to get msg from kernel...");
        hr = FilterGetMessage(
            context->Port,&notification->MessageHeader,FIELD_OFFSET(MINISPY_MESSAGE,Ovlp),&notification->Ovlp);

        if (hr != HRESULT_FROM_WIN32(ERROR_IO_PENDING))
            break;

        printf("\nWaiting to get GetQueuedCompletionStatus success...\n");
        printf("\nInThreadFunc,Minispy: Port = 0x%p Completion = 0x%p\n",context->Port,context->Completion);



       //Todo: SYstem HANGS here AND RESTARTED!



        success = GetQueuedCompletionStatus(
            context->Completion,&outSize,&key,&overlapped,INFINITE);

        if (!success)
            break;

        // Obtain the notification. Note that this notification may not be
        // the same as message buffer,since there are multiple threads.

     
        printf("GetQueuedCompletionStatus Success!");

        notification = CONTAINING_RECORD(overlapped,MINISPY_MESSAGE,Ovlp);

        //Todo: process processpath


        //printf("\nReceived messageId: %llu\n",notification->MessageHeader.MessageId);
        //Todo: process processpath and fileName and update the result
        //resultBool = strstr(notification->Notification.Processpath,"firefox") != NULL ? TRUE : FALSE;
       

        response.ReplyHeader.Status = 0;
        response.ReplyHeader.MessageId = notification->MessageHeader.MessageId;
        response.Reply.res = resultBool;
        printf("\nReplying message,Res bool: %d\n",response.Reply.res);

        hr = FilterReplyMessage(context->Port,&response.ReplyHeader,sizeof(notification->MessageHeader.ReplyLength));

        if (SUCCEEDED(hr)) {
            printf("\nsuccessfully Replied message!\n");
        }
        else {
            printf("\nMINISPY: Error replying message. Error = 0x%X\n",hr);
        }
    }

    if (!SUCCEEDED(hr)) {

        if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE)) {

            //
            //  MINISPY port disconncted.
            //

            printf("\nMINISPY: Port is disconnected,probably due to MINISPY filter unloading.\n");

        }
        else {

            printf("\nMINISPY: UnkNown error occured. Error = 0x%X\n",hr);
        }
    }

    return hr;
}




    int _cdecl
    main (
        _In_ int argc,_In_reads_(argc) char *argv[]
        )
   
    {
        HANDLE port = INVALID_HANDLE_VALUE;
        HRESULT hResult = S_OK;
        DWORD result;
        ULONG threadId2;
        HANDLE thread2 = NULL;
        MINISPY_THREAD_CONTEXT context2; //to reply to kernel
        UINT threadCount = 1; // number of thread to reply to kernel
        CHAR inputChar;
        HANDLE completion = INVALID_HANDLE_VALUE;
    
        printf( "Connecting to filter's port...\n" );
    
        hResult = FilterConnectCommunicationPort( MINISPY_PORT_NAME,// fully name of port to connect
                                                  0,NULL,&port // receives a handle for the newly created connection port if the call to FilterConnectCommunicationPort succeeds
                                                );
    
        if (IS_ERROR( hResult )) {
    
            printf( "Could not connect to filter: 0x%08x\n",hResult );
            displayError( hResult );
            goto Main_Exit;
        }
    
        completion = CreateIoCompletionPort(port,threadCount);
    
        if (completion == NULL) {
    
            printf("ERROR: Creating completion port: %d\n",GetLastError());
            CloseHandle(port);
            return 3;
        }
    
        printf("Minispy: Port = 0x%p Completion = 0x%p\n",port,completion);
    
        context2.Port = port;
        context2.Completion = completion;
    
        //
       // Create the thread to read msg from kernel and reply bool to kernel
       // by MiniSpy.sys.
       //
        thread2 = CreateThread(NULL,RetrieveMsgAndReplyToKernel,(LPVOID)&context2,&threadId2);
    
        if (!thread2) {
    
            result = GetLastError();
            printf("Could not create MsgReplying thread: %d\n",result);
            displayError(result);
            goto Main_Exit;
        }
         
         //Waiting here for the thread to return 
          
      }

内核代码

    // In PreRead 
 try {

                        PMINISPY_NOTIFICATION notification = ExAllocatePoolWithTag(NonPagedPool,sizeof(MINISPY_NOTIFICATION),SPY_TAG);

                        if (notification != NULL) {
                            seconds_to_wait = 5;
                            timeOut.QuadPart = -((LONGLONG)seconds_to_wait * 10 * 1000 * 1000);
                            replyLength = sizeof(MINISPY_REPLY);

                            //Todo: send processName to usermode app and wait for the reply
                            DbgPrint("\nMiniPreRead: kernelTousermode: Waiting for usermode reply...");
                            status = FltSendMessage(MiniSpyData.Filter,&MiniSpyData.ClientPort,notification,replyBuffer,&replyLength,&timeOut);

                            if (STATUS_SUCCESS == status) {
                                blockOrAllowFlag = ((PMINISPY_REPLY)replyBuffer)->res;
                                DbgPrint("\nMiniPreRead: kernelTousermode: Reply blockOrAllowFlag: %d",blockOrAllowFlag);
                            }
                            else if (STATUS_TIMEOUT == status) {
                                DbgPrint("\nMiniPreRead: kernelTousermode: timeout occured!");
                            }
                            else {
                                //  Couldn't send message. This sample will let the I/O through. 
                                DbgPrint("\nMiniPreRead: kernelTousermode: --- Couldn't send message to user-mode to processpath,status 0x%X\n",status);
                            }
                        }
                    }
                    finally {
                        if (notification != NULL) {
                            ExFreePoolWithTag(notification,SPY_TAG);
                        }
                    }

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)