Форум программистов, компьютерный форум, киберфорум
Программирование драйверов
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 161

Ошибка выгрузки драйвера

06.12.2016, 12:28. Показов 1640. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.

Помогите разобраться с BSOD. Возникает он в следующем режиме: при выдергивании кабеля питания из компьютера. Только при этом поведении! В остальных случаях драйвер ведет себя штатно (множественная загрузка/выгрузка).

После выдергивания кабеля иногда возникает BSOD с ошибкой DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDI NG_OPERATIONS. И эта ошибка уже не пропадает. После снятия dump-а памяти компьютер загружается и снова "сваливается" в эту ошибку.

Я обращался к странице, но у меня нет ни одного из перечисленного "This driver failed to cancel lookaside lists, DPCs, worker threads, or other such items before unload".

Драйвер вешает хук на функцию ZwCreateSection (знаю, что это плохо, но это самый первый мой драйвер).

Пытался смотреть dump памяти, но он оказался не очень информативным...
C
1
2
3
4
5
6
STACK_TEXT:  
a8679a94 80529170 00000050 a903c0a8 00000000 nt!KeBugCheckEx+0x1b
a8679ae4 804e0944 00000000 a903c0a8 00000000 nt!MmAccessFault+0x77e
a8679ae4 a903c0a8 00000000 a903c0a8 00000000 nt!KiTrap0E+0xd0
WARNING: Frame IP not in any known module. Following frames may be wrong.
a8679b6c 00000000 00000400 00000030 00000000 <Unloaded_MyDriver.sys>+0x60a8
Если я правильно понимаю, то ошибка происходит в функции Unload.
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
void DrvUnload(IN PDRIVER_OBJECT driver)
{
    UNICODE_STRING devlink;
 
    UnhookDispatchTable();
 
    RtlInitUnicodeString(&devlink, deviceLink);
    
    if (driver->DeviceObject != NULL)
    {
        IoDeleteSymbolicLink(&devlink);
        IoDeleteDevice(driver->DeviceObject);
    }
}
 
void UnhookDispatchTable()
{
    ULONG a,
          base;
 
    if (address != 0)
    {
        a = 4*address + (ULONG)KeServiceDescriptorTable->ServiceTable;
        base = (ULONG)MmMapIoSpace(MmGetPhysicalAddress((void*)a), 4, MmNonCached);
 
        _asm
        {
            mov eax, base
            mov ebx, RealCallee
            mov dword ptr[eax], ebx
        }
 
        MmUnmapIoSpace((PVOID)base, 4);
 
        address = 0;
    }
}
Если я комментирую вызов функции UnhookDispatchTable(), то BSOD после перезагрузки компьютера и новым подложенным драйвером все равно появляется...

Подскажите, как можно докопаться до сути, где искать ошибку?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.12.2016, 12:28
Ответы с готовыми решениями:

Программа, для загрузки и выгрузки драйвера
Здравствуйте. Ситуация следующая: хочу написать программу для журналирования обращений к диску, при этом само журналирование будет...

Ошибка загрузки драйвера - 1275
Здравствуйте.Тестирую драйвер,у меня на Win XP SP3 все нормально,у друга Windows 7 x64 возникает ошибка при загрузка драйвера на...

Непонятная ошибка компиляции драйвера
Всем привет. Начал изучать программирование драйверов по книге &quot;Солдатов В.П. Программирование драйверов Windows&quot;. Дошел до главы...

11
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
06.12.2016, 14:16
Ну во-первых, ты перехватываешь не ZwCreateSection, а NtCreateSection.
А это немного разные вещи.

Во-вторых, драйвер, который ставит хуки, невыгружаем по своей природе.
Потому что если кто-то сверху поставит хук, то после выгрузки твоего драйвера
указатель этого "кого-то" повиснет. И при первом обращении будет "бяка".

В-третьих, я не вижу синхронизации между Unload и хук-функцией.
Что, если они будут вызваны системой одновременно?

В-четвертых, даже для выгруженных модулей можно в WinDBG
попробовать сделать .reload с ключом /unl и тогда, если символы
подключены, он покажет нормальный стек падения.

И в-пятых, никто и нигде не обещал, что SSDT будет всегда находиться в
неподкачиваемой памяти. Надежнее IoAllocateMdl, MmProbeAndLockPages,
MmProtectMdlSystemAddress и т.д.
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 161
06.12.2016, 17:13  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Во-вторых, драйвер, который ставит хуки, невыгружаем по своей природе.
Потому что если кто-то сверху поставит хук, то после выгрузки твоего драйвера
указатель этого "кого-то" повиснет. И при первом обращении будет "бяка".
Я это неоднократно читал на форуме, спасибо, но сейчас я рассматриваю лабораторные условия. На своем компьютере я сотни раз вешал хук и снимал хук. Ни одного падения в этот момент не было.

