前言 在XP中可以使用 NDIS5
做网络过滤,在《WINDOWS内核安全与驱动开发》一书中, 对 NDIS5
做了非常详尽的解释,这里就不再做原理性的探讨,只处理具体的应用方法。 整体框架采用WDK源码中 src -> network -> ndis -> passthru
工程作为基础。
修改passthru.c文件 如下 宏定义
为与应用层通讯的 控制设备
的名称,这里修改为其他需要的名称
1 2 #define LINKNAME_STRING L"\\DosDevices\\Passthru" #define NTDEVICE_STRING L"\\Device\\Passthru"
在 DriverEntry
函数中,如下为 协议名称
的定义,这里也要修改为其他需要的名称
1 2 NdisInitUnicodeString(&Name, L"Passthru" ); PChars.Name = Name;
在 PtDispatch
函数中,如下为 控制码
的处理,这里可以添加自定义的控制码处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 switch (irpStack->MajorFunction){ case IRP_MJ_CREATE: break ; case IRP_MJ_CLEANUP: break ; case IRP_MJ_CLOSE: break ; case IRP_MJ_DEVICE_CONTROL: break ; default : break ; }
修改miniport.c文件 在 MPSend
函数开始的位置,判断完设备状态后,调用我们的数据包解析函数
1 2 3 4 5 6 7 8 9 10 if (pAdapt->MPDeviceState > NdisDeviceStateD0){ return NDIS_STATUS_FAILURE; } fStatus = AnalysisPacket(Packet, FALSE); if (fStatus == STATUS_DROP){ return NDIS_STATUS_FAILURE; }
在 MPSendPackets
函数开始的for循环体中,判断完设备状态后,调用我们的数据包解析函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if (pAdapt->MPDeviceState > NdisDeviceStateD0){ NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); continue ; } fStatus = AnalysisPacket(Packet, FALSE); if (fStatus == STATUS_DROP){ NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); continue ; }
在 MPTransferData
函数中,调用 NdisTransferData
成功后,调用我们的数据包解析函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 NdisTransferData(&Status, pAdapt->BindingHandle, MiniportReceiveContext, ByteOffset, BytesToTransfer, Packet, BytesTransferred); if (Status == NDIS_STATUS_SUCCESS){ fStatus = AnalysisPacket(Packet, TRUE); if (fStatus == STATUS_DROP) { Status = NDIS_STATUS_FAILURE; } }
修改protocol.c文件 在 PtTransferDataComplete
函数的开始,定义变量以后,首先调用我们的数据包解析函数
1 2 3 4 5 6 7 8 PADAPT pAdapt = (PADAPT)ProtocolBindingContext; PKGFLT_STATUS fStatus; fStatus = AnalysisPacket(Packet, TRUE); if (fStatus == STATUS_DROP){ Status = NDIS_STATUS_FAILURE; }
在 PtReceive
函数的开始,调用 NdisGetReceivedPacket
成功后,调用我们的数据包解析函数
1 2 3 4 5 6 7 8 9 10 Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext); if (Packet != NULL ){ fStatus = AnalysisPacket(Packet, TRUE); if (fStatus == STATUS_DROP) { Status = NDIS_STATUS_FAILURE; break ; }
在 PtReceivePacket
函数的开始,判断完设备状态后,调用我们的数据包解析函数
1 2 3 4 5 6 7 8 9 10 if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0)){ return 0 ; } fStatus = AnalysisPacket(Packet, TRUE); if (fStatus == STATUS_DROP){ return 0 ; }
数据包解析函数 数据包解析函数返回值的定义:
1 2 3 4 typedef enum { STATUS_PASS = 0 , STATUS_DROP = 1 } PKGFLT_STATUS;
如下为数据包解析函数,拿到以太网数据包后,可以根据相关规定进行格式解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 PKGFLT_STATUS AnalysisPacket (PNDIS_PACKET Packet, BOOLEAN bRecv) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PNDIS_BUFFER NdisBuffer = NULL ; UINT32 TotalLength = 0 ; UINT32 PhysicalCount = 0 ; UINT32 BufferCount = 0 ; PUCHAR PacketContent = NULL ; PUCHAR tempbuf = NULL ; UINT32 copysize = 0 ; UINT32 DataOffset = 0 ; if (Packet == NULL ) return STATUS_PASS; NdisQueryPacket(Packet, &PhysicalCount, &BufferCount, &NdisBuffer, &TotalLength); Status = NdisAllocateMemoryWithTag(&PacketContent, TotalLength, 'MEM'); if (Status != NDIS_STATUS_SUCCESS) return STATUS_PASS; NdisZeroMemory(PacketContent, TotalLength); while (NdisBuffer != NULL ) { NdisQueryBufferSafe(NdisBuffer, &tempbuf, ©size, NormalPagePriority); if (tempbuf == NULL ) { NdisFreeMemory(PacketContent, 0 , 0 ); return STATUS_PASS; } NdisMoveMemory(PacketContent + DataOffset, tempbuf, copysize); DataOffset += copysize; NdisGetNextBuffer(NdisBuffer, &NdisBuffer); } NdisFreeMemory(PacketContent, 0 , 0 ); return STATUS_PASS; }
修改INF文件 在 netsf_m.inf
文件中,修改如下项
1 2 3 4 5 6 7 8 9 10 11 [ControlFlags] ExcludeFromSelect = ms_passthrump[MSFT] %PassthruMP_Desc% = PassthruMP.ndi, ms_passthrump [MSFT.NTx86] %PassthruMP_Desc% = PassthruMP.ndi, ms_passthrump [MSFT.NTia64] %PassthruMP_Desc% = PassthruMP.ndi, ms_passthrump [MSFT.NTamd64] %PassthruMP_Desc% = PassthruMP.ndi, ms_passthrump
1 2 3 4 5 [PassthruMP.ndi.AddReg] HKR, Ndi, Service, 0, PassthruMP [PassthruMP.ndi.Services] AddService = PassthruMP, 0 x2, PassthruMP.AddService
1 2 3 4 5 6 7 [PassthruMP.AddService] ServiceType = 1 StartType = 3 ErrorControl = 1 ServiceBinary = %12 %\passthru.sysAddReg = PassthruMP.AddService.AddReg
在 netsf.inf
文件中,修改如下项
1 2 3 4 5 6 7 8 9 [MSFT] %Passthru_Desc% = Passthru.ndi, ms_passthru [MSFT.NTx86] %Passthru_Desc% = Passthru.ndi, ms_passthru [MSFT.NTia64] %Passthru_Desc% = Passthru.ndi, ms_passthru [MSFT.NTamd64] %Passthru_Desc% = Passthru.ndi, ms_passthru
1 2 3 [Passthru.ndi.Services] AddService = Passthru, , Passthru.AddService
1 2 3 4 5 6 7 8 9 10 [Passthru.AddService] DisplayName = %PassthruService_Desc%ServiceType = 1 StartType = 3 ErrorControl = 1 ServiceBinary = %12 %\passthru.sysAddReg = Passthru.AddService.AddReg[Passthru.Files.Sys] passthru.sys, , , 2
1 2 3 4 5 6 7 8 9 [Passthru.ndi.AddReg] HKR, Ndi, HelpText, , %Passthru_HELP% HKR, Ndi, FilterClass, , failover HKR, Ndi, FilterDeviceInfId, , ms_passthrump HKR, Ndi, Service, , Passthru HKR, Ndi\Interfaces, UpperRange, , noupper HKR, Ndi\Interfaces, LowerRange, , nolower HKR, Ndi\Interfaces, FilterMediaTypes, , "ethernet, tokenring, fddi, wan"