如何解决需要帮助从 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(¬ificatioBuffer.Ovlp,sizeof(OVERLAPPED));
notification = ¬ificatioBuffer;
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,¬ification->MessageHeader,FIELD_OFFSET(MINISPY_MESSAGE,Ovlp),¬ification->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 举报,一经查实,本站将立刻删除。