прошу помочь мне в этом ... дело в том что я устанавливаю обычный драйвер хук .... хук как известно работает с при IRQL >PASSIVE_LEVEL .... но суть в том что нужно вызывать функи zwcreatefile , etc ... но они работают только на пассиве .... поэтому создаю поток в driverentry, но как только запускается функция хука ... то поток как будто замораживается ....... вобщем даю примерный код который поможет вам понять суть ..... функция потока LogpThreadProcedure но я никогда не вижу сообщения ThREAD2 ((((( и еще вопрос .... какой существует аналог для Sleep(int) только в кернеле Код (Text): #include <string.h> #include <stdio.h> #include <ntddk.h> #include <ntddndis.h> #include <pfhook.h> #include "DrvFltIp.h" #define dprintf DbgPrint NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); VOID DrvUnload(IN PDRIVER_OBJECT DriverObject); NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction); NTSTATUS AddFilterToList(IPFilter *pf); void ClearFilterList(void); PF_FORWARD_ACTION cbFilterFunction(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long RecvLinkNextHop, IN unsigned long SendLinkNextHop); #define NT_DEVICE_NAME L"\\Device\\DrvFltIp" #define DOS_DEVICE_NAME L"\\DosDevices\\DrvFltIp" struct filterList *first = NULL; struct filterList *last = NULL; typedef struct _PACKET { LIST_ENTRY li; char Packet[64*1024]; int iLenPacket; }PACKET ; LIST_ENTRY li; PACKET * pp; int gflag ; VOID LogpThreadProcedure( IN PVOID StartContext ) { while(gflag==1){ k++; } dprintf("id= %d",k); DbgPrint("ThREAD2"); } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { PDEVICE_OBJECT deviceObject = NULL; NTSTATUS ntStatus; UNICODE_STRING deviceNameUnicodeString; UNICODE_STRING deviceLinkUnicodeString; NTSTATUS status; UNICODE_STRING fullFileName; HANDLE fileHandle; IO_STATUS_BLOCK iostatus; OBJECT_ATTRIBUTES oa; ULONG len; HANDLE handle; NTSTATUS ntstatus; IO_STATUS_BLOCK ioStatusBlock; HANDLE hLogThread; pp=(PACKET*)ExAllocatePool(NonPagedPool,sizeof(PACKET)); gflag =1; pp->iLenPacket=0; DbgPrint("DrvFltIp.SYS: entering DriverEntry\n"); //we have to create the device RtlInitUnicodeString(&deviceNameUnicodeString, NT_DEVICE_NAME); ntStatus = IoCreateDevice(DriverObject, 0, &deviceNameUnicodeString, FILE_DEVICE_DRVFLTIP, 0, FALSE, &deviceObject); if ( NT_SUCCESS(ntStatus) ) { // Create a symbolic link that Win32 apps can specify to gain access // to this driver/device RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME); ntStatus = IoCreateSymbolicLink(&deviceLinkUnicodeString, &deviceNameUnicodeString); if ( !NT_SUCCESS(ntStatus) ) { dprintf("DrvFltIp.SYS: IoCreateSymbolicLink failed\n"); } // // Create dispatch points for device control, create, close. // DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch; DriverObject->DriverUnload = DrvUnload; DbgPrint("NEEEEEEEEWWWWWW"); PsCreateSystemThread(&hLogThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE)LogpThreadProcedure, NULL); / if ( !NT_SUCCESS(ntStatus) ) { dprintf("Error in initialization. Unloading..."); DrvUnload(DriverObject); } return ntStatus; } NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION irpStack; PVOID ioBuffer; ULONG inputBufferLength; ULONG outputBufferLength; ULONG ioControlCode; NTSTATUS ntStatus; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; irpStack = IoGetCurrentIrpStackLocation(Irp); ioBuffer = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: dprintf("DrvFltIp.SYS: IRP_MJ_CREATE\n"); break; case IRP_MJ_CLOSE: dprintf("DrvFltIp.SYS: IRP_MJ_CLOSE\n"); break; case IRP_MJ_DEVICE_CONTROL: dprintf("DrvFltIp.SYS: IRP_MJ_DEVICE_CONTROL\n"); ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; switch (ioControlCode) { // ioctl code to start filtering case START_IP_HOOK: { SetFilterFunction(cbFilterFunction); break; } // ioctl to stop filtering case STOP_IP_HOOK: { SetFilterFunction(NULL); break; } // ioctl to add a filter rule case ADD_FILTER: { if(inputBufferLength == sizeof(IPFilter)) { IPFilter *nf; nf = (IPFilter *)ioBuffer; AddFilterToList(nf); } break; } // ioctl to free filter rule list case CLEAR_FILTER: { ClearFilterList(); break; } default: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; dprintf("DrvFltIp.SYS: unknown IRP_MJ_DEVICE_CONTROL\n"); break; } break; } // // DON'T get cute and try to use the status field of // the irp in the return status. That IRP IS GONE as // soon as you call IoCompleteRequest. // ntStatus = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); // // We never have pending operation so always return the status code. // return ntStatus; } /*++ Routine Description: Free all the allocated resources, etc. Arguments: DriverObject - pointer to a driver object Return Value: --*/ VOID DrvUnload(IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING deviceLinkUnicodeString; dprintf("DrvFltIp.SYS: Unloading\n"); ExFreePool(pp); SetFilterFunction(NULL); // Free any resources ClearFilterList(); // Delete the symbolic link RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME); IoDeleteSymbolicLink(&deviceLinkUnicodeString); // Delete the device object IoDeleteDevice(DriverObject->DeviceObject); } /*++ Routine Description: Get a reference to IpFilterDriver so we will be able to install the filter Arguments: pDeviceObject - pointer to a pointer of device object pFileObject - pointer to a pointer of file object Return Value: STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise --*/ NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction) { NTSTATUS status = STATUS_SUCCESS, waitStatus=STATUS_SUCCESS; UNICODE_STRING filterName; PDEVICE_OBJECT ipDeviceObject=NULL; PFILE_OBJECT ipFileObject=NULL; PF_SET_EXTENSION_HOOK_INFO filterData; KEVENT event; IO_STATUS_BLOCK ioStatus; PIRP irp; dprintf("Getting pointer to IpFilterDriver\n"); //first of all, we have to get a pointer to IpFilterDriver Device RtlInitUnicodeString(&filterName, DD_IPFLTRDRVR_DEVICE_NAME); status = IoGetDeviceObjectPointer(&filterName,STANDARD_RIGHTS_ALL, &ipFileObject, &ipDeviceObject); if(NT_SUCCESS(status)) { //initialize the struct with functions parameters filterData.ExtensionPointer = filterFunction; //we need initialize the event used later by the IpFilterDriver to signal us //when it finished its work KeInitializeEvent(&event, NotificationEvent, FALSE); //we build the irp needed to establish fitler function irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER, ipDeviceObject, (PVOID) &filterData, sizeof(PF_SET_EXTENSION_HOOK_INFO), NULL, 0, FALSE, &event, &ioStatus); if(irp != NULL) { // we send the IRP status = IoCallDriver(ipDeviceObject, irp); //and finally, we wait for "acknowledge" of IpDriverFilter if (status == STATUS_PENDING) { waitStatus = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); if (waitStatus != STATUS_SUCCESS ) dprintf("Error waiting for IpFilterDriver response."); } status = ioStatus.Status; if(!NT_SUCCESS(status)) dprintf("Error, IO error with ipFilterDriver\n"); } else { //if we cant allocate the space, we return the corresponding code error status = STATUS_INSUFFICIENT_RESOURCES; dprintf("Error building IpFilterDriver IRP\n"); } if(ipFileObject != NULL) ObDereferenceObject(ipFileObject); ipFileObject = NULL; ipDeviceObject = NULL; } else dprintf("Error while getting the pointer\n"); return status; } /*++ Routine Description: Add a rule to the filter list Arguments: pf - pointer to filter rule Return Value: STATUS_SUCCESS if successful, STATUS_INSUFFICIENT_RESOURCES otherwise --*/ NTSTATUS AddFilterToList(IPFilter *pf) { struct filterList *aux=NULL; // first, we reserve memory (non paged) to the new filter aux=(struct filterList *) ExAllocatePool(NonPagedPool, sizeof(struct filterList)); if(aux == NULL) { dprintf("Problem reserving memory\n"); return STATUS_INSUFFICIENT_RESOURCES; } //fill the new structure aux->ipf.destinationIp = pf->destinationIp; aux->ipf.sourceIp = pf->sourceIp; aux->ipf.destinationMask = pf->destinationMask; aux->ipf.sourceMask = pf->sourceMask; aux->ipf.destinationPort = pf->destinationPort; aux->ipf.sourcePort = pf->sourcePort; aux->ipf.protocol = pf->protocol; aux->ipf.drop=pf->drop; //Add the new filter to the filter list if(first == NULL) { first = last = aux; first->next = NULL; } else { last->next = aux; last = aux; last->next = NULL; } dprintf("Rule Added\n\t%x %x\n\t%x %x\n\t%x\n\t%x", aux->ipf.sourceIp , aux->ipf.sourceMask , aux->ipf.destinationIp , aux->ipf.destinationMask , aux->ipf.sourcePort , aux->ipf.destinationPort); return STATUS_SUCCESS; } /*++ Routine Description: Remove the linked list where the rules were saved. Arguments: Return Value: --*/ void ClearFilterList(void) { struct filterList *aux = NULL; //free the linked list dprintf("Removing the filter List..."); while(first != NULL) { aux = first; first = first->next; ExFreePool(aux); dprintf("One Rule removed"); } first = last = NULL; dprintf("Removed is complete."); } /*++ Routine Description: Filter each packet is received or sended To see parameters and return you can read it in MSDN --*/ PF_FORWARD_ACTION cbFilterFunction(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long RecvLinkNextHop, IN unsigned long SendLinkNextHop) { IPPacket *ipp; TCPHeader *tcph; UDPHeader *udph; int countRule=0; struct filterList *aux = first; //we "extract" the ip Header ipp=(IPPacket *)PacketHeader; dprintf("Tamaсo: %x, %d", PacketLength, RecvInterfaceIndex); dprintf("Source: %x\nDestination: %x\nProtocol: %d", ipp->ipSource, ipp->ipDestination, ipp->ipProtocol); //TCP -> protocol = 6 //we accept all packets of established connections if(ipp->ipProtocol == 6) { ULONG len; HANDLE handle; NTSTATUS ntstatus; IO_STATUS_BLOCK ioStatusBlock; KIRQL oldrql,irql; NTSTATUS status; UNICODE_STRING fullFileName; HANDLE hf; IO_STATUS_BLOCK iostatus; OBJECT_ATTRIBUTES oa; PACKET *new_pack; oldrql=KeGetCurrentIrql(); if(gflag==1){ pp->iLenPacket=PacketLength; //InsertTailList(&li,&new_pack->li); DbgPrint("ADD LIST"); gflag=0; } ; dprintf("SNIFFFFFFFFFF = %d",pp->iLenPacket); //KeLowerIrql(PASSIVE_LEVEL); /* RtlInitUnicodeString( &fullFileName, L"\\??\\C:\\testfile.txt"); InitializeObjectAttributes( &oa, &fullFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); ntstatus = ZwCreateFile(&handle, GENERIC_WRITE, &oa, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( NT_SUCCESS(ntstatus)){ ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock,&fullFileName, 10, NULL, NULL); ZwClose(handle); } */ //KeRaiseIrql(oldrql,&irql); tcph=(TCPHeader *)Packet; dprintf("FLAGS: %x\n", tcph->flags); //if we havent the bit SYN activate, we pass the packets if(!(tcph->flags & 0x02)) return PF_FORWARD; } //otherwise, we compare the packet with our rules while(aux != NULL) { dprintf("Comparing with Rule %d", countRule); //if protocol is the same.... if(aux->ipf.protocol == 0 || ipp->ipProtocol == aux->ipf.protocol) { //we look in source Address if(aux->ipf.sourceIp != 0 && (ipp->ipSource & aux->ipf.sourceMask) != aux->ipf.sourceIp) { aux=aux->next; countRule++; continue; } // we look in destination address if(aux->ipf.destinationIp != 0 && (ipp->ipDestination & aux->ipf.destinationMask) != aux->ipf.destinationIp) { aux=aux->next; countRule++; continue; } //if we have a tcp packet, we look in ports //tcp, protocol = 6 if(ipp->ipProtocol == 6) { if(aux->ipf.sourcePort == 0 || tcph->sourcePort == aux->ipf.sourcePort) { if(aux->ipf.destinationPort == 0 || tcph->destinationPort == aux->ipf.destinationPort) //puerto tcp destino { //now we decided what to do with the packet if(aux->ipf.drop) return PF_DROP; else return PF_FORWARD; } } } //udp, protocol = 17 else if(ipp->ipProtocol == 17) { udph=(UDPHeader *)Packet; if(aux->ipf.sourcePort == 0 || udph->sourcePort == aux->ipf.sourcePort) { if(aux->ipf.destinationPort == 0 || udph->destinationPort == aux->ipf.destinationPort) { //now we decided what to do with the packet if(aux->ipf.drop) return PF_DROP; else return PF_FORWARD; } } } else { //for other packet we dont look more and .... //now we decided what to do with the packet if(aux->ipf.drop) return PF_DROP; else return PF_FORWARD; } } //compare with the next rule countRule++; aux=aux->next; } //we accept all not registered return PF_FORWARD; }
Какие могут быть работы с файлами и спячка в кернеле. Почитай основы. Логика драйвера : быстро зашел, пометил и назад. Все трудоемкое в фоне делается, тихо и не спеша.
valterg , аха )))))) ты мне конкретно ответить можешь на конкретно поставленную задачу ??? мне нужно логировать данные !
На всякий случай уточним: WorkItem'ы достаточно ценный системный ресурс. Не такой, конечно, как non-paged pool, но где-то близко. Короче говоря, не стоит использовать их для частых и, тем более, для длительных операций.
Просто их лимитированное количество, и есть возможность полностью занять её. Что будет крайне плохо. В принципе, есть еще вариант со своим системным логгирующим потоком, управляемым событием.
Отвечаю конкретно. Логгировать внутри перехватчика с паузами можно только, когда ты управляешь потоком логгируемых сообщений. Иначе легко попадем на "накапливание" сообщений. Надо просто буферизовать сообщения и обрабатывать их в фоне. Естественно все равно будет риск нехватки ресурсов, но он гораздо меньше и легче разрулить.
alekseyWasen KeStallExecutionProcessor KeDelayExecutionThread но только вот на IRQL>PASSIVE_LEVEL лучше не ждать, т к планирование не происходит и будут явно заметные тормоза лучше сделать рабочий поток так чтобы он писал в файл сколько успеваеет когда ему выделили время
Это немножко не то, но исходник драйвера там есть. И на основе этого пакета пишут снифферы http://www.winpcap.org/archive/
я вот тоже думал о скидывании данных юзерской апликухе при логировании. вобщем остановился на такой мысле: - юзер выделяет память, передаёт указатель дрову, дров скидывает в этот буфер пакеты (при этом блокируя буфер). на каждый новый пакет генерирует event. когда буфер заканчивается - начинает писать в начало буфера.
а какая у него проблема с логированием? в правилах какие надо добавляешь слово log он тогда пишет в файл эти пакеты