先说需求,我想知道指定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 ID
flowContext: 这个也就是建立的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



Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