驅動層 完成擷取進程網路流量模組(總結)

來源:互聯網
上載者:User

標籤:style   io   ar   os   使用   sp   for   on   資料   

xp平台下是使用TDI,win 7平台採用的是WFP的模式

WFP架構下思路

擷取進程ID  擷取進程的上傳資料大小和下載資料大小,然後儲存到鏈表中

鏈表中節點結構體如下:

typedef struct tagFlowInfoItem
{
    /**  鏈表結構
    */
    LIST_ENTRY  m_listEntry;

    /**  進程ID
    */
    HANDLE  m_processID;           

    /** 已上傳流量,BYTE為單位
    */
    UINT64 m_uploadFlow;             

    /** 已下載流量,BYTE為單位
    */
    UINT64 m_downloadFlow;           

    /** 上傳速度,BYTE為單位
    */
    ULONG m_uploadSpeed;           

    /** 下載速度,BYTE為單位
    */
    ULONG m_downloadSpeed;         
    
    /** 限制的上傳速度,BYTE為單位
    */
    ULONG m_limitUploadSpeed;       

    /** 限制的下載速度,BYTE為單位
    */
    ULONG m_limitDownloadSpeed;     
} FlowInfoItem;

wfp中是需要註冊callout函數的,進程id是在FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4層來擷取,而UDP和TCP流資料資訊(比如大小,內容)是在FWPM_LAYER_DATAGRAM_DATA_V4和FWPM_LAYER_STREAM_V4層來擷取的

,問題來了,在流註冊的callout函數中我們可以擷取到資料的大小,但是問題來了,怎麼樣把進程ID和對應的進程資料相對應???

//////////////////////////////////////////////////////////////////////////////////////////////////////

不斷的尋找資料,研究wdk文檔,wdk樣本,各種搜尋和qq群請教,(*^__^*) 嘻嘻……

//////////////////////////////////////////////////////////////////////////////////////////////////////

最終發現wdk的樣本中有相關的代碼可以參考一下,

目錄如下:C:\WinDDK\7600.16385.1\src\network\trans\msnmntr

主要是用到了一個FwpsFlowAssociateContext0函數,具體的用法看msdn或者範例程式碼使用,很簡單

一定要很仔細的看哦,這個函數有個很需要注意的地方,不然就藍藍更健康了哦,(關於DeleteFn函數的註冊和寫法)

這個FwpsFlowAssociateContext0函數的作用就是把進程id從FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4層傳遞到了FWPM_LAYER_DATAGRAM_DATA_V4和FWPM_LAYER_STREAM_V4層,然後我們就可以使用鏈表結構把進程id和進程的資料關聯起來了.


那麼如何識別是上傳資料還是下載資料呢?好問題

解析layerData中的streamData,streamData中有個標誌位,

上傳資料判斷:

和系統定義的宏FWPS_STREAM_FLAG_SEND和FWPS_STREAM_FLAG_SEND_EXPEDITED與(&)操作一下,不就可以得到是否是上傳了嗎?

下載資料判斷:

和上傳資料的方法類似.


最後說一句,在操作鏈結表的時候,記得加鎖.

xp下比win7下要簡單的多,而且TDI的資料也多.實現起來還是容易的多

