С Новым годом! Форум программистов, компьютерный форум, киберфорум
Программирование драйверов
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/8: Рейтинг темы: голосов - 8, средняя оценка - 4.75
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294

WFP. ClassifyFn и BSOD

16.10.2015, 17:03. Показов 1719. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Итак, перехватываются UDP-дейтаграммы, на этой функции вылетает любимый BSOD. Признаться, я уверен, что она написана неправильно, но что именно, сказать мне трудно. Видимо, что-то во время чтения MSDN упустил.

Не могли бы подсказать, что не так?

ClassifyFn
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
void _stdcall OnClassify(
    __in    FWPS_INCOMING_VALUES0 const           * pInFixedValues,
    __in    FWPS_INCOMING_METADATA_VALUES0 const  * pInMetaValues,
    __out   VOID                                  * pLayerData,
    __in    FWPS_FILTER0 const                    * pFilter,
    __in    UINT64                                  FlowContext,
    __out   FWPS_CLASSIFY_OUT0                    * pClassifyOut)
{
    NTSTATUS status = STATUS_SUCCESS;
 
    NET_BUFFER_LIST* netBufferList,
        *clonedNetBufferList;
    FWPS_PACKET_INJECTION_STATE injectionState;
    FWPS_TRANSPORT_SEND_PARAMS0* tlSendArgs;
    NET_BUFFER* buf;
    int sizeOfPackage,
        j, where;
    char strr[14];
 
    status = STATUS_SUCCESS;
    netBufferList = (NET_BUFFER_LIST*)pLayerData;
    clonedNetBufferList = NULL;
    tlSendArgs = NULL;
    sizeOfPackage = 0;
    j = 0;
 
    /* Проверям, не был ли пакет встроен в стек TCP/IP заранее */
    injectionState = FwpsQueryPacketInjectionState0(
        inject,
        netBufferList,
        NULL);
 
    if (injectionState == FWPS_PACKET_INJECTED_BY_SELF ||
        injectionState == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF)
    {
        pClassifyOut->actionType = FWP_ACTION_PERMIT;
        pClassifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
        return;
    }
 
    pClassifyOut->rights &= FWPS_RIGHT_ACTION_WRITE;
 
    /* Находим размер всего пакета */
    for (buf = NET_BUFFER_LIST_FIRST_NB(netBufferList); buf != 0;
    buf = NET_BUFFER_NEXT_NB(buf))
        sizeOfPackage += NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(netBufferList));
 
    if (sizeOfPackage < 170)
    {
        pClassifyOut->actionType = FWP_ACTION_PERMIT;
        goto Exit;
    }
 
    /* Создем клона netBufferList */
    status = FwpsAllocateCloneNetBufferList0(netBufferList, 0, 0,
        0, &clonedNetBufferList);
 
    /* Этот цикл просматривает все NET_BUFFER на наличие интересной информации */
    for (buf = NET_BUFFER_LIST_FIRST_NB(clonedNetBufferList); buf != 0;
    buf = NET_BUFFER_NEXT_NB(buf))
    {
        int sizeOfBlock;
        char* data, curr[4];
        int i;
 
        /* Размер блока */
        sizeOfBlock = NET_BUFFER_DATA_LENGTH(buf) - 1;
 
        /*!!! Получаем информацию с NET_BUFFER */
        data = (char*)NdisGetDataBuffer((PNET_BUFFER)buf, sizeOfBlock, 0, 1, 0);
 
        for (i = sizeOfBlock; i >= 0; --i)
        {
            if (data[i] == '@')
            {
                int k, curDigits, digitCount;
 
                while (i < sizeOfBlock && tolowerD((int)data[i]) != 'v') 
                    strr[j++] = data[i++];
                
                /* Если интересующая нас информация располагается в нескольких 
                   NET_BUFFER — ну ее к черту, уходим. */
 
                
                if (i == sizeOfBlock && data[i - 1] != 'v')
                    goto Exit;
 
                parse(strr, &curDigits, curr);
 
                /* digitCount — число, определяющее, сколько байтов нужно добавить в пакет */
                if ((digitCount = strlen(curr) - curDigits) < 0)
                    goto Exit;
 
                /* Смещаем все байты до на digitCount (за счет NonUsedBlock, вроде) */
                for (k = 0; k <= where; ++k)
                    *(data - digitCount + k) = *(data + k);
 
                /* Смещаем смещение и длину данных в buf*/
                NET_BUFFER_DATA_OFFSET(buf) -= digitCount;
                NET_BUFFER_DATA_LENGTH(buf) += digitCount;
 
                /* Записываем данные */
                for (k = 0; k < strlen(curr); ++k)
                    data[where++] = curr[k];
 
                /* Корректируем MDL (мы ведь изменили Offset и Data_Length) */
                NdisAdjustNetBufferCurrentMdl(buf);
 
                /* Инжектим клона в стек */
                status = FwpsInjectTransportSendAsync(inject, 0, pInMetaValues->transportEndpointHandle,
                    0, 0, AF_INET, UNSPECIFIED_COMPARTMENT_ID, clonedNetBufferList, InjectionCompletionFn, 0);
 
                if (NT_SUCCESS(status))
                    pClassifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
                else
                    goto Exit;
 
                clonedNetBufferList = 0;
 
                goto Exit;
            }
        }
    }
