Проблемы с написанием драйвера

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by slesh, 25 Sep 2007.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Вот сталкнулся с такой проблемой:
    Програма должна постоянно считывать
    через из драйвера через:

    ReadFile струткуру следующего типа:

    typedef struct _TMySTRUC // структура описывающая запрос к драйверу
    {
    HANDLE z1;
    HANDLE z2;
    } TMySTRUC, *PMySTRUC;

    ВОт не могу написать как именно осуществить запись со стороны драйвера.
    к примеру:

    Code:
     TMySTRUC mystruc;
     mystruc->z1=11111;
     mystruc->z2=22222;
    
     irpStack = IoGetCurrentIrpStackLocation (Irp);
     if (irpStack->MajorFunction == IRP_MJ_READ)
     {
    ВОт что сюда вставить, чтобы передаться струкруру
    mystruc?????
     }
    
     Irp->IoStatus.Status = STATUS_SUCCESS;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
     return STATUS_SUCCESS;
    
    
    Еще чуть запустался с IRP_MJ_READ и IRP_MJ_WRITE

    КАк я понял irpStack->MajorFunction == IRP_MJ_READ
    будет тогда когда програма будет читать данные из драйвера т.е. readfile, а IRP_MJ_WRITE - когда будет писать чтото драйверу.
    Перебрал кучу документаций так толком и не понял как осуществить чтение и запись.
     
  2. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,118
    Reputations:
    1,139
    какой тип ввода-вывода?
    1) если buffered (DO_BUFFERED_IO), тогда Irp->AssotiatedIrp.SystemBuffer указывает на системный буффер, который потом будет скопирован в пользовательский выходной (если это IRP_MJ_READ) или в который уже скопирован входной (если это IRP_MJ_WRITE)

    другие типы тебе пока не нужны.. запутаешься нафиг.
    тебе нужно лишь проверить длину буффера и скопировать туда структуру
     
    1 person likes this.
  3. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    Чтото начал делать в этоге при копировании идет BSOD
    Вообще драйвер должен перехватывать запуск процессов.
    И потом по требованию возвращать PID и PARENT последнего запущенного процесса.
    Код функции обработчика:
    Code:
    if (irpStack->MajorFunction == IRP_MJ_READ)
     {
       DPRINT("READ");
       if (irpStack->Parameters.Read.Length < 8)
        {
    	    DPRINT("LENGTH < 8");
            Irp->IoStatus.Status = status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information  = 0;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
            return status;
        } else
    	{
              DPRINT("LENGTH OK");	
    Еcли раскоментировать, то BSOD >>>	 //RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &RUNPROC, 8);
    
    
     	 Irp->IoStatus.Status = status = STATUS_SUCCESS;
      	 IoCompleteRequest (Irp, IO_NO_INCREMENT);
          return status;
    	}
     }
    
    
    где
    TRUNPROC RUNPROC
    typedef struct _TRUNPROC
    {
    HANDLE parent;
    HANDLE PID;
    } TRUNPROC, *PRUNPROC;


    И вот вопрос еще один. Как мне получать то, что выводится через DbgPrint?
    Юзаю WinDbg. Т.е. я запускаю через него прогу, которая общается с драйвером, но почемуто сообщения от DbgPrint на экране они не появляются :(
     
  4. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    Путаешь. Для просмотра сообщений от DbgPrint тебе нужен DebugView от Sysinternals.
    Сейчас посмотрю код.
     
    2 people like this.
  5. Ky3bMu4

    Ky3bMu4 Elder - Старейшина

    Joined:
    3 Feb 2007
    Messages:
    487
    Likes Received:
    284
    Reputations:
    42
    Если я не ошибаюсь, то для передачи информации драйвер<->программа драйвер должен создать устройство, через которое будет передаваться инфа. Вот тебе:
    http://www.wasm.ru/article.php?article=apihook_3 (см.Взаимодействие драйвера с приложением)
    И вот: http://wasm.ru/article.php?article=drvw2k04
     
  6. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    не с устройсвом всё ок. всё создано отлично. И пашет отлично. А вот тока как именно драйвер должен передать ответ - хз.
    На счет васма - процел всё - толком там не описано.
     
  7. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    Да сделай ты через DeviceIoControl, проще будет, один из аргументов функции - буфер для обратного ответа. Будешь передавать драйверу IOCTL коды.
    Code:
    #define IOCTL_GETPID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x01, \
    	METHOD_BUFFERED, \
    	FILE_READ_DATA | FILE_WRITE_DATA)
    
    А драйвер будет обрабатывать их.
    Code:
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyIrp;
    ...
    NTSTATUS MyIrp(IN PDEVICE_OBJECT dev, IN PIRP pirp)
    {
    ...
    switch (ioctl_code)
    	{
    	case IOCTL_GETPID:
    		GetPid();
    		break;
    	default:	
    		ns = STATUS_INVALID_DEVICE_REQUEST;
    	}
    ...
    
     
  8. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    с DbgPrint разобрался +

    ----------
    Суть в том, что я юзаю DeviceIoControl для чуть другйо функции.
    а именно - защита процесса. Чтобы его не могли выкинуть стандартными методами.
    у меня он заюзан вот так:
    if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
    ProtectedPid = (HANDLE)irpStack->Parameters.DeviceIoControl.IoControlCode;
     
    #8 slesh, 27 Sep 2007
    Last edited: 27 Sep 2007
  9. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 Ni0x В принципе можно былобы и сделать как ты говоришь, но тогда таже проблема - чтение и запись.
     
  10. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    И в чем проблема использовать DeviceIoControl для всего?
     
  11. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    переписал на DeviceIoControl
    но чуть не допер как получить параметр.
    сделал вот что. но тут чегото не хватает. А именно знаний в С:
    Code:
    if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) 
     {
      switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
       {
    	case 0x12345:
    	    if (irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(HANDLE)) 
    		{
    ------> Вот тут я туплю. Как правильно сделать? ProtectedPid=Irp->AssociatedIrp.SystemBuffer;
    				DPRINT("PID= %d",ProtectedPid);
    		}
    		break;
    		
    	default: status = STATUS_INVALID_DEVICE_REQUEST;
    	}
     
     }
    
    
     
  12. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    Тут указаны примеры для разных методов:
    Code:
    stack = IoGetCurrentlrpStackLocation (Irp); 
    switch (pIrpStack->MajorFunction) 
    {
    case IRP_MJ_CREATE: case IRP_MJ_CLOSE: break;
    case IRP_MJ_DEVICE_CONTROL:
    switch (stack->Parameters.DeviceloControl.loControlCode) 
    { 
    [b]case IOCTL_MY_BUFFERED:[/b]
    InBuffer = Irp->AssociatedIrp.SystemBuffer; 
    InLength =  stack->Parameters.DeviceloControl.InputBuffer.Length; 
    OutBuffer = Irp->AssociatedIrp.SystemBuffer; 
    OutLength = stack->Parameters.DeviceloControl.OutputBufferLength; 
    [b]case IOCTL_MY_IN_DIRECT:[/b]
    //OutBuffer доступен только для чтения 
    InBuffer = Irp->AssociatedIrp.SystemBuffer; 
    InLength = stack->Parameters.DeviceloControl.InputBufferLength; 
    OutBuffer = MmGetSystemAddressForMdl( Irp->MdlAddress );
    OutLength = stack->Parameters.DeviceloControl.OutputBufferLength; 
    break; 
    [b]case IOCTL_MY_OUT_DIRECT:[/b]
    //OutBuffer доступен для чтения/записи 
    InBuffer = Irp->AssociatedIrp.SystemBuffer; 
    InLength = stack->Parameters.DeviceloControl.InputBufferLength; 
    OutBuffer = MmGetSystemAddressForMdl( Irp->MdlAddress);
    OutLength = stack->Parameters.DeviceloControl.OutputBufferLength; break;
    [b]case IOCTL_MY_NEITHER:[/b]
    InBuffer = irpStack->Parameters.DeviceloControl.TypeInputBuffer;
    InLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; 
    OutBuffer = Irp->UserBuffer;
    OutLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; 
    break;
    
    Также обязательно прочитай:
     
    #12 Ni0x, 28 Sep 2007
    Last edited: 28 Sep 2007
  13. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,118
    Reputations:
    1,139
    Я тебя умоляю, если ты не шаришь в теме, не пиши
     
    2 people like this.
  14. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    подскажите что я делаю не так. почему BSOD?
    При установке ProtectedPid - ставится всё нормально и пашет отлично.
    А при чтении его - BSOD. читаю через

    PID,TrId:dword;
    DeviceIoControl(hDriver, $23456, nil, 0, @PID, 4, TrId, nil);

    Вот код обработчика
    Code:
    HANDLE ProtectedPid;
    
    NTSTATUS DriverDispatcher(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
    {
     NTSTATUS status;
     PIO_STACK_LOCATION irpStack;
     irpStack = IoGetCurrentIrpStackLocation (Irp);
     
    if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) 
     {
      switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
       {
    	case 0x12345:
    	    if (irpStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(HANDLE)) 
    		{
    		       
    				ProtectedPid=*(HANDLE *)Irp->AssociatedIrp.SystemBuffer;
    				DPRINT("PID= %d",ProtectedPid);
    	 	}
    		break;
    	case 0x23456:
    	if (irpStack->Parameters.Read.Length < 4)
        {
    	    DPRINT("LENGTH < 4");
            Irp->IoStatus.Status = status = STATUS_BUFFER_TOO_SMALL;
            Irp->IoStatus.Information  = 0;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
            return status;
        } 
    	 else
    	{
         DPRINT("LENGTH OK");	
         Irp->IoStatus.Information  = 4;
    // чтото тут я не мойму как реализовать.
    	 *(HANDLE *)Irp->AssociatedIrp.SystemBuffer=ProtectedPid;
    	 Irp->IoStatus.Status = status = STATUS_SUCCESS;
      	 IoCompleteRequest (Irp, IO_NO_INCREMENT);
         return status;
    	}
    	break;
    	
    	default: status = STATUS_INVALID_DEVICE_REQUEST;
    	}
     
     }
    
    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    
     return status;
     }
    
     
  15. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,118
    Reputations:
    1,139
    Кто тебе сказал что ты можешь какие угодно io control code задавать?
    Юзай макрос IOCTL_CODE()
    Самое главное - тип ввода-вывода (младшие 2 бита), у тебя видно тип не buffered во втором случае (да и в первом тоже)
     
  16. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 _Great_ Ты имеешь ввиду что именно через CTL_CODE и истанавливаются прва на запись, чтение и мето ввода-вывод?

    Вот еще сталкнулся с такой проблемой. Иногда почемуто програма не может связаться с драйвером. Драйвер у меня как сервис. Поэтому я делаю:
    net stop MyDRV
    потом перекомпиливаю драйвер
    затем: net start MyDRV
    Все пахало нормально. но потом через несколько перезагрузок почемуто из програмы не возможно связаться с драйвером. т.е.
    CreateFile('\\.\MyDRVS', GENERIC_ALL, 0, nil, OPEN_EXISTING, 0, 0);
    возвращает INVALID_HANDLE_VALUE
    Хотя драйвер пашет нормально - по дебаговым сообщением видно что создания процессов перехватываются. НО связи по сей час нет. уже перезагружался пару раз - дохлое дело.

    Также заметил один интерестный факт. Вроде все програмы и DLL ки виндовые отображаются на память, а драйвера получается что нет? потому что при запущенном драйвере можно спакойно удалить файл драйвара.
     
    #16 slesh, 28 Sep 2007
    Last edited: 28 Sep 2007
  17. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    А самому лень посмотреть?
    winioctl.h
    Code:
    #define CTL_CODE( DeviceType, Function, Method, Access ) (                 
        ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) 
    )
    
     
  18. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    А тебе драйвера то не рано ещё писать? ; )
    И DLL и EXE любую можно удалить без проблем как и драйвер.
    Просто после загрузки драйвера винда не лочит попытки удаления его файла на диске, а для user-mode модулей - лочит. Т.е. файл остается открытым для user-mode модулей и закрывается сразу после загрузки для драйверов (а нахер ему быть открытым).
    Но, ИМХО, одно из двух писал НЕ ты. Либо "драйвер не отображается на память", либо сам драйвер ; )

    Учитесь как надо кодить
    [​IMG]
    всё хотел кому-нибудь показать чтоб оценили
    гыгыг
     
    #18 KEZ, 29 Sep 2007
    Last edited: 29 Sep 2007
    2 people like this.
  19. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,118
    Reputations:
    1,139
    Некоторые биты ио контрол кода служебные. А ты рандомно задаешь все число. Поэтому и глюки

    GetLastError() ?
     
  20. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 _Great_ спасибо за разъяснение. Переписал все через CTL_CODE.
    Но всеже также осталась проблема с доступом к драйверу.
    GetLastError дает код ошибки - 317