VOID AnalyzeNetworkIrp(PIRP Irp)
{
    PEPROCESS Process;
    PIO_STACK_LOCATION IoStackLocation;
    NETWORK_USAGE_INFORMATION NetworkUsageInformation;
    //memset(&NetworkUsageInformation,0,sizeof(NETWORK_USAGE_INFORMATION));

    IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

    ASSERT(IoStackLocation->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
    
    Process = PsGetCurrentProcess();
    

    if (QueryProcessNetworkUsage(Process, &NetworkUsageInformation) == FALSE)
    {
        NetworkUsageInformation.BytesReceived = 0;
        NetworkUsageInformation.BytesSent = 0;
    }

    if (IoStackLocation->MinorFunction == TDI_RECEIVE)        //    TDI_RECEIVE
    {
        DbgPrint("Enter TCP 接收!\n");
        PTDI_REQUEST_KERNEL_RECEIVE Parameters;
        Parameters = (PTDI_REQUEST_KERNEL_RECEIVE)&IoStackLocation->Parameters;
        NetworkUsageInformation.BytesReceived += Parameters->ReceiveLength;
    }
    else if (IoStackLocation->MinorFunction == TDI_SEND)    //TDI_SEND
    {
        DbgPrint("Enter TCP 發送!\n");
        PTDI_REQUEST_KERNEL_SEND Parameters;
        Parameters = (PTDI_REQUEST_KERNEL_SEND)&IoStackLocation->Parameters;
        NetworkUsageInformation.BytesSent += Parameters->SendLength;
    }
    else if (IoStackLocation->MinorFunction == TDI_RECEIVE_DATAGRAM)        //TDI_RECEIVE_DATAGRAM
    {
        DbgPrint("Enter UDP 接收!\n");
        PTDI_REQUEST_KERNEL_RECEIVEDG Parameters;
        Parameters = (PTDI_REQUEST_KERNEL_RECEIVEDG)&IoStackLocation->Parameters;
        NetworkUsageInformation.BytesReceived += Parameters->ReceiveLength;
    }
    else if (IoStackLocation->MinorFunction == TDI_SEND_DATAGRAM)            //TDI_SEND_DATAGRAM
    {
        DbgPrint("Enter UDP 發送!\n");
        PTDI_REQUEST_KERNEL_SENDDG Parameters;
        Parameters = (PTDI_REQUEST_KERNEL_SENDDG)&IoStackLocation->Parameters;
        NetworkUsageInformation.BytesSent += Parameters->SendLength;
    }
    else if (IoStackLocation->MinorFunction == TDI_CONNECT) //本機向外界發起串連請求
    {
        DbgPrint("Enter Connect!\n");
        PTDI_REQUEST_KERNEL_SENDDG Parameters;
        Parameters = (PTDI_REQUEST_KERNEL_SENDDG)&IoStackLocation->Parameters;
        NetworkUsageInformation.BytesSent += Parameters->SendLength;
    }
    else if (IoStackLocation->MinorFunction == TDI_ACCEPT)//外界向本機發起串連請求
    {
        DbgPrint("Enter Accept!\n");
        PTDI_REQUEST_KERNEL_RECEIVEDG Parameters;
        Parameters = (PTDI_REQUEST_KERNEL_RECEIVEDG)&IoStackLocation->Parameters;
        NetworkUsageInformation.BytesReceived += Parameters->ReceiveLength;
    }

    // 更新進程的網路使用方式
    UpdateProcessNetworkUsage(Process, &NetworkUsageInformation);

    return;
}

VOID UpdateProcessNetworkUsage(
    __in PEPROCESS Process,
    __in PNETWORK_USAGE_INFORMATION NetworkUsageInformation
    )
{
    KLOCK_QUEUE_HANDLE LockHandle;

    KeAcquireInStackQueuedSpinLock(&NetworkUsageGenericTable.TableLock,&LockHandle);

    UpdateProcessNetworkUsageUnsafe(Process, NetworkUsageInformation);

    KeReleaseInStackQueuedSpinLock(&LockHandle);
    return;
}


VOID UpdateProcessNetworkUsageUnsafe(
    __in PEPROCESS Process,
    __in PNETWORK_USAGE_INFORMATION NetworkUsageInformation
    )
{
    NETWORK_USAGE_GENERIC_TABLE_NODE TableNode;
    PVOID EntryFound;

    TableNode.Process = Process;
    TableNode.NetworkUsageInformation = *NetworkUsageInformation;

    EntryFound = RtlLookupElementGenericTable(&NetworkUsageGenericTable.Table,
        (PVOID)&TableNode);

    if (EntryFound)
    {
        BOOLEAN Status;

        Status = RtlDeleteElementGenericTable(&NetworkUsageGenericTable.Table, EntryFound);

        ASSERT(Status == TRUE);
    }

    (VOID)RtlInsertElementGenericTable(&NetworkUsageGenericTable.Table,
        (PVOID)&TableNode, sizeof(NETWORK_USAGE_GENERIC_TABLE_NODE), NULL);

    return;
}

//網路使用方式結構體定義
typedef struct _NETWORK_USAGE_INFORMATION {

    ULONGLONG BytesSent;
    ULONGLONG BytesReceived;
} NETWORK_USAGE_INFORMATION, *PNETWORK_USAGE_INFORMATION;


typedef struct _NETWORK_USAGE_GENERIC_TABLE_NODE {
    PEPROCESS Process;
    //UINT32 uProcessID;
    NETWORK_USAGE_INFORMATION NetworkUsageInformation;
} NETWORK_USAGE_GENERIC_TABLE_NODE, *PNETWORK_USAGE_GENERIC_TABLE_NODE;


typedef struct _NETWORK_USAGE_GENERIC_TABLE {
    RTL_GENERIC_TABLE Table;

    KSPIN_LOCK TableLock;
    KSPIN_LOCK TrafficLock;
} NETWORK_USAGE_GENERIC_TABLE, *PNETWORK_USAGE_GENERIC_TABLE;


NETWORK_USAGE_GENERIC_TABLE NetworkUsageGenericTable;

思路如此,TDI的實現大家實現起來不難,我就不多說了,顯得很嘮叨煩人,嘿嘿

驅動層 完成擷取進程網路流量模組(總結)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.