В данном примере ошибка возникает только по причине выдергивания кабеля питания из компьютера, система обесточена. После того как заново включаю компьютер происходит эта ошибка. Не может же в этот момент система проверять что было до ее внезапного выключения... или может?

Цитата Сообщение от Убежденный Посмотреть сообщение
В-третьих, я не вижу синхронизации между Unload и хук-функцией.
Что, если они будут вызваны системой одновременно?
Вы имеете в виду выгрузку драйвера и одновременно выполнение хука? Подскажите, как можно реализовать синхронизацию.

Цитата Сообщение от Убежденный Посмотреть сообщение
В-четвертых, даже для выгруженных модулей можно в WinDBG
попробовать сделать .reload с ключом /unl и тогда, если символы
подключены, он покажет нормальный стек падения.
Попробовал команду .reload. "No unloaded module named ...", значит модуль не является выгруженным?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
06.12.2016, 17:25
Цитата Сообщение от shtuceron Посмотреть сообщение
На своем компьютере я сотни раз вешал хук и снимал хук. Ни одного падения в этот момент не было.
Это ничего не доказывает. Не упало 100 раз - упадет в 101-ый.

Цитата Сообщение от shtuceron Посмотреть сообщение
После того как заново включаю компьютер происходит эта ошибка. Не может же в этот момент система проверять что было до ее внезапного выключения... или может?
Скорее всего, все проще и происходит банальная гонка между вызовом
перехваченной функции и выгрузкой драйвера. KiTrap0E - это обработчик
страничных сбоев, кстати говоря.

Цитата Сообщение от shtuceron Посмотреть сообщение
Вы имеете в виду выгрузку драйвера и одновременно выполнение хука? Подскажите, как можно реализовать синхронизацию.
Стопроцентно корректно - никак.
Система не предоставляет внешней синхронизации для таких вещей.

Цитата Сообщение от shtuceron Посмотреть сообщение
Попробовал команду .reload. "No unloaded module named ...", значит модуль не является выгруженным?
Полный текст команды какой?
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 161
06.12.2016, 17:48  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Скорее всего, все проще и происходит банальная гонка между вызовом
перехваченной функции и выгрузкой драйвера.
Я сто процентов не выгружаю драйвер в момент падения.

Последовательность действий такова:
1. Система загрузилась.
2. Происходит работа с компьютером.
3. Выдергиваю кабель из розетки.
4. Вставляю кабель в розетку.
5. Включаю компьютер.
6. Система начинает грузиться.
7. Бац, BSOD (иногда могу дойти до окна ввода имени пользователя и пароля)

Цитата Сообщение от Убежденный Посмотреть сообщение
Полный текст команды какой?
Все, я виноват! Я прописывал неправильный путь, достаточно написать имя драйвера. В моем случае он имеет вид .reload /unl MyDriver.sys

Продолжаю разбираться...

Добавлено через 3 минуты
А ругается он на функцию status = ZwReadFile(...)

C
1
2
3
4
5
6
7
8
9
status = ZwReadFile(fileHandle,
                    hEvent,
                    NULL,
                    NULL,
                    &ioStatusBlock,
                    (PVOID)pFileBuffer,
                    fileBufferLength,
                    pFileOffset,
                    NULL);
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
06.12.2016, 18:00
Цитата Сообщение от shtuceron Посмотреть сообщение
Я сто процентов не выгружаю драйвер в момент падения.
Тогда кто его выгрузил, если в стеке падения написано: "Unloaded_MyDriver.sys"?

Цитата Сообщение от shtuceron Посмотреть сообщение
А ругается он на функцию status = ZwReadFile
Но ты же писал, что у тебя все чисто:

Цитата Сообщение от shtuceron Посмотреть сообщение
Я обращался к странице, но у меня нет ни одного из перечисленного "This driver failed to cancel lookaside lists, DPCs, worker threads, or other such items before unload".
А ZwReadFile вполне может выполняться долгое время...
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 161
07.12.2016, 14:11  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Тогда кто его выгрузил, если в стеке падения написано: "Unloaded_MyDriver.sys"?
Сегодня пол дня потратил на анализ этой проблемы, но так и не нашел ответ.