Exit:
    if (clonedNetBufferList)
        FwpsFreeCloneNetBufferList(clonedNetBufferList, 0);
 
    pClassifyOut->actionType = FWP_ACTION_BLOCK;
    pClassifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.10.2015, 17:03
Ответы с готовыми решениями:

Wfp + БД
Добрый день. Задача заключается в том, что хочу написать что то типа калькулятора калорий. Меню(или как это назвать) на wpf, а все...

WFP
Помогите описать элементы структуры WPM_FILTER0_ myFilter = { 0 }; UINT64 id = NULL; RtlZeroMemory(&amp;myFilter,...

Firewall, сниффер WFP
1) Минимальный пример из msdn не работает http://msdn.microsoft.com/en-us/library/windows/desktop/aa364040(v=vs.85).aspx ...

16
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
16.10.2015, 23:08
А BSOD с каким кодом ? Упало в какой строке ? Где стек падения ? И т.д.
Навскидку - почему нет проверки, что pLayerData != NULL ?
0
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294
16.10.2015, 23:51  [ТС]
Код 0x000000D1: DRIVER_IRQL_NOT_LESS_OR_EQUAL. Ну и остальные :
BCP1: 000000000000011A
BCP2: 0000000000000002
BCP3: 0000000000000000
BCP4: FFFFF880016477FC

Цитата Сообщение от Убежденный Посмотреть сообщение
Навскидку - почему нет проверки, что pLayerData != NULL ?
Проворонил, поставим. Стоп, а возможна передача нулевого указателя?

Меня пора вешать на первом фонарном столбе, я совершенно забыл погуглить. Я ведь и не знал, что вообще есть .dmp файлы, да и эффект BSOD'a и коды испугали. В общем, сейчас сам проанализирую файл, но вот он сам (Яндекс.Диск), если хочешь, потому что я скорее всего чего-то упущу :)
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
16.10.2015, 23:58
На будущее: эксперименты на живой машине и "разбор полетов"
через .dmp-файлы - это далеко не лучшее, что можно придумать.

Значительно удобнее отлаживать драйверы на виртуальной машине с
подключенным отладчиком ядра, там и BSOD-а не будет, пока сам
не пожелаешь, и можно крутить систему так и этак, пока не
найдешь "виновника". А .dmp - это "привет из прошлого", очень
часто по дампу ничего не понятно...
1
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294
17.10.2015, 18:01  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
На будущее: эксперименты на живой машине и "разбор полетов"
через .dmp-файлы - это далеко не лучшее, что можно придумать.
Я, конечно, подавал признаки идиота, но я им не в такой степени являюсь. Конечно, виртуалкa на моих 3 Гб каком-то бюджетнейшем процессоре — не самая лучшая вещь, но живую систему я храню как зеницу ока.

Насчет отладчика — KernelDebugger.exe из DTfW?
Так как все-таки правильно такую программу отлаживать? WinDbg.exe?

