Здравствуйте. Вот нашел исходник , подработал под свои задачи , а он не работает. Пои идеи когда я буду пытаться прочитать test.txt блокнот его не откроет , но такого не происходит .Вот код. Код (Text): #include <ntddk.h> //#include <winnt.h> #include "Driver.h" VOID UnloadRoutine(IN PDRIVER_OBJECT pDriverObject); NTSTATUS Create_File_IRProcessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp); NTSTATUS Close_HandleIRProcessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp); NTSTATUS ReadWrite_IRPhandler(IN PDEVICE_OBJECT fdo,IN PIRP Irp); NTSTATUS DeviceControlRutine(IN PDEVICE_OBJECT fdo,IN PIRP Irp); KSPIN_LOCK MySpinLock; typedef PVOID* PNTPROC; typedef DWORD (ULONG); typedef DWORD* PDWORD; typedef unsigned char (BYTE); typedef BYTE* PBYTE; typedef struct _SYSTEM_SERVICE_TABLE { PNTPROC ServiceTable; PDWORD CounterTable; ULONG ServiceLimit; PBYTE ArgumentTable; } SYSTEM_SERVICE_TABLE , * PSYSTEM_SERVICE_TABLE , * * PPSYSTEM_SERVICE_TABLE ; typedef struct _SERVICE_DESCRIPTOR_TABLE { SYSTEM_SERVICE_TABLE ntoskrnl; //SST для ntoskrnl.exe SYSTEM_SERVICE_TABLE win32k; //SST для win32k.sys SYSTEM_SERVICE_TABLE unused1; //не используется SYSTEM_SERVICE_TABLE unused2; //не используется } SERVICE_DESCRIPTOR_TABLE , * PSERVICE_DESCRIPTOR_TABLE, * * PPSERVICE_DESCRIPTOR_TABLE ; //макрос для простого доступа к SST ядра #define NTCALL(_function) KeServiceDescriptorTable->ntoskrnl.ServiceTable[_function] //импортируем указатель на SDT extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; //импортируем версию ядра NT extern PUSHORT NtBuildNumber; //обьявляем прототип True функции для перехватываемой функции typedef NTSTATUS (*NtCreateFile) (OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength ); //обьявляем True функцию NtCreateFile TrueNtCreateFile; //номер системного вызова NtOpenProcess ULONG OpenProcId; ULONG PID=20320; //функция - обработчик перехвата NTSTATUS NewNtCreateFile ( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength ) { PWCHAR wcsFileName; NTSTATUS status; wchar_t *pdest; wchar_t ch = '\\'; void* pMdl1; void* pMdl2; void* pMdl3; UNICODE_STRING uniFileName, uniHideDirFile; BOOLEAN locked1 = FALSE, locked2 = FALSE, locked3 = FALSE; RtlInitUnicodeString(&uniHideDirFile, L"test.txt"); DbgPrint("Started"); if (ExGetPreviousMode() == UserMode) { pMdl1 = IoAllocateMdl(ObjectAttributes, sizeof(ObjectAttributes), FALSE, FALSE, NULL); if (pMdl1 == NULL) goto done; __try { MmProbeAndLockPages(pMdl1, KernelMode, IoModifyAccess); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("bla-bla-bla1: error"); goto done; } locked1 = TRUE; pMdl2 = IoAllocateMdl(ObjectAttributes->ObjectName, sizeof(UNICODE_STRING), FALSE, FALSE, NULL); if (pMdl2 == NULL) goto done; __try { MmProbeAndLockPages(pMdl2, KernelMode, IoModifyAccess); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("bla-bla-bla2: error"); goto done; } locked2 = TRUE; pMdl3 = IoAllocateMdl(ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length, FALSE, FALSE, NULL); if (pMdl3 == NULL) goto done; __try { MmProbeAndLockPages(pMdl3, KernelMode, IoModifyAccess); } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("bla-bla-bla3: error"); goto done; } locked3 = TRUE; // Start wcsFileName = ObjectAttributes->ObjectName->Buffer; pdest = wcsrchr(wcsFileName, ch); if (pdest > 0) { RtlInitUnicodeString(&uniFileName, pdest+1); if (RtlCompareUnicodeString(&uniFileName, &uniHideDirFile, TRUE ) == 0){ status = STATUS_OBJECT_NAME_NOT_FOUND; goto done; } } else { if (wcslen(wcsFileName) > 0) RtlInitUnicodeString(&uniFileName, wcsFileName); if (RtlCompareUnicodeString(&uniFileName, &uniHideDirFile, TRUE ) == 0) { status = STATUS_OBJECT_NAME_NOT_FOUND; goto done; } } // End // End done: if (locked1) MmUnlockPages(pMdl1); if (locked2) MmUnlockPages(pMdl2); if (locked3) MmUnlockPages(pMdl3); if (pMdl1 != NULL) IoFreeMdl(pMdl1); if (pMdl2 != NULL) IoFreeMdl(pMdl2); if (pMdl3 != NULL) IoFreeMdl(pMdl3); } if (status == STATUS_SUCCESS) TrueNtCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock, AllocationSize,FileAttributes,ShareAccess,CreateDisposition, CreateOptions,EaBuffer,EaLength); return status; // return TrueNtCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock, // AllocationSize,FileAttributes,ShareAccess,CreateDisposition, CreateOptions,EaBuffer,EaLength); } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { ULONG CR0Reg; NTSTATUS status; UNICODE_STRING fullFileName; HANDLE fileHandle; IO_STATUS_BLOCK iostatus; OBJECT_ATTRIBUTES oa; UNICODE_STRING devName; PDEVICE_OBJECT fdo; PEXAMPLE_DEVICE_EXTENSION dx; UNICODE_STRING symLinkName; DriverObject->DriverUnload=UnloadRoutine; DriverObject->MajorFunction[IRP_MJ_CREATE]=Create_File_IRProcessing; DriverObject->MajorFunction[IRP_MJ_CLOSE]=Close_HandleIRProcessing; DriverObject->MajorFunction[IRP_MJ_READ]=ReadWrite_IRPhandler; DriverObject->MajorFunction[IRP_MJ_WRITE]=ReadWrite_IRPhandler; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DeviceControlRutine; RtlInitUnicodeString(&devName,L"\\Device\\EXAMPLE"); status=IoCreateDevice(DriverObject,sizeof(EXAMPLE_DEVICE_EXTENSION), &devName,FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo); dx=(PEXAMPLE_DEVICE_EXTENSION) fdo->DeviceExtension; dx->fdo=fdo; #define SYM_LINK_NAME L"\\DosDevices\\Example" RtlInitUnicodeString(&symLinkName,SYM_LINK_NAME); dx->ustrSymLinkName=symLinkName; status=IoCreateSymbolicLink(&symLinkName,&devName); KeInitializeSpinLock(&MySpinLock); RtlInitUnicodeString(&fullFileName,L"\\??\\C:\\make my driver.txt"); InitializeObjectAttributes(&oa, &fullFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); status=ZwCreateFile(&fileHandle, GENERIC_WRITE | SYNCHRONIZE, &oa, &iostatus, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); ZwClose(fileHandle); //определяем версию ядра системы switch (*NtBuildNumber) { case 2195 : //win 2k OpenProcId = 0x06A; break; case 2600 : //win xp OpenProcId = 0x026; break; default : return STATUS_NOT_IMPLEMENTED; break; } //устанавливаем перехват TrueNtCreateFile = NTCALL(OpenProcId); __asm { cli // запрещаем прерывания mov eax, cr0 mov CR0Reg,eax and eax,0xFFFEFFFF // сбросить WP bit mov cr0, eax } NTCALL(OpenProcId) = NewNtCreateFile; __asm { mov eax, CR0Reg mov cr0, eax // востановить содержимое CR0 sti // разрешаем прерывания } return status; } NTSTATUS CompleteIrp(PIRP Irp,NTSTATUS status,ULONG info) { Irp->IoStatus.Status=status; Irp->IoStatus.Information=info; IoCompleteRequest(Irp,IO_NO_INCREMENT); return status; } NTSTATUS ReadWrite_IRPhandler(IN PDEVICE_OBJECT fdo,IN PIRP Irp) { ULONG BytesTdx=0; NTSTATUS status=STATUS_SUCCESS; return CompleteIrp(Irp,status,BytesTdx); } NTSTATUS Create_File_IRProcessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp) { PIO_STACK_LOCATION IrpStack=IoGetCurrentIrpStackLocation(Irp); return CompleteIrp(Irp,STATUS_SUCCESS,0); } NTSTATUS Close_HandleIRProcessing(IN PDEVICE_OBJECT fdo,IN PIRP Irp){ return CompleteIrp(Irp,STATUS_SUCCESS,0); } NTSTATUS DeviceControlRutine(IN PDEVICE_OBJECT fdo,IN PIRP Irp) { NTSTATUS status=STATUS_SUCCESS; PEXAMPLE_DEVICE_EXTENSION dx; PIO_STACK_LOCATION IrpStack; KIRQL irql; KIRQL currentIrql; ULONG BytesTdx=0; ULONG ControlCode; ULONG method; IrpStack=IoGetCurrentIrpStackLocation(Irp); IrpStack=IoGetCurrentIrpStackLocation(Irp); dx=(PEXAMPLE_DEVICE_EXTENSION) fdo->DeviceExtension; ControlCode=(ULONG)(IrpStack->Parameters.DeviceIoControl.IoControlCode); method=ControlCode & 0x03; irql=KeGetCurrentIrql(); currentIrql=KeGetCurrentIrql(); KeAcquireSpinLock(&MySpinLock,&irql); PID=ControlCode; KeReleaseSpinLock(&MySpinLock,irql); return CompleteIrp(Irp,status,BytesTdx); } VOID UnloadRoutine(IN PDRIVER_OBJECT pDriverObject) { ULONG CR0Reg; //снимаем перехват __asm { cli // запрещаем прерывания mov eax, cr0 mov CR0Reg,eax and eax,0xFFFEFFFF // сбросить WP bit mov cr0, eax } NTCALL(OpenProcId) = TrueNtCreateFile; __asm { mov eax, CR0Reg mov cr0, eax // востановить содержимое CR0 sti // разрешаем прерывания } return; } Запускаю dryver.sys с помощью DriverMonitor. Подскажите пожалуйста , в чем ошибка?
Отладчик желательно применить.. Для начала нужно знать устанавливаетсо ли хук ? И есчо вполне возможно что блокнот юзоет NtOpenFile Хуки в пограничном режиме слишком хлипкие, нужно глубже..
Для начала нужно знать устанавливаетсо ли хук ? Да.Перехват осуществляется. И есчо вполне возможно что блокнот юзоет NtOpenFile Также пробывал удалять файлы-DeleteFile-реакции никакой. Немоглибы Вы пожалуйста точно описать , что вы имели ввиду под выражением "Хуки в пограничном режиме слишком хлипкие, нужно глубже.."? Спасибо
Поясняю: Хуки в сст ненадёжны и не удобны. Раз перехват осуществляется в таком случае запускаем отладчик, ставим бряк на NewNtCreateFile и трассируем. Там и видно будет что и как.
hawk Я тебе еще в той теме, которая в беггинерсах написал, потом засомневалсо и потер. Ща проверил. Ты не пробовал хукать NtCreateFile (0x25 for XP), а не NtCreateIoCompletion ?
hawk Ядро на этой таблице не заканчивается, оно тока там начинается, гугль в помощ. [Я ведь всё с нуля напальцах не собираюсь пересказывать.]
hawk Меня терзают смутные сомнения, но мне кажется, что мы будем находиться в контексте вызывающего процесса. Сейчас нет возможности проверить, попробуй сам. (PsGetCurrentProcess)
Возник вопрос.Вот если мне необходимо отловить запись в какойто конкретный файл,как быть? Я вижу следующее решение: отловить ntcreatefile и если аргументом функции являеться интересующий нас файл,мы сохраняем хендл после выполнения ntCreateFile.Затем отлавливаем NtWriteFile,и если передоваемый ей хэндл,тот же самый ,что вернула ntCreateFile,то допустим блокируем запись в файл. Такой способ жизнеспособен?
hawk В разных процессах - разные хендлы. В итоге, может получиться, что твой сохраненный хендл совпадет с хендлом другого файла (объекта) в другом процессе. И все, пипец... Наверное, имеет смысл проверять параметр ACCESS_MASK. Или перехватывать сразу NtWriteFile?
перехватывать сразу ntWriteFile?А как из его параметров выташить имя файла? Спасибо,на счёт такой ситуации с хэнделами я не подумал.А что,если ввести дополнительный параметр,т.е. при перехвате ntCreateFile в отдельное поле заносить ещё имя процесса который его вызвал,а точнее полный путь к процессу?И тогда,при перехвате ntWriteFile сравнивать не только хэндл,но и имя процесса.Тогда по идеи всё должно корректно работать.
hawk Все проще. Насколько помню, для того чтобы писать в файл, он должен быть открыт с правами на запись. Вот и ограничивай права. Я ж тебе сверху писал.
ну это я понимаю,но фаил с правами записи,не означает,что в него запишут,я хочу конкретно запись в файл отловить.Как вы думайте,вышеописанный мной метод пойдёт или есть что-то лучше?
hawk Описанный тобой метод, имхо, будет тем более тормознутым, чем дольше работает юзер в системе, т.к. с каждым открытым файлом будут расти два массива (хендлов и процессов) по кторым нужно пробежаться перед тем, как вызвать оригинальную функцию. Хз.. помоему с этим никто не заморачивается. Просто, если кто-то пытается открыть на запись какой-нить стратегический файл - выкидывают аллерт. Но, если уж так необходимо, видимо лучше хучить врайтфайл и сверять имя через хендл (ZwQueryInformationFile). Это так, на вскидку...
Народ ХЭЛП. Пытаюсь отловить запись в реестр, точно также как я и отлавливал обращение к файлу. Полностью отключить обращение к реестру я могу , а вот к конкретной ветке(ключу), не выходит. ИМХО сравнение както не верно делаю. Код (Text): NTSTATUS NewNtCreateKey ( OUT PHANDLE pKeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL) { PWCHAR wcsFileName; NTSTATUS status; NTSTATUS FILE_O; ULONG KP=0; wchar_t *pdest; wchar_t ch = '\\'; void* pMdl1; void* pMdl2; void* pMdl3; UNICODE_STRING uniFileName, uniHideDirFile; BOOLEAN locked1 = FALSE, locked2 = FALSE, locked3 = FALSE; status=STATUS_SUCCESS; RtlInitUnicodeString(&uniHideDirFile, L"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); wcsFileName = ObjectAttributes->ObjectName->Buffer; if (wcslen(wcsFileName) > 0)RtlInitUnicodeString(&uniFileName, wcsFileName); if (RtlCompareUnicodeString(&uniFileName, &uniHideDirFile, TRUE ) == 0) { status = STATUS_OBJECT_NAME_NOT_FOUND; goto done; }; done: if (status == STATUS_SUCCESS){TrueNtCreateKey(pKeyHandle,DesiredAccess,ObjectAttributes,TitleIndex, Class, CreateOptions,Disposition);} return status; } Вот функция оброботчика. Если в ее начале поставить status = STATUS_OBJECT_NAME_NOT_FOUND; return status; то ни к одному ключу обращение произвести нельзя-перехват происходит. А вот со сравнением пути как-то тяжко. Может не правильная форма записи? Хотя вроде форму брал из В.П.Солдатова-т.е. все должно быть в норме, подскажите пожалуйста, в чем баг, кроме моей головы
Пока только стилистически поправлю. Код (Text): ... if (ObjectAttributes->ObjectName->Length) //длина больше нуля if (RtlCompareUnicodeString(ObjectAttributes->ObjectName, &uniHideDirFile, TRUE ) == 0)// строки равны status = STATUS_OBJECT_NAME_NOT_FOUND; if (status == STATUS_SUCCESS) status = TrueNtCreateKey(pKeyHandle,DesiredAccess,ObjectAttributes,TitleIndex, Class, CreateOptions,Disposition); return status; }
Нашел причину. Как говорил Козьма Прутков(или фиг его как там) -зри в корень, а корень-ядро. Так вот , RegCreateKeyEx в advapi32.dll делает некую фильтрацию, т.е. в зависимости от первого параметра функции мы перепрыгиваем в то или иное место библиотеки, а при первом параметре HKEY_LOCAL_MACHINE мы никуда не ответвляемся и продолжаем свой путь по основной функции , и при передаче параметров NtCreateKey мы , в качестве ObjectName-> имеем чисто путь без указания ветви реестра. Т.е. чтобы все работало для HKEY_LOCAL_MACHINE необходимо изменить лишь одну строку- RtlInitUnicodeString(&uniHideDirFile, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"); Вот и все! Для других ветвей реестра еще не смотрел.