首页
社区
课程
招聘
[分享]如何把NDIS Filter框架利用到日常的Windows驱动开发工作中
发表于: 2014-8-20 18:48 28361

[分享]如何把NDIS Filter框架利用到日常的Windows驱动开发工作中

2014-8-20 18:48
28361

以前,我在看雪发表了一篇文章,文章如下。

【原创】NDIS中间层驱动开发在Win7系统下和Windows XP系统下的区别
http://bbs.pediy.com/showthread.php?t=137545

当时,我只写了一个大概,抛砖引玉,讲述了NDIS Filter框架,告诉大家NDIS Filter大概怎么用,有什么样的变动。

最近这几年,Windows8和Windows8.1操作系统逐渐地成为主流,被越来越多人使用。而网络上有关NDIS驱动开发的文章,还都是停留在NDIS Passthru。

基于NDIS Filter框架的网络数据包,它的格式是以NET_BUFFER_LIST、NET_BUFFER、MDL为主导的。
每一个的NET_BUFFER_LIST结点都是由一个NET_BUFFER链表组成,而每一个NET_BUFFER结点是由1个MDL链表组成。但网络数据包含了 多个NET_BUFFER_LIST

网络数据结构如下图所示:



你可以按照我的下述2种程序代码的实现方法,来获取数据包的内容。你可以把代码直接添加到你的NDIS Filter工程代码里面。

下面的代码,我测试通过。

代码编译环境:
Visual Studio 2013
WDK8.1

测试通过的Windows系统有:
32位Windows7
64位Windows7

32位Windows8
64位Windows8

32位Windows8.1
64位Windows8.1

WindowsXP,不支持 NDIS Filter框架。

这个帖子的附件是一个完整的NDIS Filter工程代码,可直接下载,编译。必须在Visual Studio 2013和WDK8.1环境下进行。
基本上不蓝屏幕。如果发生蓝屏的情况,请不要着急,你可以在代码中找到如下的宏定义:
#define         MAX_BUFFER_SIZE  1024*8

你把这个MAX_BUFFER_SIZE 宏修改成你所想要的大小。这样就不蓝屏了。我建议最好是更大一些。最好大于 1024*8

代码在编译的时候,会出现错误:
  error C2220: warning treated as error - no 'object' file generated        D:\NdisLwfDemo\NdisLwfDemo\filter.c        1328

你在Visual Studio 2013环境下配置。图如下:



你把Warning Level修改成:   Turn Off All Warnings(/W0)
这样,就编译正确了。

第一种方法:

VOID
PSQueryPacketLength(
                                IN PNET_BUFFER_LIST Packet,
                                OUT OPTIONAL PUINT32 Length
                         )

{
        PNET_BUFFER pNetBuffer = NET_BUFFER_LIST_FIRST_NB(Packet);
        BOOLEAN FLAG = FALSE;

        do
        {
                if (NULL == Length)
                {
                        break;
                }

                *Length = 0;

                while (pNetBuffer)
                {
                        *Length += NET_BUFFER_DATA_LENGTH(pNetBuffer);
                        pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer);
                }
        } while (FLAG);
       
        return;
}

