Member 13809184 Ответов: 1

Мини-фильтр получает постоянное значение от приложения пользовательского режима


Эй,

У меня возникла проблема, когда я отправляю сообщение в пользовательский режим из режима ядра с помощью FltSendMessage, которое ожидает ответа.Передаваемая структура содержит значение and int, равное либо 0, либо 1. Пользовательский режим отвечает, устанавливая этот флаг и вызывая FilterReplyMessage. Однако, когда сообщение принимается ядром, его значение всегда равно 56. Независимо от того, какое число я установил флаг в пользовательском режиме. Ядро всегда получает значение 56. Я не совсем понимаю, в чем моя ошибка. Я попытался изменить тип данных passFlag с int на другие типы (USHORT и т. д.), которые, как я знал, вероятно, не будут иметь значения, но попробовать стоило.

Поскольку сообщение ядра отвечает успешно (проверка пользовательского режима HRESULT не возвращает ошибок и нет таймаута, поэтому, если ответ не будет получен, система зависнет, чего она не делает), я знаю, что ошибка должна быть связана с буферами, передаваемыми между пользовательским режимом и режимом ядра. Кажется, я не могу найти причину, по которой passFlag не интерпретируется правильно в режиме ядра.

Спасибо всем, кто найдет время рассмотреть мой вопрос.
Ваше здоровье!

Общая Структура:
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");

replyBuffer.passFlag = 0;
ULONG replySize = ((ULONG)sizeof(replyBuffer.header)) + ((ULONG)sizeof(replyBuffer));
REPLY_MESSAGE_STRUCT replyBuffer;

// Note: Try-catch statement has been omitted in this question to save time.
// In the actual code there is a try-catch statement surrounding FltSendMessage.
status = FltSendMessage(imageFilterData.filterHandle,
			            &imageFilterData.clientPort,
				        (PVOID)&sendingBuffer.messageBuffer,
						sizeof(sendingBuffer.messageBuffer),
						(PVOID)&replyBuffer,
					    &replySize,
					    0
					    );
// Always returns 56
// When a reply has been received.
DbgPrint("Message received: %i\n", replyBuffer.passFlag);

код пользователя:

// User-mode buffer is the same size as kernel-mode buffer.
ULONG replySize = ((ULONG)sizeof(replyBuffer.header)) + ((ULONG)sizeof(replyBuffer));
replyMessage.header.MessageId = messageFromKernel.header.MessageId;
REPLY_MESSAGE_STRUCT replyMessage;

// User-mode setting flag.
replyMessage.passFlag = 1;

// Flag is changed to 1 successfully.
printf("Test: %i\n", replyMessage.passFlag);

// Reply is sent successfully, but flag value on kernel end is always 56
hResult = FilterReplyMessage(port,
		&replyMessage.header,
		replySize);

_com_error err2(hResult);

errorMessage = err2.ErrorMessage();

// No errors.
printf("Result: %s\n", errorMessage);


Что я уже пробовал:

Изменение типа данных passFlag.

Проходя через каждый шаг до и после сообщения FltSendMessage и FilterReply, чтобы узнать, изменяется ли значение перед отправкой обратно в ядро.

1 Ответов

Рейтинг:
5

Jochen Arndt

Опубликованный код не имеет никакого смысла и даже не должен компилироваться, потому что вы используете REPLY_MESSAGE_STRUCT переменные до того, как они были объявлены с обеих сторон.

Расчет размера также неверен, потому что вы добавляете размер всей структуры ответа вместо размера компонентов:

ULONG replySize = ((ULONG)sizeof(replyBuffer.header)) + ((ULONG)sizeof(replyBuffer));
Так и должно быть
ULONG replySize = sizeof(replyBuffer.header) + sizeof(replyBuffer.passFlag);
или
ULONG replySize = sizeof(FILTER_REPLY_HEADER) + sizeof(int);

Вы также всегда должны инициализировать все обязательные поля структур:
// This is missing in your code.
// When not clearing Status here it may contain any random value.
replyMessage.header.Status = 0; 
// Set other members
replyMessage.header.MessageId = messageFromKernel.header.MessageId;
replyMessage.passFlag = 1;

Это все еще может не решить вашу проблему, но позволит избежать, по крайней мере, других проблем, которые возникнут позже.

