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

У меня возникла проблема, когда я отправляю сообщение в пользовательский режим из режима ядра, используя FltSendMessage, который ожидает ответа. Передаваемая структура содержит целое число, для которого установлено значение 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, чтобы определить, изменяется ли значение перед отправкой обратно в ядро.


person user6719374    schedule 15.05.2018    source источник
comment
Не имеет отношения к вашему вопросу и проблеме, но символы, начинающиеся с подчеркивания и за которыми следует заглавная буква (например, _REPLY_MESSAGE_STRUCT), зарезервированы во всех областях. См., например. этот старый ответ для более подробной информации.   -  person Some programmer dude    schedule 15.05.2018
comment
Кроме того, пожалуйста, не используйте многоязычные теги, если это действительно не актуально, и вы работаете с несколькими языками или спрашиваете о различиях между несколькими языками. Если вы программируете на C, используйте только тег C.   -  person Some programmer dude    schedule 15.05.2018
comment
Спасибо за ваш ответ, но просто чтобы вы знали, что пользовательский режим находится в C++, а режим ядра — в C. Следовательно, необходимы теги C++ и C. Поскольку я не знаю, где может быть ошибка, либо в приложении пользовательского режима, либо в фильтре режима ядра, но спасибо за ваше предложение.   -  person user6719374    schedule 15.05.2018
comment
FILTER_REPLY_HEADER предназначен только для пользовательского режима FilterReplyMessage и FilterGetMessage. буфер режима ядра не должен начинаться с FILTER_REPLY_HEADER - вы не можете использовать буфер в режиме ядра. удалить FILTER_REPLY_HEADER header; из определения режима ядра   -  person RbMm    schedule 15.05.2018
comment
@Someprogrammerdude - может быть, это сюрприз, но сами заголовки Windows постоянно используют это обозначение. например, _FILTER_REPLY_HEADER   -  person RbMm    schedule 15.05.2018
comment
@RbMm Спасибо за ваше предложение! Удаление структуры ответа из определения режима ядра останавливает получение ответа режимом ядра. Это может быть связано с разницей в структурах, передаваемых между пользовательским режимом и режимом ядра.   -  person user6719374    schedule 15.05.2018
comment
посмотрите, например, сканер - как здесь определены структуры   -  person RbMm    schedule 15.05.2018
comment
FILTER_REPLY_HEADER и FILTER_MESSAGE_HEADER используются только в пользовательском режиме. не по ядру. вы должны определить отдельные структуры для сообщения и ответа. и режим ядра используют его напрямую, пользовательский режим - используют другие структуры - наследуют от FILTER_MESSAGE_HEADER (или FILTER_REPLY_HEADER) и пользовательских структур   -  person RbMm    schedule 15.05.2018


Ответы (1)


вы используете данные об ошибках в вызове FltSendMessage:

ReplyBuffer — это указатель на настраиваемые пользовательские данные. он не должен начинаться с FILTER_REPLY_HEADER SenderBuffer — это указатель на настраиваемые пользовательские данные. он не должен начинаться с FILTER_MESSAGE_HEADER

прежде всего вам нужно < em>определить структуры, общие для режима ядра и пользовательского режима, для сообщения и ответа. Например

struct SCANNER_NOTIFICATION {
    // any custom data
    int someData;

};

struct SCANNER_REPLY {
    // any custom data
    int passFlag;
};

и в режиме ядра вы используете его как есть:

SCANNER_NOTIFICATION send;
SCANNER_REPLY reply;
ULONG ReplyLength = sizeof(reply);

FltSendMessage(*, *, &send, sizeof(send), &reply, &ReplyLength, *);

в пользовательском режиме вы нужно определить 2 дополнительные структуры:

struct SCANNER_MESSAGE : public FILTER_MESSAGE_HEADER, public SCANNER_NOTIFICATION {};

struct SCANNER_REPLY_MESSAGE : public FILTER_REPLY_HEADER, public SCANNER_REPLY {};

(здесь я использую стиль c++, когда здесь используется стиль c), а в пользовательском режиме нам нужно использовать следующий, например:

SCANNER_MESSAGE* mesage;
FilterGetMessage(*, mesage, sizeof(SCANNER_MESSAGE), *);

и

    SCANNER_REPLY_MESSAGE reply;
    reply.MessageId = mesage->MessageId;
    FilterReplyMessage(*, &reply, sizeof(reply));
person RbMm    schedule 15.05.2018
comment
спасибо большое вы легенда! Я совершенно неправильно истолковал документацию. Спасибо еще раз. - person user6719374; 16.05.2018