Добавлено через 17 часов 29 минут
Я получил смещение от начала функции (от дамп-файла -- OnClassify + 20c). Теперь что, дизассемблер в руки и вперед? Или есть более эффективный путь?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
17.10.2015, 18:45
Подключи PDB-файлы и будешь видеть названия функций, имена и значения,
переменных, нормальный стек и т.п.

По поводу отладчика я настоятельно рекомендую WinDBG и только его.
Там огромное количество самых разных команд, а также возможность
подключать расширения, например мои любимые pykd и cmkd с Python.

Вот здесь написано, как подключить отладочные символы Microsoft:

Use the Microsoft Symbol Server to obtain debug symbol files
https://support.microsoft.com/en-us/kb/311503

Ну а дальше все по накатанной: ставишь VBox/VMware/Hyper-V, -
кому что больше нравится, - переводишь ее в режим отладки и
коннектишь WinDBG через виртуальный COM-порт (-> pipe).

А если есть дополнительный монитор, то лучше вывести окно
отладчика на него, тогда вообще шик !..
1
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294
17.10.2015, 21:42  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
А если есть дополнительный монитор, то лучше вывести окно
отладчика на него, тогда вообще шик !..
Дополнительный монитор?) Хах, мне бы завтра нормально поесть, куда там, мониторы :D

В общем, нехорошая ситуация вышла. Вылет происходит в 74 строке:
C
1
if (data[i] == '@')
Честно говоря, странно. Все инициализировано, pLayerData не пустой, вон и отладчик говорит, что там на целых 500 байт DataLength у текущего NET_BUFFER... А ВОТ data (70 строка) ПУСТОЙ, во всяком случае, так отладчик говорит (скрин приложен).
Миниатюры
WFP. ClassifyFn и BSOD  
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
17.10.2015, 22:15
tnk500, а что тут удивляться-то, собственно говоря ?
Почитай внимательно описание NdisGetDataBuffer, там есть ответы.

И вообще, возьми за правило: если нет стопроцентной уверенности,
что функция всегда будет возвращать ненулевое значение, то всегда
должна стоять проверка на NULL.
1
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294
17.10.2015, 22:22  [ТС]
Получается, data может быть равно нулю... Значит, нужно "листать" список до тех пор, пока не найдется тот NET_BUFFER, от которого получим корректный указатель на данные... И лучше загонять data в качестве параметра (вроде)... Ладно, потестирую, хоть от синего экрана избавлюсь (если других ошибок нет).

Правило полезное, частенько забываю о нем. Вот кстати к этой функции я описание не полностью читал, зато бы уверен, что получу отличный указатель на данные.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
17.10.2015, 22:23
Цитата Сообщение от tnk500 Посмотреть сообщение
Значит, нужно "листать" список до тех пор, пока не найдется тот NET_BUFFER, от которого получим корректный указатель на данные...
Нет. Если тебе нужно содержимое NET_BUFFER, а не нули, нужно
передавать немного другие аргументы в NdisGetDataBuffer.
0
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294
17.10.2015, 23:57  [ТС]
Убежденный, так, стоп, тут я немного не понял. Непонятно предназначение третьего параметра. Если блок данных непрерывен, получаем указатель на него через возвращаемое значение. Иначе он вернет ноль, зато скопирует непрерывный блок в третий параметр, так? Хм, как же тогда понять, что ноль возвращен не потому что там некорректено число запрошенных байтов, а именно потому, что блок данных не является непрерывным.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
18.10.2015, 00:32
Смотри: тебе нужно прочесть данные, которые лежат в NET_BUFFER. Существуют два
основных подхода, даже можно сказать идеологии. Первая (назовем ее callback-модель)
подразумевает проход по всем разбросанным буферам, MDL и т.п. и на каждый кусок
данных вызов определенной функции (callback). Эта модель сложна в реализации,
но она самая эффективная, поскольку здесь нет ни выделений и освобождений памяти,
ни копирования. Вторая модель, более простая (пускай будет object-модель),
заключается в том, чтобы сначала склеить все куски данных в один промежуточный
буфер, а затем уже работать с ним. Короче, прямо как SAX и DOM в обработке XML.

