Работа драйвера с файлом, контексты

Тема в разделе "WASM.WIN32", создана пользователем netex, 8 янв 2006.

  1. netex

    netex New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2005
    Сообщения:
    114
    Адрес:
    Russia
    Знаю, что просить разобраться в исходнике не прилично, но все-таки посмотрите.



    Цель драйвера: Писать в файл из буфера.



    Основные данные:

    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 DrvObject:lol: WORD,RegPath:lol: WORD



    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 DrvObject:lol: WORD

    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 DeviceObject:lol: WORD,pIRP:lol: WORD



    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 DeviceObject:lol: WORD,pIRP:lol: WORD



    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 pDev:lol: WORD, pCont:lol: WORD



    local InitStruct:OBJECT_ATTRIBUTES

    local FileHandle:lol: WORD



    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 DevObject:lol: WORD,pIRP:lol: WORD



    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
     
  2. netex

    netex New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2005
    Сообщения:
    114
    Адрес:
    Russia
    Кто знает подскажите, очень надо.
     
  3. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Наверное тут:
    Код (Text):
    1. sub ebx,ebx
    esi, edi, ebx, esp и ebp должны восстанавливаться по выходу из процедур.
     
  4. netex

    netex New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2005
    Сообщения:
    114
    Адрес:
    Russia
    С этой программой дошло до смешного...

    Я уже несколько раз наступал на грабли сохранения регистров 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!