Странности с добавлением сервиса в SDT

Тема в разделе "WASM.NT.KERNEL", создана пользователем slesh, 12 сен 2010.

  1. slesh

    slesh New Member

    Публикаций:
    0
    Регистрация:
    6 фев 2009
    Сообщения:
    214
    Появилась задача: добавить новый сервис в SDT. Предполагался план:
    1) получаю кол-во сервисов через MAX = KeServiceDescriptorTable->ServiceLimit
    2) по адресу KeServiceDescriptorTable->ServiceTable[MAX + 1] записываю число MAX + 1
    3) увеличиваю KeServiceDescriptorTable->ServiceLimit
    4) по адресу KeServiceDescriptorTable->ServiceTable[MAX] записываю адрес своей функции

    Второй пункт сделан для того, что подправить странную вещь (наверное какое-то контрольное значение), что после последнего элемента в SDT следует кол-во элементов этой SDT. Если что-то не так с ним сделать то работать ничего не будет.
    И вот после таких дeйствия получаю BSOD
    Вот код.
    Код (Text):
    1. #include <ntddk.h>
    2.  
    3. typedef struct _SYS_SERVICE_TABLE
    4. {
    5.     ULONG*  ServiceTable;
    6.     ULONG   CounterTable;
    7.     ULONG   ServiceLimit;
    8.     void**  ArgumentsTable;
    9. } SYS_SERVICE_TABLE, *PSYS_SERVICE_TABLE;
    10.  
    11. extern PSYS_SERVICE_TABLE KeServiceDescriptorTable;
    12.  
    13. UINT32 MyTestProcID = 0xFFFFFFFF; // если 0xFFFFFFFF значит сервис не был добавлен
    14.  
    15. // безопасным способом записывает ULONG значение по указанному адресу
    16. int SetULONG(void* Addr, ULONG Value)
    17. {
    18.     int ret = 0;
    19.  
    20.     PHYSICAL_ADDRESS PhysicalAddr;
    21.     void* VirtualAddr;
    22.    
    23.     PhysicalAddr = MmGetPhysicalAddress(Addr);
    24.     if (PhysicalAddr.QuadPart)
    25.     {
    26.         VirtualAddr = MmMapIoSpace(PhysicalAddr, 4, 0);
    27.         if (VirtualAddr)
    28.         {
    29.             *(ULONG*)VirtualAddr = Value;
    30.             ret = 1;
    31.             MmUnmapIoSpace(VirtualAddr, 4);
    32.         }
    33.     }
    34.    
    35.     return ret;
    36. }
    37.  
    38. // Добавляет процедуру в SDT
    39. // на входе адрес процедуры
    40. // на выходе номер в SDT. В случае ошибка вернем 0xFFFFFFFF
    41. UINT32 AddMyProcToSdt(void* ProcAddr)
    42. {
    43.     UINT32 ret = 0xFFFFFFFF;
    44.     UINT32 max;
    45.    
    46.     max = KeServiceDescriptorTable->ServiceLimit; // получаем кол-во сервисов
    47.     if (SetULONG(&KeServiceDescriptorTable->ServiceTable[max + 1], max + 1)) // добавим новое контрольное значение
    48.     {
    49.         // увеличиваем кол-во сервисов
    50.         if (SetULONG(&KeServiceDescriptorTable->ServiceLimit, max + 1))
    51.         {
    52.             // Если норм, то прописываем адрес своего сервиса
    53.             if (SetULONG(&KeServiceDescriptorTable->ServiceTable[max], (ULONG)ProcAddr))
    54.             {
    55.                 DbgPrint("Set OK");
    56.                 ret = max; // вернем адрес нашего сервиса
    57.             }
    58.             else // если ошибка добавления адреса сервиса
    59.             {
    60.                 // вернем на место кол-во сервисов
    61.                 SetULONG(&KeServiceDescriptorTable->ServiceLimit, max);
    62.             }
    63.         }
    64.     }
    65.    
    66.     return ret;
    67. }
    68.  
    69. // тестовая функция
    70. NTSTATUS __stdcall MyTestProc(ULONG param)
    71. {
    72.     DbgPrint("MyTestProc");
    73.    
    74.     return STATUS_SUCCESS;
    75. }
    76.  
    77. void DriverUnload(IN PDRIVER_OBJECT DriverObject)
    78. {
    79.     UINT32 max;
    80.    
    81.     DbgPrint("DRV UNLOAD");
    82.  
    83.     if (MyTestProcID != 0xFFFFFFFF) // если добавили удачно всё
    84.     {
    85.         max = KeServiceDescriptorTable->ServiceLimit; // получим кол-во элементов
    86.         if (max - 1 == MyTestProcID) // если больше никто не добавлял свои сервисы
    87.         {
    88.             // пропатчим значение         
    89.             SetULONG(&KeServiceDescriptorTable->ServiceTable[max - 1], max - 1);
    90.             // уменьшим кол-во сервисов
    91.             SetULONG(&KeServiceDescriptorTable->ServiceLimit, max - 1);
    92.         }
    93.     }
    94.        
    95.     return;
    96. }
    97.  
    98.  
    99. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
    100. {
    101.     DbgPrint("DRV LOAD");
    102.  
    103.     DriverObject->DriverUnload = DriverUnload;
    104.    
    105.        
    106.     // добавляем нашу процедуру в sdt
    107.     MyTestProcID = AddMyProcToSdt(MyTestProc);
    108.     if (MyTestProcID != 0xFFFFFFFF) // если добавили удачно
    109.     {
    110.         DbgPrint("ADD OK. MyTestProc ID = %0.8X", MyTestProcID);
    111.     }
    112.    
    113.     return STATUS_SUCCESS;
    114. }
    Всё добавляется нормально, но потом через секунду BSOD вылетает.
     
  2. slesh

    slesh New Member

    Публикаций:
    0
    Регистрация:
    6 фев 2009
    Сообщения:
    214
    При этом, если убрать правку контрольного значения, то всё норм пашет, но при попытки вызвать новый сервис вываливается сообщение STATUS_INVALID_SYSTEM_SERVICE.

    Вообще необходимо добавить сервис в таблицу, неважно куда, главное чтобы его можно было вызвать из юзермода через sysenter
     
  3. Bazhan

    Bazhan Андрей

    Публикаций:
    0
    Регистрация:
    8 янв 2008
    Сообщения:
    71
    Адрес:
    Украина
    BSOD происходит потому что ты затираешь nt!KiArgumentTable
    Код (Text):
    1. kd> dps nt!KeServiceDescriptorTable L4
    2. 8089f7e0  80831b20 nt!KiServiceTable
    3. 8089f7e4  00000000
    4. 8089f7e8  00000128
    5. 8089f7ec  80831fc4 nt!KiArgumentTable
    6. kd> db nt!KiServiceTable+(128+1)*4
    7. 80831fc4  18 20 2c 2c 40 2c 40 44-0c 08 08 18 18 08 04 04  . ,,@,@D........
    8. 80831fd4  0c 10 18 08 08 08 0c 04-08 08 04 04 0c 08 0c 04  ................
    9. 80831fe4  04 20 08 10 0c 14 0c 2c-10 0c 0c 1c 20 10 38 10  . .....,.... .8.
    10. 80831ff4  14 20 24 24 1c 14 10 20-10 34 14 08 0c 08 04 04  . $$... .4......
    11. 80832004  04 04 04 0c 08 28 04 1c-18 08 08 18 0c 18 08 18  .....(..........
    12. 80832014  0c 08 0c 04 10 00 0c 10-28 08 08 10 1c 04 08 0c  ........(.......
    13. 80832024  04 10 08 00 08 04 08 0c-10 28 08 04 10 04 04 0c  .........(......
    14. 80832034  0c 28 04 04 24 28 30 0c-0c 0c 18 0c 0c 0c 0c 30  .(..$(0........0
    p.s. почитай про KeAddSystemServiceTable