BSOD && ZwQuerySystemInformation

Тема в разделе "WASM.NT.KERNEL", создана пользователем valix7, 25 авг 2007.

  1. valix7

    valix7 New Member

    Публикаций:
    0
    Регистрация:
    31 окт 2006
    Сообщения:
    143
    Подскажите плз почему сразу после старта драйвера появляется BSOD?

    Код (Text):
    1. #include <ntddk.h>
    2.  
    3. #define SYS_SERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[(PULONG)*((PUCHAR)_function+1)]
    4. #define SYSCALL_IND(_function)  (PULONG)*((PUCHAR)_function+1)    //индекс фун. из SSDT
    5. #define HOOK(_function, _hook, _orig) _orig = (PVOID) InterlockedExchange((PLONG)&MappedSystemCallTable[SYSCALL_IND(_function)], (LONG)_hook);
    6. #define UNHOOK(_function, _hook, _orig) InterlockedExchange((PLONG)&MappedSystemCallTable[SYSCALL_IND(_function)], (LONG)_hook);
    7.  
    8. struct _SYSTEM_THREADS{
    9. LARGE_INTEGER CreateTime;
    10. LARGE_INTEGER UserTime;
    11. LARGE_INTEGER KernelTime;
    12. ULONG WaitTime;
    13. PVOID StartAddress;
    14. CLIENT_ID ClientIs;
    15. KPRIORITY Priority;
    16. KPRIORITY BasePriority;
    17. ULONG ContextSwitchCount;
    18. ULONG ThreadState;
    19. KWAIT_REASON WaitReason;
    20. };
    21.  
    22. struct _SYSTEM_PROCESSES{
    23. ULONG NextEntryDelta;
    24. ULONG ThreadCount;
    25. ULONG Reserved[6];
    26. LARGE_INTEGER CreateTime;
    27. LARGE_INTEGER UserTime;
    28. LARGE_INTEGER KernelTime;
    29. UNICODE_STRING ProcessName;
    30. KPRIORITY BasePriority;
    31. ULONG ProcessId;
    32. ULONG InheritedFromProcessId;
    33. ULONG HandleCount;
    34. ULONG Reserved2[2];
    35. VM_COUNTERS VmCounters;
    36. IO_COUNTERS IoCounters;
    37. struct _SYSTEM_THREADS Threads[1];
    38. };
    39.  
    40.  
    41. NTSTATUS _QSI(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength);
    42. VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
    43.  
    44. typedef NTSTATUS ZWQUERYSYSTEMINFORMATION(
    45.     IN PULONG SystemInformationClass,
    46.     OUT PVOID SystemInformation,
    47.     IN ULONG SystemInformationLength,
    48.     OUT PULONG ReturnLength OPTIONAL
    49. );
    50.  
    51.  
    52. #pragma pack(1)
    53. typedef struct ServiceDescriptorEntry{
    54.     unsigned int *ServiceTableBase;
    55.     unsigned int *ServiceCounterTableBase;
    56.     unsigned int NumberOfServices;
    57.     unsigned char *ParamTableBase;
    58. }ServiceDescriptorTableEntry_t;
    59. #pragma pack()
    60. _declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
    61.  
    62. PVOID _oriQSI;
    63.  
    64. PVOID *MappedSystemCallTable;
    65.  
    66. //DriverEntry
    67. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath){
    68. PMDL psyscall;
    69. DriverObject->DriverUnload = DriverUnload;
    70. _oriQSI = (PVOID)SYS_SERVICE(ZwQuerySystemInformation);
    71.  
    72. //снимаем защиту с SSDT
    73. psyscall = MmCreateMdl(0, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices * 4);
    74. if(!psyscall)return STATUS_UNSUCCESSFUL;
    75. MmBuildMdlForNonPagedPool(psyscall);
    76. psyscall->MdlFlags = psyscall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
    77. MappedSystemCallTable = MmMapLockedPages(psyscall, KernelMode);
    78.  
    79. //ставим хук...
    80. HOOK(ZwQuerySystemInformation, _QSI, _oriQSI);
    81. return STATUS_SUCCESS;
    82. }
    83.  
    84.  
    85.  
    86.  
    87. VOID DriverUnload(IN PDRIVER_OBJECT DriverObject){
    88. UNHOOK(ZwQuerySystemInformation, _oriQSI, _QSI);
    89. }
    90.  
    91.  
    92.  
    93.  
    94. //ниче не делаем просто передаем управление оригиналу.
    95. NTSTATUS _QSI(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength){
    96. _asm{
    97.     push ReturnLength;
    98.     push SystemInformationLength
    99.     push SystemInformation
    100.     push SystemInformationClass
    101.     call _oriQSI
    102.              ret
    103. }
    104. return 0;
    105. }
     
  2. Guest

    Guest Guest

    Публикаций:
    0
    Это зачем?
    Поищи по форуму, там есть стандартный и известный метод с остановкой прерываний.
    Хм, это stdcall функция, следовало бы добавить add esp, 16 после call'а.
    P.S. Сообщи номер ошибки и прочую инфу из BSOD
     
  3. mathio

    mathio New Member

    Публикаций:
    0
    Регистрация:
    16 июн 2007
    Сообщения:
    110
    im1111
    stdcall ф-ии сами чистят стек, если вы имеете ввиду ZwQuerySystemInformation(), т.е. после call никаких дополнительных очисток в вызывающей процедуре делать не следует.
    Это вы попутали с сидекл :)
     
  4. Guest

    Guest Guest

    Публикаций:
    0
    угу точно, значит тогда ret 16 надо добавить =)
     
  5. mathio

    mathio New Member

    Публикаций:
    0
    Регистрация:
    16 июн 2007
    Сообщения:
    110
    Нужно просто возвращаться по сишному return, чтобы стек очищался кодом построенным компилятором.
    Здесь нужно четко представлять, с помощью какой конвенции по-дефолту конкретный компилятор строит вызов функции. Либо самому определять нужную(что правильнее):
    #define NTAPI __stdcall
    NTSTATUS NTAPI _QSI(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength);
    Ибо, если вызов _QSI() построен как stdcall, то падение в этом месте будет 100% из-за асмового ret из _QSI().
     
  6. Guest

    Guest Guest

    Публикаций:
    0
    Код (Text):
    1. typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION) (
    2.          IN ULONG SystemInformationClass,
    3.          IN PVOID SystemInformation,
    4.          IN ULONG SystemInformationLength,
    5.          OUT PULONG ReturnLength);
    6. ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;
    7.  
    8. .....Перехват:
    9. OldZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION) KeServiceDescriptorTable.ServiceTableBase[_callnumber_ZwQuerySystemInformation];
    10.  
    11. (ZWQUERYSYSTEMINFORMATION)KeServiceDescriptorTable.ServiceTableBase[_callnumber_ZwQuerySystemInformation] = NewZwQuerySystemInformation;
    12.  
    13. NTSTATUS __stdcall NewZwQuerySystemInformation( IN ULONG SystemInformationClass, IN PVOID SystemInformation,
    14.          IN ULONG SystemInformationLength, OUT PULONG ReturnLength)
    15. {
    16.      return OldZwQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
    17. }
     
  7. valix7

    valix7 New Member

    Публикаций:
    0
    Регистрация:
    31 окт 2006
    Сообщения:
    143
    Всем спасибо! разобрался
     
  8. mathio

    mathio New Member

    Публикаций:
    0
    Регистрация:
    16 июн 2007
    Сообщения:
    110
    im1111
    при таком тайпдефе
    компилятор построит вызов
    по-умолчанию скорее всего в соответствии с конвенцией __cdecl.
    Таким образом стек будет очищен 2 раза и станет не сбалансированным -> BSOD. Иными словами параметры, передаваемые в OldZwQuerySystemInformation(), будут очищены как в самой OldZwQuerySystemInformation(), ибо она скомпилирована как __stdcall, так и в NewZwQuerySystemInformation(), т.к. вызов OldZwQuerySystemInformation() происходит как __cdecl.
    Нужно строже определить нужный тип, т.е.:
    Код (Text):
    1. typedef NTSTATUS (NTAPI*ZWQUERYSYSTEMINFORMATION) (
    2.          IN ULONG SystemInformationClass,
    3.          IN PVOID SystemInformation,
    4.          IN ULONG SystemInformationLength,
    5.          OUT PULONG ReturnLength);
    6. ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;
     
  9. Guest

    Guest Guest

    Публикаций:
    0
    "скорее всего" здесь лишне, этот код проверен, не стоит флеймить.
     
  10. mathio

    mathio New Member

    Публикаций:
    0
    Регистрация:
    16 июн 2007
    Сообщения:
    110
    Это не флейм. При вашем стиле программирования, компилятор волен сам выбирать конвенцию вызова, что в данном случае не допустимо, ибо один из участков кода системы(ZwQuerySystemInformation()) уже построен, как stdcall.
     
  11. Guest

    Guest Guest

    Публикаций:
    0
    Это именно флейм, а если не флейм то "кодерская бюрократия" (до....ся до чужого кода на ровном месте). Я не объявляю stdcall по 2м причинам: 1. Не было с этим проблем(DDK 2000/2003 и на 99% уверен что собирется под вистовским DDK). 2. В 64битных дровах stdcall идет лесом.
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    откуда ты знаешь, можеть он его компилирует с /Gz