BOOLEAN
GetOneNetBufferListData(
                        __in PNET_BUFFER_LIST Packet,
                        __out PUCHAR* pBuf,
                        __out PUINT32 BufLen
                                           )
{
        NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
        PNET_BUFFER_LIST pCurrentNBL = NULL;
        PNET_BUFFER pCurrentNB = NULL;
        int lTotalLength = 0;
        PMDL pMdl = NULL;       
        PUCHAR pData = NULL;
        int lOffset = 0;
        int lDataBufferLen = 0;
        int lBytesToCopy = 0;
        int lMdlOffset = 0;

        pCurrentNBL = Packet;
        PSQueryPacketLength(pCurrentNBL,(PUINT32)&lTotalLength);

        if (lTotalLength != 0)
        {
                pBuf=ExAllocatePoolWithTag(NonPagedPool,lTotalLength,'tag1');
                if (NULL == *pBuf)
                {
                        DEBUGP(DL_WARN,("%s: Allocate memory failed! Status=0x%08x\n",__FUNCTION__,Status));
                        return FALSE;
                }
        }
        else
        {
                DEBUGP(DL_WARN,("%s: The packet is an invalid packet!\n",__FUNCTION__));
                return FALSE;
        }

        NdisZeroMemory(pBuf,lTotalLength);
        *BufLen = (UINT32)lTotalLength;

        pCurrentNB = NET_BUFFER_LIST_FIRST_NB(pCurrentNBL);

        while (pCurrentNB)
        {
                pMdl = NET_BUFFER_CURRENT_MDL(pCurrentNB);
                lMdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNB);

                while(pMdl)
                {

                        NdisQueryMdl( pMdl,(PVOID *)&pData,&lDataBufferLen,NormalPagePriority );

                        //NBL->DataLength <= MDL1->ByteCount+ MDL2->ByteCount+........+ MDLx->ByteCount  -  NBL->CurrentMDLOffset.
                        //这里 Data length 不等于 Buffer Length
                        lBytesToCopy =min( lDataBufferLen - lMdlOffset, lTotalLength);

                        NdisMoveMemory(
                                (pBuf+ lOffset),
                                pData + lMdlOffset,
                                lBytesToCopy
                                );
                        lTotalLength -= lBytesToCopy;
                        lOffset += lBytesToCopy;

                        //一般来说,只有第一个MDL的buffer才有偏移,其余的都没有。
                        //如果offset大于了buflen,那么第一个MDL就没有存在的意义了。

                        lMdlOffset = 0;

                        NdisGetNextMdl(pMdl, &pMdl); //pMdl = pMdl->Next;
                }

                pCurrentNB = NET_BUFFER_NEXT_NB(pCurrentNB);

        }//end while(pCurrentNB)               

        //当while循环结束以后,pBuf保存的是:一整个NET_BUFFER_LIST里面的数据内容。

       
        ExFreePoolWithTag(pBuf, 'tag1');//不需要pBuf了,这里把它释放掉

        return TRUE;
}

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

第二种方法:

/*******************************************************************
GetNetBufferData函数的功能:
从1个NET_BUFFER里面获取数据。1个NET_BUFFER里面含有1个或者多个的MDL
*******************************************************************/
VOID GetNetBufferData(
        PNET_BUFFER                NetBuffer,
        PUCHAR                        OutputBuffer,
        ULONG                        OutputBufferSize,
        PULONG                        OutputBytesCopied
        )

{

        PMDL        Mdl = NetBuffer->CurrentMdl;
        *OutputBytesCopied = 0;

        if (NetBuffer->DataLength > OutputBufferSize)
        {
#if DBG
                DbgPrint("Not enough output buffer space, in: %d, out : %d\n",
                        NetBuffer->DataLength,
                        OutputBufferSize);

#endif
                return;
        }

        NdisMoveMemory(OutputBuffer,
                (PUCHAR)MmGetSystemAddressForMdlSafe(Mdl, LowPagePriority) + NetBuffer->CurrentMdlOffset,
                Mdl->ByteCount - NetBuffer->CurrentMdlOffset);

       
        OutputBuffer += Mdl->ByteCount - NetBuffer->CurrentMdlOffset;
        *OutputBytesCopied += Mdl->ByteCount - NetBuffer->CurrentMdlOffset;

        //
        //循环 MDL链表,获取每一个结点的数据,数据被保存到 OutputBuffer里面
        //OutputBuffer的空间不断地扩大。

        //当链表不为空, 并且 OutputBuffer的长度 < 1个NET_BUFFER的总长度

        while ( ((Mdl = Mdl->Next)!=NULL) && (*OutputBytesCopied < NetBuffer->DataLength) )
        {
                NdisMoveMemory(OutputBuffer,
                        MmGetSystemAddressForMdlSafe(Mdl, LowPagePriority),
                        Mdl->ByteCount);

                OutputBuffer += Mdl->ByteCount;          //数据被保存到 OutputBuffer里面
                *OutputBytesCopied += Mdl->ByteCount;    //OutputBuffer的空间不断地扩大
        }

        if (Mdl != NULL)
        {
                NdisMoveMemory(OutputBuffer,
                        MmGetSystemAddressForMdlSafe(Mdl, LowPagePriority),
                        NetBuffer->DataLength);

                OutputBuffer += Mdl->ByteCount;
                *OutputBytesCopied += Mdl->ByteCount;
        }

#if DBG
        DbgPrint("buffer copied: %d bytes\n", *OutputBytesCopied);
#endif

}

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

