Несколько дней назад пришла в голову идея, о том как скрытно выполнять код в ядре - создать системный поток. Вычислить его сложно, он не привязан к конкретному драйверу. Решил проверить такую идею в целях "повышения образованности". Написал небольшой драйвер, в нём создаёт системный поток, который в бесконечном цикле ждёт событие и как только оно переходит в сигнальное состояние издаёт звук, потом переводит событие в несигнальное состояние и снова ждёт. Написал user mode прогу для управления событием (в том числе и создание), всё чётко работает. Следующий шаг - сделать код потока базонезависимым, сказано сделано. Чтобы проверить как он будет работать находясь по другому адресу, зарезервировал в драйвере место для копии "тела" потока и перед созданием потока переместил код потока туда, а функции PsCreateSystemThread передал новый адрес. Поток создаётся, начинает выполняться, но ошибки возникают в совершенно неожиданных местах, например после вызова функции KeWaitForSingleObject (адрес передаваемого события правильный, проверил сам лично), притом что с функций IoCreateNotificationEvent проблем нет. Может кто-нибудь знает в чём проблема? или у меня в коде есть глупая ошибка, которую я не замечаю... FASM Код (Text): SystemThreadDataStart: Sound: ; функция издаёт звук с помощью системного динамика через порты ввода/вывода cli mov al, 10110110b out 43h, al mov eax, ecx out 42h, al mov al, ah out 42h, al ; включить динамик in al, 61h or al, 11b out 61h, al sti mov ecx, 2800000h loop $ cli ; выключить динамик in al, 61h and al, 11111100b out 61h, al sti ret proc SystemThread PARAM1 int3 call .delta .delta: pop ebx sub ebx, .delta ; EBX = дельта смещение lea eax, [ebx+SyncEventHandle] push eax lea eax, [ebx+SyncEventName ] push eax call [ebx+mitIoCreateNotificationEvent] mov [ebx+SyncEvent], eax .repeat: stdcall [ebx+mitKeWaitForSingleObject], [ebx+SyncEvent], Executive, KernelMode, FALSE, 0 mov ecx, TONE1 call Sound mov ecx, TONE2 call Sound mov ecx, TONE3 call Sound stdcall [ebx+mitKeResetEvent], [ebx+SyncEvent] jmp .repeat ret endp UNICODE_STRING_define SyncEventName, "\BaseNamedObjects\MySyncEventName" SyncEventHandle dd 0 SyncEvent dd 0 mitIoCreateNotificationEvent dd 0 mitKeWaitForSingleObject dd 0 mitKeResetEvent dd 0 SystemThreadDataEnd: SystemThreadDataSize = SystemThreadDataEnd - SystemThreadDataStart SystemThreadHandle dd 0 align 4 NewSysThreadAddress: rb SystemThreadDataSize proc DriverUnloadHandler pDriverObject ret endp proc DriverEntry pDriverObject, pRegistryPath ;пересохраняем адреса необходимых функций mov eax, [IoCreateNotificationEvent] mov [mitIoCreateNotificationEvent], eax mov eax, [KeWaitForSingleObject] mov [mitKeWaitForSingleObject], eax mov eax, [KeResetEvent] mov [mitKeResetEvent], eax mov eax, NewSysThreadAddress mov esi, SystemThreadDataStart mov edi, eax mov ecx, SystemThreadDataSize rep movsb add eax, SystemThread - SystemThreadDataStart ;mov eax, SystemThread invoke PsCreateSystemThread, SystemThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, eax, 0 ;mov eax, STATUS_DEVICE_CONFIGURATION_ERROR mov eax, [pDriverObject] virtual at eax .eax DRIVER_OBJECT end virtual mov [.eax.DriverUnload], DriverUnloadHandler mov eax, STATUS_SUCCESS ret endp с макросом UNICODE_STRING_define проблем нет так как IoCreateNotificationEvent успешно выполняется Код (Text): macro UNICODE_STRING_define name,string { _us_#name du #string _us_#name_len = ($ - _us_#name) dw 0 #name _UNICODE_STRING _us_#name_len,(_us_#name_len+2),_us_#name } после перемещения структуры ссылка (поле Buffer) на саму строку осталась правильной