До сих пор я не пользовался такими фильтрами. Так что я больше ничем не могу помочь. Но вы должны прочитать документацию Microsoft об этих фильтрах и используемых функциях. Это может быть также полезно для поиска в интернете, например, кода, чтобы увидеть, как это делают другие.


Member 13809184

Спасибо Йохен,

Это моя вина, я оставил приличное количество кода, чтобы сэкономить место. Все значения создаются перед использованием (включая значения структуры). Простите меня за то, что я не правильно выложил код, есть приличная сумма, которую я пропустил. Я просто пытался получить важные вещи, чтобы сэкономить время читателей.

Все строится и работает правильно. В том числе успешное сообщение, отправленное в пользовательский режим из режима ядра, и ответ в режим ядра из пользовательского режима также работают. Единственная проблема заключается в том, что значение passFlag не меняется.

К сожалению, согласно документации Microsoft, могут возникнуть некоторые проблемы с заполнением, поэтому они рекомендуют вычислить размер буфера, добавив размер replyStruct.header + replyStruct
Ссылка:
(https://msdn.microsoft.com/en-us/library/windows/hardware/ff541508(v=против 85).aspx)

Еще раз спасибо за ваш ответ Йохен!

Jochen Arndt

Я читал документацию о прокладке, как и вы. Но вы добавили один sizeof(replyStruct) (общая структура, размер), а оператор sizeof(mystruct) (размер дополнительных данных; int в вашем случае)!

Что касается статуса участника:
При наличии отладочной сборки, которая будет инициализирована нулем. Но как только вы сделаете релизную сборку, память структуры не будет очищена при объявлении!

Что касается не видимого значения данных:
Каков поток функций (в каком порядке они вызываются и перекрываются или нет)?

Опять же: это может помочь проверить источники в интернете, которые использовали такие фильтры.

Member 13809184

Спасибо Йохен,

Я изменил значения соответственно.

Расчет размера = это типа ulong replySize = ((как ulong)оператор sizeof(replyBuffer.заголовок)) + ((типа ulong)оператор sizeof(replyBuffer));

Статус также устанавливается в пользовательском режиме:

сообщений replymessage.заголовок.Статус = 0;

Значение в режиме ядра теперь всегда равно 40.

As for flow of functions, During driver entry I instantiate my structures and register my communication port(imageFilterData.filterHandle and imageFilterData.clientPort). I'm registered to listen for MJ_CREATE. During PostOperation I get the filename safely , parse it and copy it into sendingBuffer.messageBuffer (message struct definition below). Then I send it off to user-mode with an allocated reply buffer using FltSendMessage. User-mode receives the file-name successfully. Does some basic processing using the filename then returns 0 or 1 to the filter using FltReplyMessage. Then I attempt to see what value is returned to the kernel and I get some constant unrelated value. If user-mode sends the pass flag 0, kernel mode gets 40 or 56. If user-mode sends 1, kernel-mode gets 40 or 56. I know I must be doing something wrong with the buffer.

Структура Сообщения Отправителя:
Это передается в пользовательский режим. Имя файла копируется в буфер сообщений.
typedef struct _MESSAGE_STRUCT {

Заголовок FILTER_MESSAGE_HEADER;

PVOID messageBuffer[400];

}MESSAGE_STRUCT , *PMESSAGE_STRUCT;


Я читал образцы WDK minispy и сканера, касающиеся общения с пользователями. Я не могу показаться, чтобы поймать то, что мне не хватает. Но я продолжу, я знаю, что мне чего-то не хватает.

Еще раз спасибо, что нашли время взглянуть на мою проблему!

Jochen Arndt

Это буфер из 400 указателей:
PVOID messageBuffer[400];

Однако на каком-то этапе вы, вероятно, используете неправильный буфер. Буфер, используемый FilterReplyMessage (), не является тем же буфером, что и те, которые используются на стороне ядра при вызове FltSendMessage(). Так что это никогда не меняется (Кстати: коды 40 и 56-это символы "(" и "8").

Как уже отмечалось, я никогда не пользовался такими фильтрами. Но кажется, что вы должны использовать буфер, переданный FltSendMessage() при ответе или получить доступ к переданному буферу на стороне ядра (если есть какая-то функция для его получения).

Member 13809184

Эй, Йохен, большое спасибо за Ваш вклад. Я обнаружил, что моя проблема была связана с моими структурами. Еще раз большое спасибо.