上面的2种方法,只是获取数据。

而原本NDIS Filter框架提供的这4个函数默认的代码,都没有做任何操作,没有实质性质的功能,
这4个函数原本默认的代码,我们都不需要, 因为我们的驱动程序需要处理网络数据包。

这4个函数分别是:

FilterSendNetBufferListsComplete
FilterSendNetBufferLists
FilterReturnNetBufferLists
FilterReceiveNetBufferLists

在我们的NDIS Filter工程里面,我们需要修改掉这4个函数的功能,把它们替换成我们所想要的功能。

比如,你在发送数据包或者接收数据包的时候,需要实现自己的一些业务逻辑,而不是去使用Microsoft NDIS Filter提供的原始代码的功能。

这4个函数的功能被替换如下:

//////////////////////////////开始把4个函数的功能替换成我们自己的代码///////////////////////////////////

/**************************************************************
  FilterSendNetBufferListsComplete函数的功能:
   NDIS调用 FilterSendNetBufferListsComplete 把发送的结构和数据返还给 Filter Driver。NDIS可以收集多次NdisFSendNetBufferLists发送的结构和数据形成一个单链表传递给FilterSendNetBufferListsComplete。除非到NDIS调用FilterSendNetBufferListsComplete,否则一个发送请求的当前状态总是未知的。

   一个过滤驱动是不能在NDIS调用FilterSendNetBufferListsComplete返回结构之前对NET_BUFFER_LIST和其关联的数据做检查的。FilterSendNetBufferListsComplete要完成一个发送请求完成后的任何必要的后继处理。当NDIS调用FilterSendNetBufferListsComplete时,Filter Driver就重新获地对结构及结构相关资源的所有权。可以在 FilterSendNetBufferListsComplete中释放相关的资源和准备下一个NdisFSendNetBufferLists调用。
  
   NDIS总是按照过滤驱动调用NdisFSendNetBufferLists提交的顺序传递给下层驱动,但是回返FilterSendNetBufferListsComplete 的顺序则是任意的。Filter Driver可以请求一个回环发送请求,只要把NdisFSendNetBufferLists的SendFlags设置成NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK就行了。NDIS会引发一个包含发送数据的接收包指示。
   
   
   一个Filter Driver应该对自己引发的发送请求保持跟踪并确保在完成时不调用NdisFSendNetBufferComplete例程。
  **************************************************************/

_Use_decl_annotations_
VOID
FilterSendNetBufferListsComplete(
        NDIS_HANDLE         FilterModuleContext,
        PNET_BUFFER_LIST    NetBufferLists,
        ULONG               SendCompleteFlags
        )

{
                PMS_FILTER         pFilter = (PMS_FILTER)FilterModuleContext;

#if DBG
                DbgPrint(">>> FilterSendNetBufferListsComplete: %p\n\n", NetBufferLists);
#endif

                NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, SendCompleteFlags);

}

