Подскажите плз почему сразу после старта драйвера появляется BSOD? Код (Text): #include <ntddk.h> #define SYS_SERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[(PULONG)*((PUCHAR)_function+1)] #define SYSCALL_IND(_function) (PULONG)*((PUCHAR)_function+1) //индекс фун. из SSDT #define HOOK(_function, _hook, _orig) _orig = (PVOID) InterlockedExchange((PLONG)&MappedSystemCallTable[SYSCALL_IND(_function)], (LONG)_hook); #define UNHOOK(_function, _hook, _orig) InterlockedExchange((PLONG)&MappedSystemCallTable[SYSCALL_IND(_function)], (LONG)_hook); struct _SYSTEM_THREADS{ LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientIs; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; ULONG ThreadState; KWAIT_REASON WaitReason; }; struct _SYSTEM_PROCESSES{ ULONG NextEntryDelta; ULONG ThreadCount; ULONG Reserved[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; IO_COUNTERS IoCounters; struct _SYSTEM_THREADS Threads[1]; }; NTSTATUS _QSI(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); VOID DriverUnload(IN PDRIVER_OBJECT DriverObject); typedef NTSTATUS ZWQUERYSYSTEMINFORMATION( IN PULONG SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL ); #pragma pack(1) typedef struct ServiceDescriptorEntry{ unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; unsigned int NumberOfServices; unsigned char *ParamTableBase; }ServiceDescriptorTableEntry_t; #pragma pack() _declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; PVOID _oriQSI; PVOID *MappedSystemCallTable; //DriverEntry NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath){ PMDL psyscall; DriverObject->DriverUnload = DriverUnload; _oriQSI = (PVOID)SYS_SERVICE(ZwQuerySystemInformation); //снимаем защиту с SSDT psyscall = MmCreateMdl(0, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices * 4); if(!psyscall)return STATUS_UNSUCCESSFUL; MmBuildMdlForNonPagedPool(psyscall); psyscall->MdlFlags = psyscall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; MappedSystemCallTable = MmMapLockedPages(psyscall, KernelMode); //ставим хук... HOOK(ZwQuerySystemInformation, _QSI, _oriQSI); return STATUS_SUCCESS; } VOID DriverUnload(IN PDRIVER_OBJECT DriverObject){ UNHOOK(ZwQuerySystemInformation, _oriQSI, _QSI); } //ниче не делаем просто передаем управление оригиналу. NTSTATUS _QSI(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength){ _asm{ push ReturnLength; push SystemInformationLength push SystemInformation push SystemInformationClass call _oriQSI ret } return 0; }
Это зачем? Поищи по форуму, там есть стандартный и известный метод с остановкой прерываний. Хм, это stdcall функция, следовало бы добавить add esp, 16 после call'а. P.S. Сообщи номер ошибки и прочую инфу из BSOD
im1111 stdcall ф-ии сами чистят стек, если вы имеете ввиду ZwQuerySystemInformation(), т.е. после call никаких дополнительных очисток в вызывающей процедуре делать не следует. Это вы попутали с сидекл
Нужно просто возвращаться по сишному return, чтобы стек очищался кодом построенным компилятором. Здесь нужно четко представлять, с помощью какой конвенции по-дефолту конкретный компилятор строит вызов функции. Либо самому определять нужную(что правильнее): #define NTAPI __stdcall NTSTATUS NTAPI _QSI(IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); Ибо, если вызов _QSI() построен как stdcall, то падение в этом месте будет 100% из-за асмового ret из _QSI().
Код (Text): typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION) ( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation; .....Перехват: OldZwQuerySystemInformation = (ZWQUERYSYSTEMINFORMATION) KeServiceDescriptorTable.ServiceTableBase[_callnumber_ZwQuerySystemInformation]; (ZWQUERYSYSTEMINFORMATION)KeServiceDescriptorTable.ServiceTableBase[_callnumber_ZwQuerySystemInformation] = NewZwQuerySystemInformation; NTSTATUS __stdcall NewZwQuerySystemInformation( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength) { return OldZwQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); }
im1111 при таком тайпдефе компилятор построит вызов по-умолчанию скорее всего в соответствии с конвенцией __cdecl. Таким образом стек будет очищен 2 раза и станет не сбалансированным -> BSOD. Иными словами параметры, передаваемые в OldZwQuerySystemInformation(), будут очищены как в самой OldZwQuerySystemInformation(), ибо она скомпилирована как __stdcall, так и в NewZwQuerySystemInformation(), т.к. вызов OldZwQuerySystemInformation() происходит как __cdecl. Нужно строже определить нужный тип, т.е.: Код (Text): typedef NTSTATUS (NTAPI*ZWQUERYSYSTEMINFORMATION) ( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation;
Это не флейм. При вашем стиле программирования, компилятор волен сам выбирать конвенцию вызова, что в данном случае не допустимо, ибо один из участков кода системы(ZwQuerySystemInformation()) уже построен, как stdcall.
Это именно флейм, а если не флейм то "кодерская бюрократия" (до....ся до чужого кода на ровном месте). Я не объявляю stdcall по 2м причинам: 1. Не было с этим проблем(DDK 2000/2003 и на 99% уверен что собирется под вистовским DDK). 2. В 64битных дровах stdcall идет лесом.