NdisGetDataBuffer - это и есть предоставленная драйвером NDIS реализация
второго метода. И ей нужно во время обработки данных откуда-то брать этот
промежуточный буфер. Если данные непрерывны, то NdisGetDataBuffer просто
возвращает указатель на них. Если данные разбиты по буферам, то NdisGetDataBuffer
сначала склеивает их в буфере, который предоставил клиент, а затем возвращает
указатель на них. Ну а если буфера нет (третий аргумент == NULL), то и
склейки нет и функция вернет NULL. Это все есть в документации...
1
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294
18.10.2015, 00:44  [ТС]
Значит, я правильно понял, замечательно. Я, по правде, слишком задержался с драйвером, поэтому этой функцией ограничиться придется. Что ж поделать...

Кстати, большущее спасибо. Я ожидал, что через пару вопросов меня кинешь, а нет, каждый вопрос разъясняешь, да еще как! Просто не знаю, что и сказать.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
18.10.2015, 00:47
Цитата Сообщение от tnk500 Посмотреть сообщение
Значит, я правильно понял, замечательно.
Если ты имел в виду это:

Цитата Сообщение от tnk500 Посмотреть сообщение
Иначе он вернет ноль, зато скопирует непрерывный блок в третий параметр, так?
То нет, неправильно

Цитата Сообщение от tnk500 Посмотреть сообщение
Кстати, большущее спасибо. Я ожидал, что через пару вопросов меня кинешь, а нет, каждый вопрос разъясняешь, да еще как! Просто не знаю, что и сказать.
Да ладно, все ок.
Ты спрашиваешь - я отвечаю. Для этого и существует форум...
1
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294
18.10.2015, 02:23  [ТС]
Убежденный, аааа, так он в любом случае вернет корректный указатель, главное, чтобы буффер был достаточным? Так даже лучше, отлично.

Добавлено через 1 час 15 минут
И все же меня беспокоит одна деталь. Достаточно ли просто изъять данные, изменить их (как я делаю в программе), заинжектить их, чтобы изменённые данные увидел адресат?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
18.10.2015, 09:28
Не могу точно ответить на этот вопрос, с техникой "clone-and-reinject" не работал.
Но если ты все сделаешь согласно документации, не забудешь про всякие флаги и т.п.,
то не вижу причин, почему бы это не должно работать.
0
117 / 121 / 42
Регистрация: 25.08.2012
Сообщений: 1,294
18.10.2015, 19:36  [ТС]
Похоже, от этой техники придется отказаться. Я не знаю, не менялись ли данные только потому, что я отправлял дейтаграммы самому себе, или нет, но данные оставались теми же. А еще начал бсод вылетать с кодом 0xA, жалуясь на 126 строку. В общем, код не стабилен, надо посмотреть на другие техники изменения. Нельзя ли о них вкраце, какую лучше использовать... Вроде видел что-то, связанное с ссылкой на NET_BUFFER_LIST, но пример там только той методики, которую я пытался реализовать.

Добавлено через 12 минут
А, забыл уточнить. Бсод появлялся в случае смещения данных (т.е. в 96 строке digitCount не равен нулю). Я немного изменил код, заменив ручную корректировку смещения и размера данных функцией NdisRetreatNetBufferDataStart и убрав корректировку MDL. Сам парсер на тестовом примере работает отлично, и изменяет нужные байты в полной версии отлично, судя по показаниям дебаггера.

Добавлено через 1 час 16 минут
Ой, не заметил, есть там примеры
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.10.2015, 19:36
Помогаю со студенческими работами здесь

Массив из Button WFP
Мне необходимо на форме создать поворачиваемые рукоятки (кликом мышки меняется положение рукоятки с вертикального в горизонтальный и...

Firewall(WFP) Запуск
Написал firewall на WFP. Когда отлаживался - запускал через студийную консоль с правами администратора, из неё - запускаю QT creator....

Firewall разработка на WFP
У меня магистерская диссертация по программированию на тему безопасности. Мне надо разработать антивирус либо firewall. можно ли...

Windows Filtering Platform (WFP)
Добрый день. Читаю документацию. Общий смысл понятен. Но вот при попытке перейти к практике - потерпел фиаско. Есть примеры. Есть...

Фильтрация и сравнение IP wia WFP
Доброго времени суток! Благодаря товарищу Убежденный, разобрался немного в теме и наваял код. Подскажите пожалуйста, как мне исправить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru