Знаю, что просить разобраться в исходнике не прилично, но все-таки посмотрите. Цель драйвера: Писать в файл из буфера. Основные данные: OutBuffer - буфер источник FilePath - путь к файлу для записи Lseek - значение указателя внитри файла (пишем всегда сначала) My_status - структура IO_STATUS_BLOCK (требуется в ZWWriteFile) Основные процедуры: WRITE_WORK - открытие, запись, закрытие файла MJ_CONTROL - обрабатывает пакеты IRP от DeviceIoControl MJ_CREATE_CLOSE - обрабатывает пакеты IRP от CreateFile & CloseHandle MJ_SHUTDOWN_FUNCTION - вызывается при перезагрузке компьютера (в данном примере не важна, она для дальнейшего усовершенствования) Краткое описание: Программа (tester) из пользовательского режима вызывает: 1. CreateFile 2. DeviceIoControl 3. CloseHandle 4. ExitProcess При вызове DeviceIoControl: метод Buffering передается один байт и принимается, в драйвере он не используется. После получения IRP с пометкой DEVICE_CONTROL вызывается процедура MJ_CONTROL, она создает "отложенное задание" и ставит его в очередь. "Отложенное задание" будет выполняться в контексте системного потока (system thread) его задача - открыть, записать и закрыть файл. ZwCreateFile, ZwWriteFile, ZwClose будут выполняются в одном системном контексте. Далее попадаем в процедуру "отложенного задания". В ней все вызовы Zw* проходят без ошибок. !!! После выхода из процедуры "отложенного задания" в SoftIce появляется до боли знакома надпись Page Fault... И последствия не заставляют себя ждать. Замечания: Создание, запись и закрытия файла завершаются успешно, если код открытия, записи и закрытия поместить в процедуру DriverEntry. Пробовал создать PsCreateSystemThread но еще не имею его синхронизировать, а через переменные-флаги объявленные в data не получается. От меня: Понимаю, что Zw* нужно вызывать из одного контекста потока (желательно из системного, ZWWriteFile только там и работает) ведь MJ_CONTROL выполняется в контексте потока, в котором был вызов DeviceIoControl. И из-за неверного контекста происходит обращение по адресу не существующей в этом контексте странице. Нужен совет, как !ПРАВИЛЬНО! организовать такую работу с файлом. Тему можно рассмотреть шире: как не запутаться в контекстах. Исходные текст драйвера: .386 .model FLAT,STDCALL option casemap:none includelib \masm32\lib\w2k\ntoskrnl.lib include \masm32\include\w2k\ntddk.inc include \masm32\include\w2k\ntstatus.inc include \masm32\include\w2k\ntoskrnl.inc .data FilePath UNICODE_STRING <sizeof FilePath_str-2,sizeof FilePath_str,offset FilePath_str> FilePath_str dw '\','?','?','\','C',':','\','M','i','k','e','.','t','x ','t',0 OutBuffer db 'MIKE_FEOKTISTOV' Lseek dd 0 dd 0 LinkName_str dw '\','?','?','\','M','y','D','e','V','L','i','n','k',0 LinkName UNICODE_STRING <sizeof LinkName_str-2,sizeof LinkName_str,offset LinkName_str> DevName_str dw '\','D','e','v','i','c','e','\','M','y','D','e','v',0 DevName UNICODE_STRING <sizeof DevName_str-2,sizeof DevName_str,offset DevName_str> My_status IO_STATUS_BLOCK <?> ;--------------------------------------------------------- .code INIT DriverEntry proc DrvObjectWORD,RegPathWORD int 3 mov eax,DrvObject mov (DRIVER_OBJECT ptr [eax]).DriverUnload,offset DriverUnload mov (DRIVER_OBJECT ptr [eax]).MajorFunction[IRP_MJ_SHUTDOWN*4],offset MJ_SHUTDOWN_FUNCTION mov (DRIVER_OBJECT ptr [eax]).MajorFunction[IRP_MJ_CREATE*4],offset MJ_CREATE_CLOSE mov (DRIVER_OBJECT ptr [eax]).MajorFunction[IRP_MJ_CLOSE*4],offset MJ_CREATE_CLOSE mov (DRIVER_OBJECT ptr [eax]).MajorFunction[IRP_MJ_DEVICE_CONTROL*4],offset MJ_CONTROL push eax invoke IoCreateDevice,eax,0,offset DevName,FILE_DEVICE_UNKNOWN,0,0,esp invoke IoCreateSymbolicLink,offset LinkName,offset DevName pop eax invoke IoRegisterShutdownNotification,eax mov eax,STATUS_SUCCESS ret DriverEntry endp .code ;--------------------------------------------------------- DriverUnload proc DrvObjectWORD int 3 ;for SoftIce mov eax,DrvObject mov eax,(DRIVER_OBJECT PTR [eax]).DeviceObject push eax invoke IoUnregisterShutdownNotification,eax invoke IoDeleteSymbolicLink,offset LinkName pop eax invoke IoDeleteDevice,eax ret DriverUnload endp ;--------------------------------------------------------- MJ_SHUTDOWN_FUNCTION proc DeviceObjectWORD,pIRPWORD int 3 mov eax,pIRP mov (_IRP ptr [eax]).IoStatus.Status,STATUS_SUCCESS mov (_IRP ptr [eax]).IoStatus.Information,0 invoke IoCompleteRequest,eax,IO_NO_INCREMENT ret MJ_SHUTDOWN_FUNCTION endp ;--------------------------------------------------------- MJ_CREATE_CLOSE proc DeviceObjectWORD,pIRPWORD int 3 mov eax,pIRP assume eax: ptr _IRP mov [eax].IoStatus.Status,STATUS_SUCCESS mov [eax].IoStatus.Information,0 assume eax:nothing invoke IoCompleteRequest,pIRP,IO_NO_INCREMENT ret MJ_CREATE_CLOSE endp ;--------------------------------------------------------- WRITE_WORK proc pDevWORD, pContWORD local InitStruct:OBJECT_ATTRIBUTES local FileHandleWORD int 3 lea eax,InitStruct sub edx,edx mov (OBJECT_ATTRIBUTES ptr [eax])._Length,sizeof OBJECT_ATTRIBUTES mov (OBJECT_ATTRIBUTES ptr [eax]).ObjectName,offset FilePath mov (OBJECT_ATTRIBUTES ptr [eax]).Attributes,edx mov (OBJECT_ATTRIBUTES ptr [eax]).RootDirectory,edx mov (OBJECT_ATTRIBUTES ptr [eax]).SecurityDescriptor,edx mov (OBJECT_ATTRIBUTES ptr [eax]).SecurityQualityOfService,edx push eax invoke ZwCreateFile,addr FileHandle,FILE_WRITE_DATA,addr InitStruct,esp,0,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ,\ FILE_OPEN_IF,0,0,0 pop edx cmp eax,STATUS_SUCCESS jnz FILE_ERROR mov eax,offset OutBuffer ; mov ebx,dword ptr [eax] ;TRASH sub ebx,ebx ;Какие-либо действия mov eax,ebx ; invoke ZwWriteFile,FileHandle,0,0,0,offset My_status,offset OutBuffer,\ sizeof OutBuffer,offset Lseek,0 invoke ZwClose,FileHandle FILE_ERROR: invoke IoFreeWorkItem,pCont ret WRITE_WORK endp ;--------------------------------------------------------- MJ_CONTROL proc DevObjectWORD,pIRPWORD int 3 invoke IoAllocateWorkItem,eax test eax,eax jz NOT_ENOUGH_RESOURCES invoke IoQueueWorkItem,eax,offset WRITE_WORK,DelayedWorkQueue,eax NOT_ENOUGH_RESOURCES: mov eax,pIRP assume eax:ptr _IRP mov [eax].IoStatus.Status,STATUS_SUCCESS mov [eax].IoStatus.Information,0 assume eax:nothing invoke IoCompleteRequest,pIRP,IO_NO_INCREMENT ret MJ_CONTROL endp ;--------------------------------------------------------- end DriverEntry
Наверное тут: Код (Text): sub ebx,ebx esi, edi, ebx, esp и ebp должны восстанавливаться по выходу из процедур.
С этой программой дошло до смешного... Я уже несколько раз наступал на грабли сохранения регистров esi,edi,ebx в процедурах, которые будет вызывать ОС (callback). Для избежания дальнейших наступлений (на грабли) я повесил на стену табличку: "Сохрани регистры". И вот! месяц назад я ее снял... Видимо еще рано Ошибки найдены и исправлены, их две: 1. В процедуре MJ_CONTROL, после int 3 нужно написать mov eax,DevObject или (что более правильно) сторочку invoke IoAllocateWorkItem,eax заменить на invoke IoAllocateWorkItem,DevObject Эта оплошность возникла при многочисленных перемещениях этого блока кода из процедуры в процедуру. 2. В процедуре WRITE_WORK, блок кода TRASH заключить в Push ebx ... pop ebx ОГРОМНОЕ СПАСИБО Four-F!