先说需求,我想知道指定PRocessID 和ProcessPath ,并且能得出对应的进程进出的数据。
这样就需要建立两个CallOuts驱动,一个Established v4层,另一个Stream v4层,第一个是用来获取进程ID和进程Path,
还有数据包包头信息(ip,prot,direction)。第二个是用来获取数据包(数据包实际数据大小,数据包内部具体信息)
首先建立了一个数据结构FLOW_DATA,用来存储Estabished Layer的数据。
因为肯定有很多条Estabished layer信息,所以建立list entry链表连起来。
typedef struct _FLOW_DATA{ LIST_ENTRY listEntry; UINT64 flowHandle; UINT64 flowContext; UINT64 calloutId; ULONG localAddressV4; USHORT localPort; USHORT ipProto; ULONG remoteAddressV4; USHORT remotePort; WCHAR* processPath; UINT64 processID; BOOLEAN deleting;} FLOW_DATA;要将进程与传输数据Connect上,先看一个函数:NTSTATUS NTAPI FwpsFlowAssociateContext0( IN UINT64 flowId, IN UINT16 layerId, IN UINT32 calloutId, IN UINT64 flowContext );flowId: inMetaValues->flowHandle(Established Layer的Classify函数中)layerId: 要连接的Layer(例如:FWPS_LAYER_STREAM_V4)calloutId: Stream layer的CallOut IDflowContext: 这个也就是建立的FLOW_DATA对象,用来存储Established layer所读出来的信息(进程ID,进程路径,ip...)因为我要做一个WFP进程监控驱动,所以就需要FwpsFlowAssociateContext函数来建立Established layer和Stream Layer的Association,所以用FLOW_DATA数据最后copy写的Established layer的Calssify函数,供参考:VOID NTAPI Established_ClassifyFn_V4( IN const FWPS_INCOMING_VALUES *inFixedValues,IN const FWPS_INCOMING_METADATA_VALUES *inMetaValues, IN OUT VOID *layerData,IN OPTIONAL const void *classifyContext,IN const FWPS_FILTER1 *filter,IN UINT64 flowContext, OUT FWPS_CLASSIFY_OUT *classifyOut){ KdPrint(("Wfp_Established_ClassifyFn_V4/n")); //存储基本包头信息 Word wDirection = 0; WORD wRemotePort = 0; WORD wSrcPort = 0; WORD wProtocol = 0; ULONG ulSrcIPAddress = 0; ULONG ulRemoteIPAddress = 0; UINT64 proID; FWP_BYTE_BLOB *proPath = NULL; ULONG Length = 0; FLOW_DATA *FlowContext = NULL; NTSTATUS Status = STATUS_SUCCESS; FlowContext = ExAllocatePoolWithTag(NonPagedPool,sizeof(FLOW_DATA),'FC'); do{ if (!FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_PATH)){ Status = STATUS_NOT_FOUND; break; } if (!(classifyOut->rights & FWPS_RIGHT_ACTION_WRITE)) return; //获得进程路径 proPath = inMetaValues->processPath; FlowContext->processPath = ExAllocatePoolWithTag(NonPagedPool,proPath->size,'pp'); memcpy(FlowContext->processPath, proPath->data, proPath->size); //获得进程ID proID = inMetaValues->processId; FlowContext->processID = proID; //wDirection表示数据包的方向,取值为 //FWP_DIRECTION_INBOUND/FWP_DIRECTION_OUTBOUND wDirection = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_DIRECTION].value.int8; //wSrcPort表示本地端口 FlowContext->localPort = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_PORT].value.uint16; //wRemotePort表示远端端口 FlowContext->remotePort = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_PORT].value.uint16; //ulSrcIPAddress 表示源IP FlowContext->localAddressV4 = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_LOCAL_ADDRESS].value.uint32; //ulRemoteIPAddress 表示远端IP FlowContext->remoteAddressV4= inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_REMOTE_ADDRESS].value.uint32; //wProtocol表示网络协议,可以取值是IPPROTO_ICMP/IPPROTO_UDP/IPPROTO_TCP wProtocol = inFixedValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_PROTOCOL].value.uint8; if (wDirection == FWP_DIRECTION_INBOUND){ KdPrint(("---IN BOUND/n")); } else if (wDirection == FWP_DIRECTION_OUTBOUND){ KdPrint(("---OUT BOUND/n")); } KdPrint(("ProcessID: %d/n", FlowContext->processID)); KdPrint(("Process Path: %ws/n",FlowContext->processPath)); KdPrint(("--SrcProt: %d/n",FlowContext->localPort)); KdPrint(("--RemoteProt: %d/n",FlowContext->remotePort)); UINT8 * srcIp = (UINT8 *)&(FlowContext->localAddressV4); KdPrint(("--SrcIp: %d,%d,%d,%d/n", srcIp[3],srcIp[2],srcIp[1],srcIp[0])); UINT8 * remIp = (UINT8 *)&(FlowContext->remoteAddressV4); KdPrint(("--RemoteIP: %d,%d,%d,%d/n",remIp[3],remIp[2],remIp[1],remIp[0])); //Establish layer Connect Stream layer UINT64 FlowHandle = inMetaValues->flowHandle; FlowContext->flowHandle = inMetaValues->flowHandle; Status = FwpsFlowAssociateContext(FlowHandle,FWPS_LAYER_STREAM_V4,g_uFwPSDataCallOutId,(UINT64)FlowContext); if (!NT_SUCCESS(Status)) classifyOut->actionType = FWP_ACTION_CONTINUE; //默认"允许"(PERMIT)classifyOut->actionType = FWP_ACTION_PERMIT;
} while (FALSE); //clear FWPS_RIGHT_ACTION_WRITE Tag if (filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT) classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE; return;}
参考文章:
http://bbs.pediy.com/thread-173871.htm
http://bbs.pediy.com/thread-212152.htm
新闻热点
疑难解答