Корректная модификация/блокирование данных + pIrp->AssociatedIrp.SystemBuffer

Тема в разделе "WASM.WIN32", создана пользователем ksu_ant, 7 ноя 2005.

  1. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Здравствуйте!

    Я пишу драйвер-фильтр, взаимодействующий с некоторым оборудованием. Его задача - мониторить канал передачи данных к этому оборудованию и блокировать определенные сигналы (команды), либо заменять их другими.

    Функции мониторинга у меня есть, но, так как я только начинаю осваивать разработку драйверов, я не могу правильно вмешаться в пересылку данных.

    Вот что у меня есть.



    PMY_DATA pMYData = NULL;

    ...

    //Данные при буферизованном вводе-выводе

    pMYData->pIrp->AssociatedIrp.SystemBuffer

    //Данные при прямом вводе-выводе

    MmGetSystemAddressForMdlSafe(pMYData->pIrp->MdlAddress, NormalPagePriority)



    После анализа данных вызывается следующий код (одинаковый для обоих типов I/O):

    PDEVICE_EXTENSION pdevex = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;



    PIRP pIrp = pMYData->pIrp;



    IoFreeWorkItem(pMYData->pWorkItem);

    ExFreeToNPagedLookasideList(&pdevex->MemListWork, pMYData);

    if (pIrp->PendingReturned)

    IoMarkIrpPending(pIrp);

    IoReleaseRemoveLock(&pdevex->RemoveLock, pIrp);

    IoCompleteRequest(pMYData->pIrp, IO_NO_INCREMENT);

    Если, при буферизованном I/O я делаю так:

    pMYData->pIrp->AssociatedIrp.SystemBuffer=NULL;

    то появляется BSoD.

    При прямом - вообще не знаю как воздействовать на данные.

    Т.е. необходимо сделать следующее:

    если в потоке данных встречается "Sample Data", надо заменить это на "Other Data", или блокировать (т.е. чтобы IRP "пропал" правильно, без всяких ошибок).

    Заранее благодарен за помощь.
     
  2. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    Если не ошибаюсь, перед IoCompleteRequest должна вызываться ф-ция, которая передаёт IRP следующему драйверу в цепочке. Значит чтобы его не пропустить надо просто её не вызывать. Н-р в моём firewall вызывается:
    Код (Text):
    1. ;----------------------------
    2.         .if [edi].EnableFilter
    3.             invoke FltFilterSendPacket, edi, esi, FALSE
    4.             .if eax==DROP_PACKET
    5. ifdef DBG
    6.                invoke DbgPrint, $CTA0("Send packet DROPED\n")
    7. endif
    8.                 NdisMSendCompleteM [edi].MiniportHandle, esi, NDIS_STATUS_SUCCESS
    9.                 jmp Continue
    10.             .endif
    11.         .endif
    12. ifdef DBG
    13.        invoke DbgPrint, $CTA0("Send packet ALLOWED\n")
    14. endif
    15. ;----------------------------


    Получается пакет как бы прошёл (так сказал драйвер), но дальше он его не пропустил.

    И не надо вызывать ExFreeToN.... иначе BSOD :) этим занимается ОСь - уничтожением пакета IRP



    Гениально ! :))) Это же системный буфер...

    Да, и ещё модифицировать его (содержимое буфера) можно без проблем, если не изменяется длина, иначе надо менять длину буфера
     
  3. LuckyDevil

    LuckyDevil New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2005
    Сообщения:
    278
    Адрес:
    Uzbekistan
    ksu_ant, замечу сразу я не профессионал в этом деле, так что сильно не бейти. Но свои 5 копеек вставлю.

    На сколько я понял тебе надо подменять чужие данные на свои, в этом случе тебе следует создавать свой IRP и посылать ниже стоящим драйверам, ждать результат обработки и уже после удалить его и восстанавливать оригенальный IRP пометить его как обработанный, и все.

    Либо можно использовать текущий IRP, подменить буфер (I\O), опять же ждать результат обработки, после высободить выделенную память и восстановть прежнии данные буфера (I\O) IRP, пометить IRP как обработанный.



    Сумбур,но это дело я себе так представляю.
     
  4. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Спасибо большое всем.

    Вроде бы я понял как можно правильно организовать "пропадание" IRP, но если кто-то имеет работающий код для правки IRP, пожалуйста, напишите.
     
  5. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Здравствуйте!

    Возвращаясь к теме.

    Мне удалось блокировать пересылку команд на устройство, но, дело в том, что при такой блокировке программа, посылающая команды, "зависает".

    Я думаю, что это из-за неправильной функции запрета обмена.

    Вот как я ее сделал:

    Диспетчерская ф-я запроса I/O

    NTSTATUS ReadWrite(

    IN PDEVICE_OBJECT pDeviceObj,

    IN PIRP pIrp

    )

    {

    PDEVICE_EXTENSION pdevex = (PDEVICE_EXTENSION) pDeviceObj->DeviceExtension;

    NTSTATUS status = STATUS_SUCCESS;

    if (...) goto Complete;

    IoCallDriver(...);

    Complete;

    MyCompleteRequest(pIrp, status, 0);

    return status;

    }



    NTSTATUS MyCompleteRequest(

    IN PIRP pIrp,

    IN NTSTATUS status,

    IN ULONG_PTR info

    )

    {

    pIrp->IoStatus.Status = status;

    pIrp->IoStatus.Information = info;

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return status;

    }

    Не могли бы Вы посоветовать, как мне правильно вернуть в систему IRP (без всяких ошибок прикладных программ), не пересылая его нижележащим драйверам (сделать правильное "исчезновение" IRP). Если не трудно, скажите, пожалуйста, какая ошибка содержится в этом коде.

    Заранее благодарен за внимание.
     
  6. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    А почему MyCompleteRequest(pIrp, status, 0); Разве чтение/запись 0-ём заканчивается ? Он же берётся из IRP если всё Ок !
     
  7. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Я правильно Вас понял, что это - MyCompleteRequest(pIrp, status, 0); надо заменить на

    MyCompleteRequest(pIrp, status, pIrp->IoStatus.Information);

    или, что аналогично, просто не выполнять pIrp->IoStatus.Information = info; в функции MyCompleteRequest (pIrp->IoStatus.Information в этом случае не будет изменено)?

    Или необходимо сделать как-то по-другому.

    Извините за назойливость, просто очень хочется разобраться в вопросе.
     
  8. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    Собственно, да еcли IoCallDriver возвращает Ок Приблизительно так
    Код (Text):
    1. NTSTATUS ReadWrite(IN PDEVICE_OBJECT pDeviceObj,IN PIRP pIrp)
    2. {
    3.   PDEVICE_EXTENSION pdevex = (PDEVICE_EXTENSION) pDeviceObj->DeviceExtension;
    4.   NTSTATUS status = STATUS_SUCCESS;
    5.   ULONG inform = pIrp->IoStatus.Information;
    6.   if (...) goto Complete;
    7.   status = IoCallDriver(...);
    8. Complete;
    9.   MyCompleteRequest(pIrp, status, inform);
    10.   return status;
    11. }
    12.  
    13. NTSTATUS MyCompleteRequest(IN PIRP pIrp, IN NTSTATUS status, IN ULONG_PTR info)
    14. {
    15.   pIrp->IoStatus.Status = status;
    16.   pIrp->IoStatus.Information = info;
    17.   IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    18.   return status;
    19. }


    Только это не очень красиво в смысле кода :dntknw:
     
  9. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Но, так как IoCallDriver в условном случае не вызывается, то можно "внаглую" присвоить status = STATUS_SUCCESS и направить это в функцию завершения?

    Просто я сейчас не могу проверить код (жалко рабочий компьютер, если что не так, - ОС установлена одна, не хочу восстанавливать), дома две системы, так что есть возможность резервно запуститься и подправить - вечером проверю.



    >>

    Только это не очень красиво в смысле кода :dntknw:



    Почему? Вроде все логично :derisive:
     
  10. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    О красоте потом :) Поставь VMWare и на ней ставь экперименты, по началу я даже исходники терял от BSOD, когда надоело - поставил VMWare и нет проблем :))
     
  11. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Спасибо :)
     
  12. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Спасибо, SteelRat, у меня все получилось!
     
  13. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
  14. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
  15. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
  16. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    Посмотрим...
     
  17. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    Поробуй выкинуть код в неподкачиваемый пул. Если это драйвер, что ему делать на диске ?
     
  18. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    to SteelRat:

    >>Поробуй выкинуть код в неподкачиваемый пул. Если это драйвер, что ему делать на диске ?



    Не подскажете, где об этом можно почитать или взять примеры кода? (В смысле, чтобы понять).
     
  19. ksu_ant

    ksu_ant New Member

    Публикаций:
    0
    Регистрация:
    28 сен 2005
    Сообщения:
    273
    Я правильно понял, что эту тему описывает Four-F в 5 части своего цикла статей о драйверах? Или там не совсем то, что в данном случае необходимо.
     
  20. SteelRat

    SteelRat New Member

    Публикаций:
    0
    Регистрация:
    26 авг 2004
    Сообщения:
    409
    Ну, читать Four-F (это как "Капиталъ" от Маркса во времена "застоя")

    #pragma CODE_PAGED, если не ошибаюсь, выкидывает код в подкачиваемый пул. Если твоя процедура GeneralCompletion вызывется (но необязательно) на DISPATH_LEVEL, и будет на диске, то BSOD :) Одна ОСь это "вкурит", а друга нет.