/*************************************************************
FilterSendNetBufferLists函数的功能:
   NDIS调用一个Filter Driver的FilterSendNetBufferLists例程来过滤上层驱动的发送请求。Filter Driver不能改变其它驱动传来的NET_BUFFER_LIST结构中的SourceHandle成员的值。它可以过滤数据并发送过滤的数据到下层驱动。
   对每一个提交到FilterSendNetBufferLists的NDIS_BUFFER_LIST,我们可做下面的操作。
   
   1)可以把缓冲区通过 NdisFSendBufferLists 传递给下层驱动,NDIS 保证上下文空间对FilterDriver的有效性。过滤驱动可以在发送前修改缓冲区的内容。可以像处理自己引发的发送请求的缓冲区一样处理这个缓冲区。   
   2)可以调用 NdisFSendNetBufferListsComplete 拒绝传递这个包
   3)排队缓冲区内容到本地的供以后处理。例如要在一定超时后处理或要接收到特定包后才处理等。如果支持这种处理方式就要支持取消请求的操作。     
   4)可以拷贝缓冲区并引发一个发送请求。它类似自己引发一个发送请求,但必须先调用 NdisFSendNetBufferComplete返回上层驱动的缓冲区。
      
   发送请求在驱动栈继续完成,当一个微端口驱动调用NdisMSendNetBufferListsComplete完成一个发送请求时,NDIS会调用微端口
   驱动之上最近的Filter Driver的FilterSendNetBufferLists例程。
   
   在一个发送操作完成后,Filter Driver可以做在FilterSendNetBufferLists中所有修改的相反操作。FilterSendNetBufferListsComplete返回一个NET_BUFFER_LIST结构的单链表和发送请求的最终状态给上层的驱动。当最顶层的 Filter Module的FilterSendNetBufferListsComplete被调用完成后NDIS会调用引发发送请求的协议驱动的ProtocolSendNetBufferListsComplete。如果Filter Driver不提供FilterSendNetBufferLists它还是可以引发一个发送操作的,但它必须提供一个FilterSendNetBufferListsComplete并且不能在这个例程里把这个事件传递给上层驱动。

   一个Filter Driver可以传递或过滤一个上层驱动的回环请求,要传递一个回环请求,NDIS会设置FilterSendNetBufferLists的SendFlags参数为NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK,Filter Driver在调用NdisFSendNetBufferLists时把这个标记传给它即可。在回环请求的情况下NDIS会指示一个包含发送数据的接收包。

   通常情况下,如果一个Filter Driver修改的任何行为不是NDIS提供的标准服务,那么它应该当自己为NDIS提供相应的服务。例如,如果一个Filter Driver修改了一个硬件地址请求,就必须处理直接到这个新地址回环包。在这种情况下, 因为Filter Driver已经更改了地址NDIS是不能提供一个回环服务的。
   还有就是如果Filter Driver设置了混杂模式那它就不能传递额外的数据给上层接收。
**************************************************************/
_Use_decl_annotations_
VOID
FilterSendNetBufferLists(
        NDIS_HANDLE         FilterModuleContext,
        PNET_BUFFER_LIST    NetBufferLists,
        NDIS_PORT_NUMBER    PortNumber,
        ULONG               SendFlags
        )

{
        PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;
        PNET_BUFFER                        NetBuffer;
        UCHAR                                TempBuffer[MAX_BUFFER_SIZE];
        ULONG                                BytesCopied;
        pEthHdr                                EthernetHeader;
        pIPHdr                                IpHeader;

#if DBG
        DbgPrint(">>> FilterSendNetBufferLists: %p\n", NetBufferLists);
#endif

        for (NetBuffer = NetBufferLists->FirstNetBuffer;
                NetBuffer!= NULL;
                NetBuffer = NetBuffer->Next)

        {
                GetNetBufferData(NetBuffer, TempBuffer, MAX_BUFFER_SIZE, &BytesCopied);
                if (BytesCopied == 0)
                {
#if DBG
                        DbgPrint("Net buffer catch error\n");
#endif
                }
                else
                {
                        EthernetHeader = TempBuffer;
                        if (EthernetHeader->Type == 0x0800)//以太网类型
                        {
                                IpHeader = EthernetHeader + sizeof(EthHdr); //去掉以太网头,抓出IP头
#if DBG
                                DbgPrint("Get ip packet\n");
#endif
                        }
                }

        }

        NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);
}

/*************************************************************
  FilterReturnNetBufferLists函数的功能:
   如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists
   返回指示数据。在这种情况下 Filter Driver失去了对NET_BUFFER_LIST的所有权,直到FilterReturnNetBufferLists被调用。

   Filter Driver调用NdisFIndicateNetBufferLists 传递接收指示给驱动栈上的上层驱动,如果上层驱动保留了对缓冲区(NET_BUFFER_LIST)的所有权,NDIS会调用Filter Driver的FilterReturnNetBufferLists 例程。
   
   在FilterReturnNetBufferLists中应该撤消在接收路径上(如在 FilterReciveNetBufferLists中做的一些处理)的操作。当最底层的Filter Module完成对缓冲区(NET_BUFFER_LIST)的处理后,NDIS把缓冲区返回给微端口驱动。如果FilterReceiveNetBufferLists的ReceiveFlags没有设置NDIS_RECEIVE_FLAGS_RESOURCES标记, FilterDriver调用NdisFReturnNetBufferList返回这个缓冲区数据,如果设置了FilterReceiveNetBufferLists直接返回时就把缓冲区返还给了下层微端口驱动。  
  ***************************************************************/
_Use_decl_annotations_
VOID
FilterReturnNetBufferLists(
        NDIS_HANDLE         FilterModuleContext,
        PNET_BUFFER_LIST    NetBufferLists,
        ULONG               ReturnFlags
        )

{
        PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;
#if DBG
        DbgPrint(">>> FilterReturnNetBufferLists: %p\n\n", NetBufferLists);
#endif
        NdisFReturnNetBufferLists(pFilter->FilterHandle, NetBufferLists, ReturnFlags);

}

/***************************************************************
  FilterReceiveNetBufferLists函数的功能:
   Filter Driver调用 NdisFIndicateReceiveNetBufferLists来指示发送数据。这个函数通过NET_BUFFER_LIST结构给上层驱动指示数据。Filter Driver可以从池中分配这个结构。如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为 NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists返回指示数据。在这种情况下Filter Driver失去了对NET_BUFFER_LIST的所有权直到FilterReturnNetBufferLists被调用。如果Filter Driver在调用NdisFIndicateReceiveNetBufferLists时设置ReceiveFlags为NDIS_RECEIVE_FLAGS_RESOURCES,在函数返回后Filter Driver会立即恢复对NET_BUFFER_LIST的所有权,这时Filter Driver必须立即处理这个NET_BUFFER_LIST的返回,因为NDIS在这种情况下是不会调用FilterReturnNetBufferLists返回NET_BUFFER_LIST结构的。

   注意: 一个Filter Driver应该跟踪自己引发的接收指示确保它在FilterReturnNetBufferLists
   中不调用NdisFReturnNetBufferLists。
  ***************************************************************/
_Use_decl_annotations_
VOID
FilterReceiveNetBufferLists(
        NDIS_HANDLE         FilterModuleContext,
        PNET_BUFFER_LIST    NetBufferLists,
        NDIS_PORT_NUMBER    PortNumber,
        ULONG               NumberOfNetBufferLists,
        ULONG               ReceiveFlags
        )

{
        PMS_FILTER                                        pFilter = (PMS_FILTER)FilterModuleContext;
        PNET_BUFFER                                        NetBuffer;
        UCHAR                                                TempBuffer[MAX_BUFFER_SIZE];
        ULONG                                                BytesCopied;
        pEthHdr                                                EthernetHeader;
        pIPHdr                                                IpHeader;

#if DBG
        DbgPrint(">>> FilterReceiveNetBufferLists: %p\n", NetBufferLists, ReceiveFlags, NumberOfNetBufferLists);
#endif

        do
        {

                for (NetBuffer = NetBufferLists->FirstNetBuffer;
                        NetBuffer != NULL;
                        NetBuffer = NetBuffer->Next)

                {
                        GetNetBufferData(NetBuffer, TempBuffer, MAX_BUFFER_SIZE, &BytesCopied);
                        if (BytesCopied == 0)
                        {
#if DBG
                                DbgPrint("Net buffer catch error\n");
#endif
                        }
                        else
                        {
                                EthernetHeader = TempBuffer;
                                if (EthernetHeader->Type == 0x0800)
                                {
                                        IpHeader = EthernetHeader + sizeof(EthHdr);
#if DBG
                                        DbgPrint("IP packet exist\n");
#endif
                                }
                        }

                }

        } while (FALSE);

/************************************************************
调用 NdisFIndicateReceiveNetBufferLists来指示发送数据。

如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的状态为NDIS_STATUS_SUCCESS, NDIS通过驱动的FilterReturnNetBufferLists 返回指示数据。
     
如果Filter Driver设置了NdisFIndicateReceiveNetBufferLists的ReceiveFlags值为NDIS_RECEIVE_FLAGS_RESOURCES,
那么在函数返回后Filter Driver会立即恢复对NET_BUFFER_LIST的所有权,这时Filter Driver必须立即处理这个NET_BUFFER_LIST的返回。
在这种情况下是不会调用FilterReturnNetBufferLists返回NET_BUFFER_LIST结构的。
************************************************************/

        NdisFIndicateReceiveNetBufferLists(
                pFilter->FilterHandle,
                NetBufferLists,
                PortNumber,
                NumberOfNetBufferLists,
                ReceiveFlags);

}

////////////////////////////////结束原本4个函数的功能替换//////////////////////////////////////////

这里是完整的工程代码, 希望能够给你带来好运。

NdisLwfDemo.rar


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 3
支持
分享
最新回复 (29)
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
2
收藏...
2014-8-20 18:55
0
雪    币: 19
活跃值: (1086)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
这帖子真好 学习了
2014-8-20 18:59
0
雪    币: 114
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢楼主分享~
2014-8-20 19:04
0
雪    币: 406
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
不错......
2014-8-20 23:57
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
mark下,有用。
2014-8-21 00:34
0
雪    币: 18
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
请问一下楼主,ndis filter在两种模式下安装的时候会向中间层驱动那样断网么
2014-8-21 11:00
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
中间层也不断网,中间层的原理是服务,而非DDM
2014-8-21 11:28
0
雪    币: 18
活跃值: (26)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
谢谢你的回答,我是想知道filter驱动在安装的时候会不会断网。中间层驱动安装的时候会短暂断开网络加载完成后恢复联网。
2014-8-21 13:15
0
雪    币: 23
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
安装必须断,不断不行地,装上以后不用动地
2014-8-21 13:17
0
雪    币: 53
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
楼主你好,按照你的方法我试了一下,遇到很多问题,自己也尝试解决,但是能力有限,相信很多新手也想问这些问题,所以贴出来问问。

1.我先安装了vs2013,再安装wdk8.1


2.关闭警告


3.编译还是报错如下



请大家看看问题在哪,谢谢。
上传的附件:
2014-10-8 20:50
0
雪    币: 557
活跃值: (449)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
12
这位朋友,你好!
Visual Studio 2013环境,可以正常编译驱动程序,没有出现错误。
我编译后的过程如下图所示:






你看,在Win8和Win8.1系统下,都可以正常编译通过。
上传的附件:
2014-10-9 09:27
0
雪    币: 53
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
编译通过了,楼主的代码没问题,自己装wdk的时候不知道怎么弄的,出现了两个wdk

我把8.0那个文件夹里面内容全部剪切到8.1里面覆盖就行了,奇葩的问题。
上传的附件:
2014-10-9 22:06
0
雪    币: 217
活跃值: (35)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
要断网的。。。想不断网的话,玩hook。先装一个filter驱动,然后在各个函数处下断,看callstack,就知道如何hook了。
2014-10-9 22:20
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
15
暂时用不上,帮顶~
2014-10-11 17:28
0
雪    币: 1821
活跃值: (1928)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
谢谢楼主分享~
2014-10-11 18:21
0
雪    币: 69
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
17
....
2014-10-11 18:59
0
雪    币: 3236
活跃值: (264)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
还在使用XP的路过
2014-10-12 16:39
0
雪    币: 7
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
楼主,你提到  //一般来说,只有第一个MDL的buffer才有偏移,其余的都没有。

但是我这里打印的MDL都不为0啊,抓的包打印和wireshark抓的也不一样。怎么回事儿啊?刚学习这个,不懂,多多指点啊。

上传的附件:
2014-10-24 11:36
0
雪    币: 7
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
又搜索了下,改成下面的了,这下和wireshark抓的包都一样了,是改的FilterReceiveNetBufferLists,但是这个函数不是收包吗?为什么出的包也能抓到?:

    DEBUGP(DL_ERROR, "NumberOfNetBufferLists is %u .\n", NumberOfNetBufferLists);
		FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
		pNBL = NetBufferLists;
		while (pNBL)
		{
			DEBUGP(DL_ERROR, "Print NBL %p NBL->NEXT %p \n", pNBL, pNBL->Next);
			pNB = NET_BUFFER_LIST_FIRST_NB(pNBL);
			
			while (pNB)
			{
				DEBUGP(DL_ERROR, "Print NB %p NB->NEXT %p\n", pNB, pNB->Next);
				pMdl = NET_BUFFER_CURRENT_MDL(pNB);
				lMdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pNB);
				lDataLen = NET_BUFFER_DATA_LENGTH(pNB);
				
				while (pMdl)
				{
					NdisQueryMdl(pMdl, (PVOID*)&pData, &lDataBufferLen, LowPagePriority);
					lBytesToCopy = lDataBufferLen - lMdlOffset;
					DEBUGPDUMP(DL_ERROR, pData + lMdlOffset, lDataLen > lBytesToCopy ? lBytesToCopy : lDataLen);
					lMdlOffset = 0;
					DEBUGP(DL_ERROR, "MDL offset %u lBytesToCopy %d pMdl->ByteCount %u lDataLen %u \n", pMdl->ByteOffset, lBytesToCopy, pMdl->ByteCount, lDataLen);
					
					if (lDataLen > lBytesToCopy)
					{
						DEBUGP(DL_ERROR, "%u Byte to copy \n", lDataLen - lBytesToCopy);
						lDataLen -= lBytesToCopy;
					}
					else
					{
						DEBUGP(DL_ERROR, "Data copy complete \n");
					}
					
					NdisGetNextMdl(pMdl, &pMdl); // pMdl = pMdl->Next;
				}
				
				DEBUGP(DL_ERROR, "%p NB print complete .\n", pNB);
				pNB = NET_BUFFER_NEXT_NB(pNB); // pNB = pNB->Next;
			}
			
			DEBUGP(DL_ERROR, "%p NBL print complete .\n", pNBL);
			pNBL = NET_BUFFER_LIST_NEXT_NBL(pNBL); // pNBL = pNBL->Next;
		}

		FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
		DEBUGP(DL_ERROR, "Print data complete .\n");
2014-10-24 15:37
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
谢谢分享,很有用
2015-3-26 10:51
0
雪    币: 278
活跃值: (83)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
要不楼主自己开个驱动相关的论坛吧
2015-4-15 20:54
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
暂时不用,,帮忙顶了
2015-6-4 21:31
0
雪    币: 1994
活跃值: (1526)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
24
田sir发的。。。。。
2015-6-10 09:16
0
雪    币: 69
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
暂时用不上,帮顶~
2015-6-10 10:46
0
游客
登录 | 注册 方可回帖
返回
//