内核FltSendMessage接收用户态回复时passFlag值异常始终为56求助
解决FltSendMessage回复中passFlag值异常的问题
你遇到的问题根源在于缓冲区大小计算错误和内核态变量定义顺序错误,这两个问题共同导致内核接收回复时解析出错误的passFlag值。让我们一步步拆解并修复:
1. 核心错误:重复计算缓冲区大小
你在计算replySize时犯了关键错误——把FILTER_REPLY_HEADER的大小和整个结构体的大小相加,这相当于重复计算了header部分。
你的REPLY_MESSAGE_STRUCT已经包含FILTER_REPLY_HEADER header字段,所以整个结构体的大小就是sizeof(REPLY_MESSAGE_STRUCT),无需额外叠加header的大小。错误的大小计算会导致:
- 用户态调用
FilterReplyMessage时发送了超出实际结构体的缓冲区,内核接收时会读取栈上的垃圾数据 - 内核态接收缓冲区的偏移解析出错,最终
passFlag被覆盖成随机值(也就是你看到的56)
2. 内核态变量定义顺序错误
看你的内核代码,你在定义replyBuffer之前就给它的成员赋值了:
replyBuffer.passFlag = 0; // 此时replyBuffer还未定义,属于未初始化内存操作 ULONG replySize = ((ULONG)sizeof(replyBuffer.header)) + ((ULONG)sizeof(replyBuffer)); REPLY_MESSAGE_STRUCT replyBuffer; // 这里才定义变量
这种顺序属于未定义行为,编译时可能触发警告,运行时会导致栈内存混乱,进一步加剧数据解析错误。
修复后的代码示例
共享结构体定义(保持不变,需确保内核/用户态完全一致)
typedef struct _REPLY_MESSAGE_STRUCT { // Message header. FILTER_REPLY_HEADER header; // Flag to be set by user mode. int passFlag; } REPLY_MESSAGE_STRUCT, *PREPLY_MESSAGE_STRUCT;
修复后的内核态代码
DbgPrint("Sending Message...\n"); // 先定义缓冲区变量,再操作成员 REPLY_MESSAGE_STRUCT replyBuffer; replyBuffer.passFlag = 0; // 正确计算回复缓冲区大小:整个结构体的大小 ULONG replySize = sizeof(REPLY_MESSAGE_STRUCT); // 实际代码中的try-catch保留 status = FltSendMessage( imageFilterData.filterHandle, &imageFilterData.clientPort, (PVOID)&sendingBuffer.messageBuffer, sizeof(sendingBuffer.messageBuffer), (PVOID)&replyBuffer, &replySize, 0 ); // 接收回复后打印,同时校验状态 if (NT_SUCCESS(status)) { DbgPrint("Message received: %i\n", replyBuffer.passFlag); } else { DbgPrint("FltSendMessage failed: 0x%X\n", status); }
修复后的用户态代码
// 先定义回复消息结构体 REPLY_MESSAGE_STRUCT replyMessage; // 正确计算回复缓冲区大小 ULONG replySize = sizeof(REPLY_MESSAGE_STRUCT); // 必须严格匹配内核发送的消息ID replyMessage.header.MessageId = messageFromKernel.header.MessageId; // 设置passFlag为目标值 replyMessage.passFlag = 1; // 验证本地设置是否成功 printf("Test: %i\n", replyMessage.passFlag); // 发送回复 HRESULT hResult = FilterReplyMessage(port, &replyMessage.header, replySize); _com_error err2(hResult); LPCTSTR errorMessage = err2.ErrorMessage(); printf("Result: %s\n", errorMessage);
额外注意事项
- 确保内核态和用户态的结构体定义完全一致,包括内存对齐(必要时可使用
#pragma pack统一对齐规则) - 始终校验
FltSendMessage和FilterReplyMessage的返回值,排查潜在的状态异常 - 用户态回复时,
replyMessage.header.MessageId必须和内核发送的消息ID严格匹配,否则回复无法被正确关联
内容的提问来源于stack exchange,提问作者user6719374
相关产品推荐
相关产品推荐

