Код (Text): typedef struct _KSERVICE_TABLE_DESCRIPTOR { PULONG_PTR Base; PULONG Count; ULONG Limit; PUCHAR Number; } KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR; PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable; BOOLEAN InitSSDTHooks() { UNICODE_STRING uRoutine; RtlInitUnicodeString(&uRoutine,L"KeServiceDescriptorTable"); KeServiceDescriptorTable =(PKSERVICE_TABLE_DESCRIPTOR) MmGetSystemRoutineAddress(&uRoutine); return (KeServiceDescriptorTable != NULL) ; }; BOOLEAN HookSSDTEntry(LONG Entry,PVOID NewHandler,PVOID *OldHandler) { if ( Entry<KeServiceDescriptorTable->Limit) { *OldHandler = KeServiceDescriptorTable->Base[Entry]; KeServiceDescriptorTable->Base[Entry] = NewHandler; return TRUE; }; return FALSE; }; BOOLEAN GetIndexSystemService(PVOID RoutineAddress,ULONG*Index) { CHAR *pByte = (CHAR*) RoutineAddress; *Index = 0; if ( *pByte != (CHAR)0xB8 /*mov eax, N*/ ) return FALSE; *Index = *(PULONG_PTR)(pByte + 1); return TRUE; }; /// Установка хука p = GetProcAddress(pNtdll,"ZwQueueApcThread",FALSE); // возвращает указатель на функцию if ( GetIndexSystemService(p,&Index) ) if ( HookSSDTEntry(Index,(PVOID)NewNtQueueApcThread,(PVOID)&OldNtQueueApcThread) == FALSE ) DbgPrint("HookSSDT(ZwQueueApcThread) fail\n"); else DbgPrint("ZwQueueApcThread __asm{ mov eax,%x } \n",Index); //// Обработка хука NTSTATUS NTAPI NewNtQueueApcThread ( HANDLE ThreadHandle, PKNORMAL_ROUTINE ApcRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2 ) { if (KeGetCurrentIrql() == PASSIVE_LEVEL) if ( (PsIsSystemThread(PsGetCurrentThread()) == FALSE) ) { PTHREAD_BASIC_INFORMATION BasicInfo; ULONG retSize = sizeof(THREAD_BASIC_INFORMATION); do{ if ( ! (BasicInfo = (PTHREAD_BASIC_INFORMATION)QueryInformationThread(ThreadHandle,ThreadBasicInformation,&retSize)) ) break; if ( BasicInfo->ClientId.UniqueProcess != PsGetCurrentProcessId()) DbgPrint("WARNING: Inject process [ %x -> %x] \n",PsGetCurrentProcessId(),BasicInfo->ClientId.UniqueProcess); }while(0); }; return OldNtQueueApcThread(ThreadHandle,ApcRoutine,NormalContext,SystemArgument1,SystemArgument2); }; Установка хука проходит успешно и RKu его отображает, через некоторое время этот хук снимается... как такое может быть? ОС хп, сп3. там розреша запись в ssdt. Чистая виртуалка на вмваре. Прикрепил тестовый драйвер он ставит нотификации на создание процессов, где просто выводит дебажные строки. в хуках аналогично только вывод дебажной строки.
Стоит ли какое-то антивирусное ПО в системе? Есть ли возможность отладить систему? Если есть, я бы поставил точку останова на запись в SSDT на адрес ф-ии и ждал, пока он сработает, чтобы выявить, кто это постарался. Еще одна непонятная вещь: SSDT доступна только для чтения. HookSSDTEntry свободно в нее пишет. Полагаю, что CR0.WP сброшен, но в коде этого не видно. В общем, этот момент не ясен.
У меня папра вопросов. 1. Так в SSDT Zw или Nt????????????????? Если Zw, то тогда где Nt??????????? 2. XshStasX, у тебя не убивается система после снятия хуков и выгрузки драйвера? 3. if (KeGetCurrentIrql() == PASSIVE_LEVEL) if ( (PsIsSystemThread(PsGetCurrentThread()) == FALSE) Объясните зачем это плз.
В SDT адреса NT-сервисов, т.е. функций с префиксом Nt, а ZwXxx() это экспорты ядра, переходники к сервисам. Можно реализовать схему с подсчётом ссылок, вероятность падения при выгрузке стремится к нулю. Это лучше спросить у автора. Проверка на irql=0 не имеет смысла здесь. Ну а проверка на поток ядра это, вероятно, какая-то особенность логики.
Спасибо за скорый ответ. Я делаю подобный перехват, но перехватывая, собираю информацию типа имени файла, хэндл после createfile и пр. За основу брал драйвер stracer, так вот там с InterlockedIncrement/Decrement в начале и в конце изменяется переменная calls_in_progress. На выгрузке стоит проверка while(calls_in_progress){}. После снятия хука с течением времени вызовы завершаются и эта переменная уменьшается, но не координально. Как будто вызовы остаются выполняться. Почему так? А если выгружаю - всё падает после пары секунд) Можно как-нибудь организовать схему перехвата с сбором инфы до и после и при этом чтобы легко все выгружать?
Возможно, тупо ошибка где-то в коде драйвера. А некоторые вызовы, если они синхронные, действительно могут долго не завершаться. Самый надёжный метод это скопировать код перехватчиков куда-нибудь в память, а драйвер спокойно выгрузить. При следующем запуске драйвера проверить, что все вызовы завершились, и освободить память, выделенную в прошлый раз. Это необходимо, чтобы не было утечек.
Блин, случилась неведомая фигня! Я попробовал запустить при работающем драйвере студию и получил бсод! Это у них такая защита? Или мой буфер на 30000 записей за секунду переполнился!?? Если 1ое - как обойти?