ZwWriteFile & Notification CallBack

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

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Есть вот такой код:


    Код (Text):
    1. WriteToFile proc uses ebx lpAppendData: PTR ANSI_STRING
    2.     LOCAL oa            :OBJECT_ATTRIBUTES
    3.     LOCAL sb            :IO_STATUS_BLOCK
    4.     LOCAL hFile         :DWORD
    5.     LOCAL dataLen       :DWORD
    6.  
    7.     InitializeObjectAttributes addr oa, addr szFileName, OBJ_CASE_INSENSITIVE or OBJ_KERNEL_HANDLE, NULL, NULL
    8.     invoke  ZwOpenFile, addr hFile, FILE_APPEND_DATA or SYNCHRONIZE, addr oa, addr sb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT
    9.     .if     (eax == STATUS_SUCCESS)
    10.         mov     ebx, lpAppendData
    11.         add     ebx,4
    12.         mov     ebx,[ebx]
    13.         invoke  strlen,ebx
    14.         mov     dataLen,eax
    15.         invoke  ZwWriteFile, hFile, NULL, NULL, NULL, addr sb, ebx, dataLen, NULL, NULL
    16.         .if     (eax == STATUS_SUCCESS)
    17.             invoke DbgPrint, $CTA0("Success")
    18.         .else
    19.             invoke DbgPrint, $CTA0("Fail")
    20.         .endif
    21.         invoke  ZwClose, hFile
    22.     .else
    23.         invoke DbgPrint, $CTA0("Error: %08X\n"), eax
    24.     .endif
    25.     invoke DbgPrint, $CTA0("End of write")
    26.     ret
    27. WriteToFile endp
    28.  
    29.  
    30. ;-------- Notify Callback ------------
    31.     invoke  WriteToFile, addr a_string
    32.  




    Callback получает сообщение о создании процесса. Из него вызывается процедура записи в файл.

    Если процессы запускать и завершать до запуска другого процесса, все работает (в файл пишется).

    Если запустить процесс, и не закрывая его, запустить какой-нибудь другой процесс (т.е. предыдущий процесс ещё не закрыт), система уходит в перезагрузку.

    Путем комментирования определил, что перезагрузку вызывает ZwWriteFile. Какая разница, завершился предыдущий процесс или нет?

    Если вместо ZwWriteFile выводить строку через DbgPrint - никаких проблем.

    Предыдущий вызов WriteToFile завершается успешно, строки Success и End of write выводятся. Т.е. с синхронностью проблем нет.

    В чем может быть дело?

    Спасибо.
     
  2. MegaZu

    MegaZu New Member

    Публикаций:
    0
    Регистрация:
    22 июл 2005
    Сообщения:
    290
    Лучше зделай хендл файла глобальним , чтоб каждый раз не открывать/закрывать ....



    Работу с лог файлом я делаю так:



    HANDLE hFileHandle;

    IO_STATUS_BLOCK iostatus;



    void InitLogFile(IN PCWSTR strLogFile)

    {

    NTSTATUS Status;

    OBJECT_ATTRIBUTES ObjAttr;

    UNICODE_STRING strFileName;

    hFileHandle = NULL;

    DPRINT("Initializing log file...");

    RtlInitUnicodeString(&strFileName,strLogFile);

    InitializeObjectAttributes(&ObjAttr,&strFileName,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,NULL,NULL);

    Status = ZwCreateFile(&hFileHandle,GENERIC_WRITE | SYNCHRONIZE,&ObjAttr,&iostatus,0,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_WRITE,FILE_OPEN_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0);

    if (NT_SUCCESS(Status))DPRINT("ok\n");

    else DPRINT("failed\n");

    }



    void CloseLogFile()

    {

    DPRINT("Closing log file\n");

    if (!hFileHandle) return;

    ZwClose(hFileHandle);

    }



    void WriteLog(IN char* Buff)

    {

    NTSTATUS Status;

    FILE_STANDARD_INFORMATION fileInfo;

    if (!hFileHandle) return;

    Status = ZwQueryInformationFile(hFileHandle,&iostatus,&fileInfo,sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation);

    if (NT_SUCCESS(Status))

    {

    LARGE_INTEGER ByteOffset = fileInfo.EndOfFile;

    Status = ZwWriteFile(hFileHandle,NULL,NULL,NULL,&iostatus,Buff,strlen(Buff),&ByteOffset,NULL);

    }

    }



    [add]



    Ты вообще под дебагом проганял этот код при запуске второго процесса ?
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Держать глобально открытый - тоже пробовал - там вообще даже одновременно один процесс запустить редко удается. Например запуск notepad - 100% перезагрузка.

    Может дело в том, что callback вызывается в контексте запускаемого процесса?
     
  4. MegaZu

    MegaZu New Member

    Публикаций:
    0
    Регистрация:
    22 июл 2005
    Сообщения:
    290


    Воу!!! Ты значит где-то намудрил :)
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Уже начинаю с бубном плясать - обрамил код вызова ZwWriteFile такими вот рюшечками от Four-F:


    Код (Text):
    1.         _try
    2.             invoke  ZwWriteFile, hLogFile, NULL, NULL, NULL, addr sb, ebx, dataLen, NULL, NULL
    3.             .if     (eax == STATUS_SUCCESS)
    4.                 invoke DbgPrint, $CTA0("%s"), ebx
    5.             .else
    6.                 invoke DbgPrint, $CTA0("Can't append data: %08X\n"), eax
    7.             .endif
    8.         _finally




    Бесполезно. Перегружается по-прежнему.
     
  6. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Вроде нашёл: RtlUnicodeStringToAnsiString,...,...,TRUE выделяет буфер и транслирует в него юникод-строку. Если к этому буферу делать strcat, то ZwWriteFile этот буфер переварить не может. В то же время DbgPrint спокойно выводит этот буфер (что и ввело в заблуждение). Поэтому содержимое буфера от RtlUnicodeStringToAnsiString надо сначала скопировать в промежуточный буфер достаточной длины, и затем только strcat и ZwWriteFile с этим промежуточным буфером
     
  7. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Весь смысл ANSI_STRING/UNICODE_STRING в том, что они всегда несут длину строки и всего буфера в себе. Зачем strlen?



    <font color="gray][ cresta</font><!--color--><font color="gray]: Если к этому буферу делать strcat, то ZwWriteFile этот буфер переварить не может. ]</font><!--color-->



    А ты обновил ANSI_STRING.Length и не вышла ли длина строки за пределы ANSI_STRING.MaximumLength?





    strlen, strcat и тому подобную CRT хрень лучше вообще в ядре не юзать. Для аппенда есть RtlAppendStringToString.



    ЗЫ: И с моими рюшечками поаккурантее. Они кривенькие http://www.wasm.ru/forum/index.php?action=vthread&forum=4&topic=11025
     
  8. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257




    В этом и была ошибка:MaximumLength оставался прежним. А strlen нужен потому, что к строке может добавляться другая стока произвольной длины (что вкупе с неизменением MaximumLength и приводило к ошибке), заранее неизвестно, сколько будет результирующая длина.

    За ссылку спасибо.
     
  9. CARDINAL

    CARDINAL Member

    Публикаций:
    0
    Регистрация:
    23 янв 2004
    Сообщения:
    551
    Адрес:
    Moscow
    cresta

    а ты не пробовал запустить рядом системный ядерный поток и пусть он за тебя сам пишет, или рабочие потоки создать и пусть они за тебя там в файл пишут, зачем тратить драгоценное время на все дела непосредственно в контексте процедуры нотификации ?
     
  10. CARDINAL

    CARDINAL Member

    Публикаций:
    0
    Регистрация:
    23 янв 2004
    Сообщения:
    551
    Адрес:
    Moscow
    вопрос в другом мне кажется, твоя процедура нотификации, вызываясь повторно, снова использует твой уникодстринг, который был до этого уже инициализирован прежним вызовом. и ты пытаешься повторно использовать её. Пересмотри алгоритм
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    CARDINAL





    В смысле ZwCreateThread? Если о нем речь, то я после отладки уберу всю работу с файлом в отдельный поток.



    Буфер для юникода выделяется через ExAllocatePool, затем invoke RtlUnicodeStringToAnsiString, addr as, addr us, FALSE, и затем ExFreePool. Все освобождается. А для анси - буфер на стеке, освобождать не надо.