DeviceIoControl

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

  1. NEOx

    NEOx New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2003
    Сообщения:
    6
    Адрес:
    Russia
    Я пишу драйвер для дампов процесса, и в ходе написания появился один вопросик.



    Я юзаю такую структурку:



    typedef struct

    {

    // Input

    IN ULONG uProcessID;

    IN ULONG uVirtualAddress;

    IN ULONG uSize;

    // Output

    OUT ULONG uStatus;

    OUT LPVOID lpAllocatedMemory;

    } PT_DUMP_PROCESS_MEMORY;



    (lpAllocatedMemory - выделяю в приложении. Размер=uSize)



    Через DeviceIoControl отсылаю её драйверу. Но он почему-то ничего не возвращает. Но если lpAllocatedMemory сделать статическим (lpAllocatedMemory[255]), то всё Ок. 255 байт пересылаются. Не подскажете где ошибка? Мне нужно именно динамически менять размер lpAllocatedMemory.
     
  2. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Подробнее. Какой метод в/в ты используешь: METHOD_BUFFERED, METHOD_NEITHER...? Драйвер твой? Если ты меняешь размер буфера, как драйвер об этом узнаёт?
     
  3. NEOx

    NEOx New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2003
    Сообщения:
    6
    Адрес:
    Russia
    Драйвер мой. Метод такой:

    #define IOCTL_GET_PROCESS_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS);



    Размер буффера драйвер узнаёт из uSize.



    Вот кусок кода, только тут теперь драйвер сам пишет память на диск (функция SaveBuffer). Ошибок нет.


    Код (Text):
    1.  
    2. switch(pStack->Parameters.DeviceIoControl.IoControlCode)
    3.     {
    4.         case IOCTL_GET_PROCESS_MEMORY:
    5.         {
    6.             // Install SEH
    7.             __try
    8.             {
    9.                 // Get Process ID
    10.                 uPID = ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uProcessID;
    11.                 // Get Virtual Address
    12.                 uVirtualAddress = ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uVirtualAddress;
    13.                 // Get size
    14.                 uSize = ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uSize;
    15.  
    16.                 DbgPrint("DeviceIoControl: uPID=0x%0.8X uVirtualAddress=0x%0.8X uSize=0x%0.8X OutSize=%d\n",
    17.                                                             uPID, uVirtualAddress, uSize, out_size);
    18.  
    19.                 ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uStatus = 0;
    20.  
    21.                 if(NT_SUCCESS(PsLookupProcessByProcessId((DWORD)uPID, &eprocess)))
    22.                 {
    23.                     KeAttachProcess(eprocess);
    24.  
    25.                     DbgPrint("PEToolsDrvDevice: RtlCopyMemory\n");
    26.  
    27.                     LPVOID lpBuffer = ExAllocatePool(NonPagedPool, uSize);
    28.                     RtlCopyMemory(lpBuffer,
    29.                         (const void *)((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uVirtualAddress,
    30.                         uSize);
    31.  
    32.                     SaveBuffer("\\??\\C:\\dump.bin", lpBuffer, uSize);
    33.  
    34.                     Irp->IoStatus.Information = sizeof(PT_DUMP_PROCESS_MEMORY);
    35.  
    36.                     ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uStatus = 1;
    37.                 }
    38.  
    39.                 KeDetachProcess();
    40.                 ObDereferenceObject((void *)eprocess);
    41.             }
    42.             __except(EXCEPTION_EXECUTE_HANDLER)
    43.             {
    44.                 KeDetachProcess();
    45.                 ObDereferenceObject((void *)eprocess);
    46.  
    47.                 DbgPrint("DeviceIoControl: Access violation\n");
    48.                 ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uStatus = 0;
    49.             }
    50.             break;
    51.  


    А до этого, я просто копировал память при помощи RtlCopyMemory:



    RtlCopyMemory((const void *)((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->lpAllocatedMemory,

    (const void *)((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uVirtualAddress, uSize);



    Но так ничего не копировалось был Access Violation.
     
  4. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Понятно. ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->lpAllocatedMemory - это указатель на буфер в юзерном адресном пространстве твоего! процесса. Когда ты делаешь KeAttachProcess, ты отключаешься от своего юзерного адресного пространства и пытаешься копировать в несуществующий буфер в приаттаченом процессе. Тут двы выхода: лочить/отображать свой буфер в ядро, для того чтобы он был доступен в любом контексте или выделять временный буфер в ядре, аттачится, копировать во временный буфер, детачится и копировать из временного буфера к себе в юзерный буфер. И в вышеприведенном коде у тя как минимум четыре явных бага и несколько потенциальных ;) и NonPagedPool - это лишнее. Я бы переписАл его так (дебужные мессаги убрал чтоб не мешали и сам мог где-нить ошибиться, ибо некогда):




    Код (Text):
    1. case IOCTL_GET_PROCESS_MEMORY:
    2.  
    3.     BOOLEAN fOK = FALSE;
    4.  
    5.     uPID = ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uProcessID;
    6.  
    7.     uVirtualAddress = ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uVirtualAddress;
    8.  
    9.     uSize = ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uSize;
    10.  
    11.     ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uStatus = 0;
    12.  
    13.     if ( NT_SUCCESS(PsLookupProcessByProcessId((DWORD)uPID, &eprocess)) ) {
    14.  
    15.         LPVOID lpBuffer = ExAllocatePool( PagedPool, uSize );
    16.  
    17.         if ( NULL != lpBuffer ) {
    18.  
    19.             KeAttachProcess( eprocess );
    20.  
    21.             __try {
    22.            
    23.                 ProbeForRead(
    24.                         uVirtualAddress,
    25.                         uSize,
    26.                         sizeof(UCHAR) );  
    27.  
    28.                 RtlCopyMemory( lpBuffer, uVirtualAddress, uSize );
    29.  
    30.                 fOK = TRUE;
    31.  
    32.             }
    33.             __except(EXCEPTION_EXECUTE_HANDLER) {
    34.                
    35.                 Status = GetExceptionCode();
    36.             }
    37.  
    38.             KeDetachProcess();
    39.  
    40.             if ( fOK  ) {
    41.  
    42.                 __try {
    43.            
    44.                     ProbeForWrite(
    45.                             ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->lpAllocatedMemory,
    46.                             uSize,
    47.                             sizeof(UCHAR) );  
    48.  
    49.                     RtlCopyMemory(
    50.                             ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->lpAllocatedMemory,
    51.                             lpBuffer,
    52.                             uSize );
    53.  
    54.                     Irp->IoStatus.Information = sizeof(PT_DUMP_PROCESS_MEMORY);
    55.  
    56.                     ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->uStatus = 1;
    57.  
    58.                 }
    59.                 __except(EXCEPTION_EXECUTE_HANDLER) {
    60.                    
    61.                     Status = GetExceptionCode();
    62.                 }
    63.             }
    64.  
    65.             ExFreePool( lpBuffer );      
    66.         }
    67.  
    68.         ObDereferenceObject( (void *) eprocess );
    69.     }
    70.  
    71.     break;
    72.  






    Или, как я говорил, отобрази свой буфер в ядро. Так он буде доступен в любом контексте.


    Код (Text):
    1.  
    2. PMDL mdl = NULL;
    3.  
    4. mdl = IoAllocateMdl( ((PT_DUMP_PROCESS_MEMORY *)pWorkBuffer)->lpAllocatedMemory, uSize,  FALSE, TRUE, NULL );
    5. MmProbeAndLockPages( mdl, UserMode, IoWriteAccess );
    6. lpBuffer = MmGetSystemAddressForMdlSafe( mdl, NormalPagePriority );
    7.  
     
  5. NEOx

    NEOx New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2003
    Сообщения:
    6
    Адрес:
    Russia
    Всё, теперь понятно. Огромное спасибо.
     
  6. NEOx

    NEOx New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2003
    Сообщения:
    6
    Адрес:
    Russia
    Проверил, работает так как я и хотел. Но появился ещё один вопросик. Как можно сдампить "NO ACCESS/NONE" регионы? Догадываюсь, что это делается как в usermode (OpenPorcess/VirtualProctectEx потом дамп). Но для драйвера я нашёл только аналог OpenProcess :dntknw: Или как-то по другому?
     
  7. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Вот с этим делом в ядре большие проблемы, в том смысле, что ни хрена не экспортируется. Единственная экспортируемая функция - это MmProtectMdlSystemAddress, да и то только для ядерных адресов и для ХР+.



    Можешь попробовать связку ObOpenObjectByPointer/ZwProtectVirtualMemory, но придется найти точку входа ZwProtectVirtualMemory. Либо попытаться делать то, что делает эта функция. А сделать надо до смешного мало:


    Код (Text):
    1. MiProtectVirtualMemory( Process, &Base, &Size, NewProtect, &OldProtect );
    MiProtectVirtualMemory, естественно, тоже не экспортируется.