Цитата Сообщение от Убежденный Посмотреть сообщение
Но ты же писал, что у тебя все чисто:
Это моя ошибка, не принял во внимание ZwReadFile.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
07.12.2016, 14:44
Цитата Сообщение от shtuceron Посмотреть сообщение
Сегодня пол дня потратил на анализ этой проблемы
Покажи стек падения.
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 161
07.12.2016, 15:47  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Покажи стек падения.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
a8679a94 80529170 00000050 a903c0a8 00000000 nt!KeBugCheckEx+0x1b
a8679ae4 804e0944 00000000 a903c0a8 00000000 nt!MmAccessFault+0x77e
a8679ae4 a903c0a8 00000000 a903c0a8 00000000 nt!KiTrap0E+0xd0
a8679cc8 a9043a04 e29cdc18 e2a778a8 00000000 MyDriver!md5_file+0x228 [_PATH_\md5.c @ 416]
a8679d14 a9043ffd a8679d48 a8679d64 0012f6b4 MyDriver!Check+0x294 [_PATH_\MyDriver.c @ 354]
a8679d40 804dd99f 0012f7d0 0000000f 00000000 MyDriver!CallCheck+0xd [_PATH_\MyDriver.c @ 441]
a8679d40 7c90e514 0012f7d0 0000000f 00000000 nt!KiFastCallEntry+0xfc
0012f68c 7c90d18a 7c91c9b3 0012f7d0 0000000f ntdll!KiFastSystemCallRet
0012f690 7c91c9b3 0012f7d0 0000000f 00000000 ntdll!ZwCreateSection+0xc
0012f710 7c91c66a 0012f7a8 0000002c 0012f768 ntdll!LdrpCreateDllSection+0x92
0012f7f0 7c91d7c8 00020498 7ffdfc00 00000000 ntdll!LdrpMapDll+0x28f
0012fa50 7c91d2ed 00020498 0040f012 00400000 ntdll!LdrpLoadImportModule+0x174
0012fa80 7c91d294 7ffd9000 00020498 00251ec0 ntdll!LdrpHandleOneOldFormatImportDescriptor+0x5e
0012fa98 7c91c1ee 7ffd9000 00020498 00251ec0 ntdll!LdrpHandleOldFormatImportDescriptors+0x1f
0012fb14 7c921e45 00020498 00251ec0 7ffdf000 ntdll!LdrpWalkImportDescriptor+0x19e
0012fc94 7c9210af 0012fd30 7c900000 0012fce0 ntdll!LdrpInitializeProcess+0xe02
0012fd1c 7c90e457 0012fd30 7c900000 00000000 ntdll!_LdrpInitialize+0x183
00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7
Добавлено через 26 минут
На всякий случай привожу код функции где происходит падение (80 строка):
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
int md5_file( PUNICODE_STRING pFilePath, unsigned char output[16] )
{
    NTSTATUS status = STATUS_SUCCESS,
             informationFileStatus;
 
    HANDLE fileHandle = NULL;
 
    OBJECT_ATTRIBUTES objectAttributes;
    IO_STATUS_BLOCK ioStatusBlock;
 
    FILE_STANDARD_INFORMATION fileStandardInformation;
 
    int fileBufferLength;
    char *pFileBuffer = NULL;
 
    PLARGE_INTEGER pFileOffset = NULL;
 
    HANDLE hEvent = NULL;
    OBJECT_ATTRIBUTES eventAttributes;
 
    md5_context ctx;
 
    InitializeObjectAttributes(&objectAttributes, 
                               pFilePath,
                               OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE, 
                               NULL, 
                               NULL);
 
    status = ZwCreateFile(&fileHandle,
                          FILE_READ_DATA,
                          &objectAttributes,
                          &ioStatusBlock,
                          NULL,
                          FILE_ATTRIBUTE_NORMAL,
                          FILE_SHARE_READ,
                          FILE_OPEN_IF,
                          FILE_SYNCHRONOUS_IO_NONALERT,
                          NULL,
                          0);
 
    if (!NT_SUCCESS(status))
        return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
 
    md5_init(&ctx);
    md5_starts(&ctx);
 
    informationFileStatus = ZwQueryInformationFile(fileHandle, 
                                                   &ioStatusBlock, 
                                                   &fileStandardInformation, 
                                                   sizeof(fileStandardInformation), 
                                                   FileStandardInformation);
 
    pFileOffset = (PLARGE_INTEGER)ExAllocatePool(PagedPool, sizeof(LARGE_INTEGER));
 
    pFileOffset->QuadPart = 0;
 
    if (fileStandardInformation.EndOfFile.QuadPart != 0)
    {
        fileBufferLength = (fileStandardInformation.EndOfFile.QuadPart > 1024) ? 1024 : (int)fileStandardInformation.EndOfFile.QuadPart;
 
        while (fileStandardInformation.EndOfFile.QuadPart > 0)
        {
            pFileBuffer = (char *)ExAllocatePool(PagedPool, fileBufferLength);
            RtlZeroMemory(pFileBuffer, fileBufferLength);
 
            InitializeObjectAttributes(&eventAttributes,
                                       0,
                                       0,
                                       0,
                                       0 );
 
            status = ZwCreateEvent(&hEvent,
                                   EVENT_ALL_ACCESS,
                                   &eventAttributes,
                                   SynchronizationEvent,
                                   0);
 
            if (NT_SUCCESS(status))
            {
                status = ZwReadFile(fileHandle,
                                    hEvent,
                                    NULL,
                                    NULL,
                                    &ioStatusBlock,
                                    (PVOID)pFileBuffer,
                                    fileBufferLength,
                                    pFileOffset,
                                    NULL);
 
                if (status == STATUS_PENDING)
                {
                    status = ZwWaitForSingleObject(hEvent, FALSE, NULL);
                    status = ioStatusBlock.Status;
                }
 
                if (hEvent != NULL)
                    ZwClose(hEvent);
 
                if (NT_SUCCESS(status))
                {
                    md5_update( &ctx, (const unsigned char *)pFileBuffer, fileBufferLength );
 
                    pFileOffset->QuadPart += fileBufferLength;
                    fileStandardInformation.EndOfFile.QuadPart -= fileBufferLength;
                    fileBufferLength = (fileStandardInformation.EndOfFile.QuadPart > 1024) ? 1024 : (int)fileStandardInformation.EndOfFile.QuadPart;
                }
            }
 
            if (pFileBuffer != NULL)
                ExFreePool(pFileBuffer);
        }
    }
 
    md5_finish( &ctx, output );
    md5_free( &ctx );
    
    if (pFileOffset != NULL)
        ExFreePool(pFileOffset);
 
    if (fileHandle != NULL)
        ZwClose(fileHandle);
 
    return STATUS_SUCCESS;
}
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
07.12.2016, 20:08
Ну лично я в этом коде сходу вижу две ошибки:

1. Нет проверки, сколько именно байт прочитала ZwReadFile.
Нужное значение следует брать из ioStatusBlock.Information.

2. Нет проверки, что ZwQueryInformationFile вернула успех.

На будущее: во время тестирования драйвера рекомендуется сразу
включать для него Driver Verifier, тогда некоторые ошибки всплывают
на максимально ранних стадиях.
0
0 / 0 / 0
Регистрация: 26.08.2013
Сообщений: 161
08.12.2016, 10:18  [ТС]
Спасибо, с Вами полностью согласен.

А что вы скажете о стеке падения и ошибке DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDI NG_OPERATIONS в данном случае?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
08.12.2016, 11:44
По поводу падения - см. пункт 1. Скорее всего, причина из-за этого.

По поводу ошибки с выгрузкой - трудно сказать что-то определенное, не видя кода.
Может быть такая, например, ситуация: система загрузила драйвер, ты поставил в
DriverEntry хук на NtCreateSection, но потом возникла какая-то ошибка и драйвер
был выгружен, а хук остался. Если в это время твой драйвер внутри функции хука
вызывал ZwReadFile, система вполне могла выкинуть BSOD с таким кодом...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.12.2016, 11:44
Помогаю со студенческими работами здесь

C# Ошибка выгрузки текста с файла в listview
Здравствуйте! Подскажите мою ошибку пожалуйста! Уже давно мучаюсь.. Почему при выполнения этого скрипта, listview становиться пустым и...

Ошибка при попытке выгрузки в Excel
Здравствуйте. В проекте использую сборку Microsoft.Office.Interop.Excel версии 12.0.0.0. На некоторых ПК при попытке выгрузить выдает...

Создание обработки для выгрузки данных в dbf: Ошибка создания файла
Всем добрый день! Пытаюсь написать обработку для выгрузки данных в dbf, нашла разные примеры. В итоге, при попытке записать обработку...

Ошибка драйвера
Доброго времени суток. Раскидывал в офисе свою программу и наткнулся на казус.БД находится на удаленном сервере, со своего компа...

Ошибка драйвера
проблема с дрйвером &quot;устройства HID&quot; &quot;ene cir receiver&quot; пишет &quot;Недостаточно свободных ресурсов для работы данного устройства. (Код 12)...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru