1. 在windows平台下的底层开发应该有什么样的学习路线
1.语言C/C++(参考书籍:<<C/C++ Primer>> ,<<C和指针>>,<<数据结构C语言描述>>)),汇编(王爽的汇编语言,作为入门,参考Intel手册,之后参考看雪的<<加密与解密>>,了解PE文件的格式,加壳脱壳和病毒感染的手法,如果是开发的话,只需要了解即可,能用反汇编调试工具去做简单的CrackMe即可),这个阶段大约是大一大二的时间,除去老师上课教的C语言基础,80x86汇编语言以为,很多知识都是自己去扩展。
2.windows api(win32sdk) 参考书籍(《Windows程序设计》,《Windows核心编程》,MFC之类的需要使用的时候在参考即可,不必花费太多精力,主要是去了解程序的消息机制,事件等等,应该把主要的精力比如线程注入,Ring3的各种HOOK等。这个阶段是大二下学期的时间,说实话,我这个方面看的太少了,花了好多时间在一些没有意义的事情上,导致到大三的时候参加信息安全比赛做驱动的时候经验严重不足,所以基础太重要了)
3.然后就是winows驱动内核的开发(参考书籍,寒江独钓,张帆的Windows驱动开发技术详解,WDK上的各种示例代码) 熟悉各种过滤驱动框架(文件过滤驱动,文件微过滤驱动,tdi,ndis协议,ndis中间层,ndis小端口等等)。
然后就是各种系统底层的原理,进程创建的流程,文件创建的流程,进程间通信的过程,用各种调试,反汇编工具(od,ida,windbg)去跟踪分析,可以写一些Rootkit/Anti-Rootkit工具,比如对于进程隐藏和保护,有SSDT HOOK OpenProcess,摘除进程链表等等,这样有助于对系统底层机制的理解
4.后期就是经验和内功了,什么《深入解析Windows操作系统》,《TCP/IP》卷123,《Windows内核原理与实现》等等,说白了,个人认为,底层开发对于调试的功力要求很高,能从蓝屏的mp文件出有用的信息
2. 求个简单的防火墙源代码
防火墙源代码网络上是有的,我也写过一套,不过我写的不是针对客户端计算机的,是针对服务器的, 目前客户端防火墙开发上使用 大致分为3种技术 1、SPI 会话层过滤的,做行为控制比较好。2、TDI 传输层过滤驱动,性能要比SPI好。3、NDIS中间层过虑驱动,也是目前几大防火墙厂家常用的计算机。 第一种防火墙 可以满足你需要的功能,下载地址 http://down.cnzz.cn/info/6548.aspx 开发语言VC++6.0如果你想研究 第三种技术,并且也顺带 第一种技术的源代码,目前没有免费的。要通过付款购买的 http://www.filseclab.com/procts/source.htm
3. 个人防火墙的数据类型
用户态(user-mode)和内核态(kernel-mode)。
1)用户态(user-mode)。
在用户态下进行网络数据包的拦截有三种方法:WinsockLayeredServiceProvider(LSP)、Windows2000包过滤接口、替换系统自带的WINSOCK动态连接库。在用户态下
进行数据包拦截最致命的缺点就是只能在Winsock层次上进行,而对于网络协议栈中底层协议的数据包无法进行处理。因此,这些方法并不适合个人防火墙。
2)内核态(kernel-mode)。
a)TDI过滤驱动程序(TDIFilterDriver)。当应用程序要发送或接收网络数据包的时候,都是通过与协议驱动所提供的接口来进行的。协议驱动提供了一套系统预定义的标准接口来和应用程序之间进行交互。因此,只需要开发一个过滤驱动来截获这些交互的接口,就可以实现网络数据包的拦截。在Windows2000/NT下,ip,tcp,udp是在一个驱动程序里实现的,叫做tcp.sys,这个驱动程序创建了5个设备:DeviceRawIp,DeviceUdp,DeviceTcp,DeviceIp,DeviceMULTICAST。应用程序所有的网络数据操作都是通过这些设备进行的。因此,我们只需要开发一个过滤驱动来截获这些交互的接口,就可以实现网络数据包的拦截。另外,TDI层的网络数据拦截还可以得到操作网络数据包的进程详细信息,这也是个人防火墙的一个重要功能。但是,TDI传输驱动程序有一个缺陷,TDIFilterdriver属于Upperdriver,位于TcpIP.sys之上,这就意味着由TcpIP.sys接收并处理的数据包不会传送到上层,从而无法过滤某些接收的数据包,例如ICMP包。ICMP的应答包直接由TcpIP.sys生成并回应,而上面的过滤驱动程序全然不知。另外,该方法需要在系统核心层编写驱动程序,需要编写人员对Windows操作核心层的工作机制非常熟悉,同时,驱动程序对代码质量要求非常高,稍有不慎就会使系统崩溃,
b)Win2kFilter-HookDriver。这是从Windows2000开始系统所提供的一种驱动程序,该驱动程序主要是利用Ipfiltdrv.sys所提供的功能来拦截网络数据包。Filter-HookDriver的结构非常简单,易于实现。但是正因为其结构过于简单,并且依赖于Ipfiltdrv.sys,Microsoft并不推荐使用Filter-HookDriver。
c)NDISHookDriver。该方法在Windows2000/xp下是非公开的,因此这种方法对平台的依赖性比较大,需要在程序中判断不同的操作系统版本而使用不同的方法。
d)NDIS中间层驱动程序(NDISIntermediateDriver)。NDIS()是Microsoft和3Com公司开发的网络驱动程序接口规范的简称,它支持如下三种类型的网络驱动程序:微端口驱动程序、中间层驱动程序(IntermediateDriver)和协议驱动程序。其中中间层驱动介于协议层驱动和小端口驱动之间,其功能非常强大,可以提供多种服务,能够截获所有的网络数据包(以太帧),过滤微端口驱动程序,实现特定的协议或其他诸如数据包加密、认证等功能。综上所述,在NDIS中间层进行网络数据包截获的方法结构规范,功能强大,该技术极其适合个人防火墙所采用。
中间层驱动程序(NDIS)的内部结构
NDIS支持3种驱动:微端口驱动,中间层驱动和协议驱动。
1) 微端口驱动。就是网卡驱动,它负责管理网卡,包括通
过网卡发送和接受数据,它也为上层驱动提供接口。
2) 中间层驱动。它通常位于微端口驱动和传输协议驱动之间,是基于链路层和网络层之间的驱动,由于中间层驱动在驱动层次中的中间层位置,它必须与其上层的协议和下层的微端口驱动通信,并且导出两种协议的函数。虽然中间层驱动导出MINIPORTXX函数,但它并不真正的管理物理网卡,而是导出一个或者多个虚拟适配器,上层协议可以绑定到上面。对于协议驱动来说,中间层导出的虚拟适配器看起来像一个物理网卡,当它向这个虚拟适配器发送封包或者请求时,中间层驱动将这些封包和请求传播到下层微端口驱动;当下层微端口驱动向上指示接收封包或者状态时,中间层驱动向上到绑定虚拟适配器上的协议驱动。中间层驱动的主要作用就是过滤封包,其优点是能够截获所有的网络数据包。
3) 协议驱动,即网络协议。它位于NDIS体系的最高层,经常用作实现传输协议堆栈的传输驱动中的最底层驱动。传输协议驱动申请封包,从发送应用程序将数据复制到封包中,通过调用NDIS函数将这些封包发送到下层驱动。协议驱动也是提供了一个协议接口来接收来自下层驱动的封包。传输协议驱动将收到的封包传递给相应的客户应用程序。在下层,协议驱动与中间层微端口驱动交互。协议驱动调用NDISXX函数发送封包,读取和设置下层驱动维护的信息,使用操作系统服务。协议驱动也要导出一系列的入口点,NDIS调用它来指示封包的接受,指示下层驱动的状态,或者是和其他协议驱动的通信。
中间层内部的工作流程
1) 中间层对数据包的管理
中间层驱动程序从高层驱动程序接收数据包描述符,并在网络上发送,该包描述符与一个或多个链式数据缓冲区相关联。中间层驱动程序能够对数据进行重新打包,并使用新的数据包描述符进行数据传输,也可以直接将数据包传递给低层驱动程序,如果驱动程序下边界面向无连接,可调用NdisSend或NdisSendPackets函数完成该功能,如果驱动程序下边界是面向连接的,可调用NdisCoSendPackets函数完成此项功能。中间层驱动程序也可以进行一些操作改变链式缓冲区的内容,或者调整内入数据包相对于其他发送任务的发送次序或发送定时。但是,即使中间层驱动程序只是向下层传递上层引入的数据报,例如,仅仅只是对数据包进行计数,也必须分配新的数据包描述符,并且要管理部分或者全部新的包结构。
每一个中间层驱动程序都必须分配自己的包描述符来代替高层的数据包描述符。如果中间层驱动程序要把数据包从一种格式转化为另一种格式,也必须分配缓冲区描述符来映射用于复制转配数据的缓冲区,该缓冲区由中间层驱动程序进行分配。如果有与复制的包描述符相关的OOB数据,那么可以将这些数据复制到与包描述符(中间层驱动程序分配的)相关的新OOB数据块,其过程是,首先,用NDIS_OOB_DATA_FROM_PACKET宏获取OOB数据区的指针,然后,调用disMoveMemory将其内容移入与新包描述符相关的OOB数据区。该驱动程序也能够用NDIS_GET_PACKET_XXX或NDIS_SET_PACKET_XXX宏从与老的包描述符相关的OOB数据区中,读取相关的内容,并写入与新包描述符相关的OOB数据区。
包描述符通过调用以下NDIS函数进行分配
a)调用NdisAllocatePacketPool或者NdisAllocatePacketPoolEx,为固定尺寸包描述符(由呼叫器指定数量)分配并初始化一组非可分页池。
b)调用NdisAllocatePacket函数,从NdisAllocatePacketPool(Ex)已经分配的池中分配包描述符。根据中间层驱动程序目的的不同,驱动程序能够对引入包描述符连接的缓冲区进行重新打包。例如,中间层驱动程序可以在接下来的情况下分配包缓冲池、对引入包数据重新打包.如果中间层驱动程序从高层协议驱动程序接收到的数据缓冲区,比低层介质能够发送的单个缓冲区更大,那么中间层驱动程序必须将引入的数据缓冲分割成更小的、满足低层发送要求的数据缓冲。中间层驱动程序在将发送任务转交低层驱动程序之前,可以通过压缩或加密数据方式来改变内入数据包的长度。调用以下NDIS函数分配上面所要求的缓冲区:
NdisAllocateBufferPool获取用于分配缓冲区描述符的句柄;
NdisAllocateMemory或NdisAllocateMemoryWithTag分配缓冲区;
c)调用NdisAllocateBuffer分配和设置缓冲区描述符,映射由NdisAllocateMemory(WithTag)分配的缓冲区,并链接到NdisAllocatePacket分配的包描述符上。驱动程序可以通过调用NdisChainBufferAtBack或NdisChainBufferAtFront函数,将缓冲区描述符和包描述符进行链接。调用NdisAllocateMemory(WithTag)返回的虚拟地址和缓冲区长度,将被传递给NdisAllocateBuffer函数来初始化其所映射的缓冲区描述符。符合典型要求的包描述符能够在驱动程序初始化时根据要求进行分配,也可以通过ProtocolBindAdapter函数调用来实现。如果必要或者出于性能方面的考虑,中间层驱动程序开发者可以在初始化阶段,分配一定数量的包描述符和由缓冲区描述符映射的缓冲区,这样,就为ProtocolReceive复制内入数据(将向高层驱动程序指示)预先分配了资源,也为MiniportSend或MiniportSendPackets向相邻低层驱动程序传递引入的发送数据包,准备了可用的描述符和缓冲区。如果在中间层驱动程序复制接收/发送数据到一个或多个缓冲区时,最末的一个缓冲的实际数据长度比缓冲区的长度小,那么,中间层驱动程序将调用NdisAdjustBufferLength把该缓冲区描述符调节到数据的实际长度。当该包返回到中间层驱动程序时,应再次调用该函数将其长度调节到完整缓冲区的实际尺寸。
2)下边界面向无连接的中间层驱动程序的工作流程
通过ProtocolReceivePacket函数,从低层NIC驱动程序以完整数据包形式接收内入数据,该数据包由NDIS_PACKET类型的包描述符指定,也能够通过将内入数据指示给ProtocolReceive函数,并将数据复制到中间层驱动程序提供的数据包中。下边界面向连接的中间层驱动程序总是用ProtocolCoReceivePacket函数,从低层NIC驱动程序接收数据作为一个完整的数据包。
在如下情况下,中间层驱动程序能够保持对接收数据包的所有权:当下边界面向无连接的中间层驱动程序向ProtocolReceivePacket函数指示完整数据包时,当下边界面向连接的中间层驱动程序向ProtocolCoReceivePacket函数指示数据包时,其中DIS_PACKET_OOB_DATA的Status成员设置为除NDIS_STATUS_RESOURCES以外的任何值。在这些情况下,中间层驱动程序能够保持对该包描述符和其所描述的资源的所有权,直到所接收数据处理完毕,并调用NdisReturnPackets函数将这些资源返还给低层驱动程序为止。如果ProtocolReceivePacket向高层驱动程序传递其所接收的资源,那么至少应该用中间层驱动程序已经分配的包描述符替代引入包描述符。根据中间层驱动程序目的的不同,当其从低层驱动程序接收完整数据包时,将有几种不同的包管理策略。例如,以下是几种可能的包管理策略:复制缓冲区内容到中间层驱动程序分配的缓冲区中,该缓冲区被映射并链接到一个新的包描述符,向低层驱动程序返回该输入包描述符,然后可以向高层驱动程序指示新的数据包;创建新的包描述符,将缓冲区(与被指示包描述符相关联)链接到新的包描述符,然后将新的包描述符指示给高层驱动程序。当高层驱动程序返回包描述符时,中间层驱动程序必须拆除缓冲区与包描述符间的链接,并将这些缓冲区链接到最初从低层驱动程序接收到的包描述符,最后向低层驱动程序返还最初的包描述符及其所描述的资源。即使下边界面向无连接的中间层驱动程序支持ProtocolReceivePacket函数,它也提供ProtocolReceive函数。当低层驱动程序不释放包描述符所指示资源的所有权时,NDIS将调用ProtocolReceive函数,当这类情况出现时,中间层驱动程序必须复制所接收的数据到它自己的缓冲区中。对于下边界面向连接的中间层驱动程序,当低层驱动程序不释放包描述符所指示资源的所有权时,则将数据包的NDIS_PACKET_OOB_DATA的Status成员设为NDIS_STATUS_RESOURCES,然后驱动程序的ProtocolCoReceivePacket函数必须将接收到数据复制到自己的缓冲区中
5) 中间层驱动过滤数据包的原理
NDIS中间层驱动程序在NDIS中起着转发上层驱动程序送来的数据包,并将其向下层驱动程序发送的接口功能。当中间层驱动程序从下层驱动程序接收到数据包时,它要么调用NdisMXxxIndicateReceive函数,要么调用NdisMindicateReceivePacket函数向上层指示该数据包中间层驱动程序通过调用NDIS打开和建立一个对低层NIC驱动程序或者NDIS中间层驱动程序的绑定。中间层驱动程序提供MiniportSetInformation和MiniportQueryInformation函数来处理高层驱动程序的设置和查询请求,某些情况下,可能还要将这些请求向低层NDIS驱动程序进行传递,如果其下边界是面向无连接的可通过调用NidsRequest实现这一功能,如果其下边界是面向连接的则通过调用NidsCoRequest实现该功能。中间层驱动程序通过调用NDIS提供的函数向网络低层NDIS驱动程序发送数据包。例如,下边界面向无连接的中间层驱动程序必须调用NdisSend或NdisSendPackets来发送数据包或者包数组,而在下边界面向连接的情况下就必须调用NdisCoSendPackets来发送包数组数据包。如果中间层驱动程序是基于非NDISNIC驱动程序的,那么在调用中间层驱动程序的MiniportSend或Miniport(Co)SendPackets函数之后,发送接口对NDIS将是不透明的。NDIS提供了一组隐藏低层操作系统细节的NdisXxx函数和宏。例如,中间层驱动程序可以调用NdisMInitializeTimer来创建同步时钟,可以调用NdisInitializeListHead创建链表。中间层驱动程序使用符合NDIS标准的函数,来提高其在支持Win32接口的微软操作系统上的可移植性。
在防火墙的设计中,最核心的部分应该是数据包的过滤。
其他的功能都是建立在数据包过滤的基础之上,如:入侵检测功能和邮件检测功能都是建立在数据包过滤的基础之上。数据包过滤中主要是IP包头的分析,例如:在以太网中,得到的数据报大致是如下结构,以太帧头14个字节,放在PUCHAR结构数组的第0个元素到第13个元素中,其中前六个字节是目的MAC地址,然后六个字节源MAC地址,然后两个字节是协议类型,通常的协议类型有0x080x00->IP,0x080x06->ARP,0x080x35->RARP,所以,可以通过数组的第12个元素和第13个元素来判断协议类型。过滤规则就是在这个基础之上建立。如果要过滤特定协议,只要在相应的字节读取数据,判断是否符合要过滤的规则就可以了,当然实际的过滤规则要复杂的多的多,比如对指定的端口指定的IP的过滤。
4. 杀毒软件与防火墙
请楼主看看这个帖子吧。真的很有用,一般我不会转帖的,这个真的很好。
流氓软件和木马在各种防火墙和杀毒软件的“打压”之下已经开始逐步向内核“退缩”,传统的依靠查看本地打开的端口与进程的关系的方法检查非法网络访问已经不再适用,个人防火墙已经成为装机必备的软件。目前主流的个人防火墙软件都是构建在Windows内核之上的,但是Windows的内核驱动是分层的,防火墙工作在哪一层实际上就决定了防火墙的性能,工作在TDI层的防火墙是无论如何也不能知道NDIS层的数据收发情况的,因为TDI驱动层在内核中是高于NDIS驱动层的。过去的木马(上个世纪九十年代以前)都是构建在Windows应用层上的普通程序,工作在TDI层的防火墙可以轻易地觉察并阻断它们非法的网络访问,但是对付缩进内核的木马和流氓软件,单纯的依靠TDI层拦截已经显得力不从心。内核木马的特点是不依赖句柄,不绑定端口(NDIS)
),可以工作在TDI层,甚至在NDIS层,所以,真正可靠的防火墙应该在NDIS层建立防线。
虽然真正可靠的防火墙应该工作在NDIS层,但是,个人防火墙和用于服务器的防火墙毕竟还是有一些不同之处,工作在服务器端的防火墙只需要根据协议、地址和端口判断是转发还是丢弃就行了,高级一点还可以分析包内容,根据预设的专家系统判断是正常的数据包还是非法攻击数据包,这样的防火墙还可以用硬件实现。但是个人防火墙的特别之处就是需要与用户交互,用户数据多是基于IP协议的,并且用户并不关心协议的细节(掌握这些对大多数用户来说有点难度),所以个人防火墙除了通过IP层的协议进行过滤之外,更主要的手段是根据用户的意愿允许还是阻止某个进程(程序)访问网络,在这个粒度上用户比较容易理解和控制。从这一点上讲,工作在TDI层的防火墙的优势就是能够在网络访问发生的时候追踪到发起访问的进程名称,从而给用户一个提示,而工作在NDIS层的防火墙则不容易做到这一点。因为发送数据时上层驱动将数据包提交到NDIS的发送队列中后就返回了,当数据包被真正投递的时候已经无从确定是哪个程序(进程)发送的了,对于收到的数据包需要根据端口号判断是哪个程序的,但是在NDIS层并不知道端口号和进程的对应关系,所以无论数据发送还是接收都无法有效地确定是属于哪个进程的数据。如果不能确定哪个进程访问网络,只是根据地址、端口和协议进行过滤对(大多数)用户来说是很不友好的,所以最好的个人防火墙(不一定是最安全的)应该是TDI+NDIS双保险:TDI层根据进程级访问过滤,NDIS层根据地址、端口和协议过滤。
前几天,一个朋友要我给他推荐一款比较好的防火墙软件,说实话,我也不知道哪个好,因为我没有比较过。没有调查就没有发言权,随便应付也不是本人的风格,加上本人最近正在验证一个在内核构建TCP/IP协议绕过防火墙的概念的可行性,需要对当前主流防火墙的能力有所了解,所以就把当前比较流行的防火墙都弄来研究了一下,没想到真是大开眼界,不看不知道,一看吓一跳。先上网搜了一下个人防火墙,没想到有这么多种,没时间全搞一遍,只能对用的最多的几个下手了,它们是“天网防火墙个人版”,“金山网镖”,“瑞星个人防火墙”,“卡巴斯基”,“冰盾”和“风云防火墙”,有几个防火墙软件不仅提供网络防火墙功能,还提供诸如文件访问控制,进程创建保护等功能,不过本文只是比较它们的网络防范功能。
首先是天网防火墙,这可是本人上学的时候最喜欢的防火墙了,简单好用。这次使用的是天网防火墙个人版(Trial_Release_v3.0_Build1213),结果却令人失望,天网是一个单纯的TDI防火墙。下图天网启动后的设备驱动加载情况:
图 1 天网防火墙设备驱动加载情况
工作在TDI层的防火墙有两种方式,一种是做成过滤驱动挂接到支持TCP/IP协议的设备上,简单地讲,就是发送给TCP/IP协议驱动的请求会先发送给它过滤,另一种是使用Hook的方式直接HookTCP/IP协议的驱动分派函数,相比较而言,第一种比较容易bypass,驱动层的木马或流氓软件通过设备直接找到TCP/IP的驱动发送请求,就可以避开Attach在其上的过滤驱动,从上图看,天网的驱动是一个Filter驱动,除了直接向TCP/IP的驱动发送请求可以避开天网之外,还有一种方法可以让它完全失效,就是直接摘除挂接的Filter驱动,看看下面的代码:
void ByPassAttachDevice(PDEVICE_OBJECT DeviceObject)
{
PDEVICE_OBJECT CurDevObj = DeviceObject;
while(CurDevObj != NULL )
{
CurDevObj->AttachedDevice = NULL;
CurDevObj = CurDevObj->NextDevice;
}
}
运行在驱动层的木马只要对设备驱动运行一下ByPassAttachDevice()函数就可以让天网和所有使用这种技术的防火墙形同虚设。口说无评,本人专门写了一个驱动来验证,首先在天网的设置中禁止IE访问网络,此时IE的网络访问会被禁止:
图 2 天网防火墙组织IE访问网络
然后用驱动加载测试工具加载本人编写的驱动程序(文后附有加载工具和驱动程序,以及使用说明,可以用来测试一下你用的防火墙是否安全),假设这是一个运行在内核的木马或流氓软件:
图 3 加载Bypass驱动程序
运行后天网就失效了,看看IE可以访问网络了,不仅IE,所有被禁止的程序都可以访问网络了:
图 4 天网防火墙失效了
结论,就不说了,真的很失望。
下面看看金山网镖,这个是我的朋友很喜欢用的,一直说它好用,本次比较用的是金山安全套件2008中附带的金山网镖,先看看它的驱动加载情况:
图 5 金山网镖驱动加载情况
这也是一个TDI Filter,没有在NDIS层做工作,使用前面的工具可以轻松bypass,不说了,下一个。
接下来是瑞星个人防火墙,使用的版本是瑞星个人防火墙2008。瑞星的驱动在TDI层使用了不容易bypass的TDI hook,除此之外,在NDIS层也使用了Hook,先看看TDI层的情况:
图 6 瑞星驱动的TDI Hook情况
再看看在NDIS层的Hook情况:
图 7 瑞星驱动的NDIS Hook情况
从驱动上看瑞星防火墙要比前两个强很多,本人曾试着手工恢复被hook的函数,虽然恢复后不再弹出“某某程序要访问网络”的提示,但是实际上还是不能访问网络,不知为何,有兴趣的朋友可以研究一下。
再来看看卡巴斯基,这次使用的是卡巴斯基的互联网安全套装6.0个人版,从驱动上看卡巴斯基采用的是用TDI Filter驱动+NDIS Hook:
图 8 卡达斯基的驱动加载情况
但是可能卡巴斯基的NDIS Hook只是用来分析可以的数据才使用的,也或者是为实现其它功能设置的Hook,总之,使用本文的程序可以bypass卡巴斯基的防火墙功能。
再看看冰盾防火墙,冰盾是一个服务器防火墙,这次使用的是冰盾8.1 Build60214,从驱动加载情况看,冰盾使用了一个NDIS中间层驱动,没有Hook,也没有处理TDI层的事务,毕竟它不是个人防火墙,没必要处理TDI层的事情(这只是本人的看法的)。工作在NDIS层的好处是可以探测工作在TDI层的rootkit木马,但是对于个人计算机用户来说,冰盾的设计不太好用(或者说比较难理解,相对于其它几种防火墙软件),另外,中间层驱动还容易被Hook,rootkit木马可以Hook它的处理函数,比如指向一个空函数,就可以瘫痪中间层驱动。
最后一个是风云防火墙,这个是从网上搜到的,以前没听说过,使用的版本是V1.26 正式版。这个软件除了防火墙功能之外,还有很多附加功能,比如文件访问监控,注册表访问监控等等,不过其网络防火墙这块使用的策略和卡巴斯基一样,可以被本文的工具bypass
从分析的结果来看,这几款防火墙软件对于应用程序的访问控制都是没有问题的,但是对于同样工作在内核级别上的木马和流氓软件则问题很多,只有瑞星防火墙结果好一点,其它的几款防火墙软件都挺令人失望,特别是天网防火墙。最后需要强调一点的是即使是瑞星这样使用TDI Hook + NDISHook的方式也不一定就是安全的,因为在应用程序级别上进行网络访问控制还是粒度太粗,如果使用rootkit工具将木马注入到防火墙允许访问网络的程序的进程中,就可以在防火墙眼皮底下堂而皇之地访问网络了,比如IE的一些BHO插件就是这么干得。
驱动加载测试工具以及bypass驱动下载
附录: 驱动加载测试工具以及bypass驱动的使用方法
首先将hook_test.sys复制到windows的系统驱动程序目录中(如果是windowsxp的系统,这个目录可能是c:\windows\system32\drivers),然后运行drv_test.exe,在驱动文件位置中填入驱动文件hook_test.sys的完整路径名,在驱动名称中填入驱动名称,这个比较重要,因为后面的启动、停止和卸载驱动都需要这个驱动名称,不过不一定是“hook_test”,显示名称随便填写就行了。输入完成后首先点击“安装驱动”按钮安装驱动,如果没有错误再点击“启动驱动”按钮启动这个驱动程序,然后就可以测试你的防火墙软件了。测试的方法很简单,就是运行一个访问网络的程序,如果防火墙有效,会提示是否阻止程序访问网络,如果防火墙失效,则没有任何提示,卸载驱动先点击“停止驱动”按钮,然后点击“卸载驱动”按钮就可以了。
5. 谁英语好帮忙翻译一段英语,是一个论文的概述,有点长,谢谢啦
With the rapid development of computer networks, network security issues are increasingly attracted our attention. Firewall as an effective security measure is widely used in various types of networks. Firewall technology has experienced a number of improvements and development stage. However, whether the traditional firewall or currently popular distributed firewall all have their own weaknesses, making their use in practice many restrictions.
This design has implemented a firewall adopting the NDIS driver technology. It’s driven through the kernel mode, the NDIS callback function has been implemented and the filter-hook driver is registered by the NDIS which is provided by system. The IP filter driver uses the filter-hook to handle the data packets in and out. The firewall is composed of the following moles: adding filter rules mole, display filter rules mole storage filter rules mole, storage file mole, installation unloading rules mole and IP packet driver mole. Users can finish the operation of firewall by using main menu and button to protect the system effectively.
The program is a traditional firewall technology and distributed firewall technology combined. The firewall can overcome the internal insecurity and other issues. And also can avoid too much focus on the distributed firewall management problems. In this paper a decision tree based on packet classification algorithms. The main idea is the pre-treatment rules to build the decision-making tree of structural characteristics.
6. 网络监控软件的网络监控软件工作原理
企业里涉及到两部分的网络管理,一部分是监视上INTERNET的行为和内容,也就是大家说的上网监控或外网监控;另一部分就是如果这个电脑不上 INTERNET但又在内部局域网上(比如打印个文件什么的),一般被大家叫成内网监控或本网监控;上网监控管理的是上网的内容监视和上网行为监视(比如发了什么邮件,是否限制流量,是否允许QQ,或监视用户页面浏览);而内网监视管理的是本地网络的活动过程(比如有没有COPY东西到U盘、是否在玩单机 游戏、使用电脑做了什么等等)。
外网监控软件模式基本可以分为两类:有客户端的和没有客户端的(内网安全都需要客户端,上面没有客户端的都不能实现内网安全管理)。
拥有内网管理功能的:网眼监控软件、Anyview(网络警)网络监控软件、网路岗局域网管理软件、网猫网络监控软件实现需要客户端支持。这几种软件都有专门的客户端软件提供。
没有内网管理功能的:百络网警局域网管理、聚生网管系统、超级嗅探狗上网监控系统。二、有客户端的外网监控
信安上网行为管理系统和Phantom系统(外网管理和内网管理功能都提供)。
不牵涉部署模式,因为他们的实现原理都是在C/S模式,通过部署在被监控计算机上的客户端来实现各种功能,在这种模式下,服务器的安装部署对网路环境就没有特别的要求,网络内随意找一个电脑就可以做服务器,而且功能、网络速度、效率都不受影响,不需要对原有网络架构、环境进行改动。
唯一的缺点就是需要安装客户端。 大概分为四种安装模式:旁路、旁听(共享式HUB、端口镜像)、网关、网桥。
(1)旁路模式:
基本采用ARP欺骗方式虚拟网关,让其他计算机将数据发送到监控计算机。
(2)网关模式:
是把本机作为其他电脑的网关(设置被监视电脑的默认网关指向本机),常用的是NAT存储转发的方式;简单说有点像个路由器工作的方式;因此控制力极强,但由于存储转发的方式,性能多少有点损失;不过效率已经比较好了。但维护和安装比较麻烦;无法跨越VLAN和VPN;假如网关死了,全网就瘫痪了。此类软件有 ISA、anyrouter软网关等,这里没有引用,ISA在一些银行金融机构仍在使用,海天上网监控软件是专门针对ISA而开发的。
(3)网桥模式:
支持网桥模式的软件比较少。 除了模式,我们讲一下获取数据包的技术,大概有两种方式:
1) 采用操作系统核心NDIS中间层驱动模式,
2) 公开免费接口WINPCAP协议层驱动。
由于WINPCAP本身设计的天生弱点,所以在流量限制方面无法实现、阻断UDP也将导致网络中断、无法支持千M网络和无线网络、性能也必然很低;也无法实现NAT等更多的扩展功能,由于在协议层运行会被火墙禁止;而NDIS中间层驱动模式由于在NDIS层位置驱动,因此性能效率将非常高,更多功能也将成为可能;能够克服WINPCAP所有的弱点,因此成为主流技术;但实现起来很大难度需要很强的开发实力;
4, 结论:
按照部署模式分:通过对比我们可以知道,网桥模式是最理想的一种模式,这种模式唯一的缺点就是额外开支,需要购买一台足够网络处理能力服务器,而且还要连接在交换机和路由器之间的网络上。
5, 总结
如果需要内网管理与外网管理都需要,那么所有软件都需要客户端,显然Phantom和网眼监控软件是最好的选择。
如果只需要外网监控,那末就需要选择了,这时不需要部署客户端,但需要买一台服务器,部署在交换机和路由器之间。而网眼网络监控软件和Phantom则可以任选一台电脑做服务器;缺点是要安装客户端,优点是:实现的功能强大,支持拓展功能性强。 1) 免费开放的国外代码,因此安全性欠缺;原理上是采用旁听模式,所以无法阻断UDP应用,无法流量限制,并容易数据丢包;阻断规则有可能引起网络中断或无效;
2) 原理上决定不适合超过100个电脑的网络环境,如采用老式共享式HUB速度限制在10M带宽损失严重;如采用交换机镜像是共享100M方式,由于一些交换机本身的缺陷,采用镜像后会导致交换机阻塞现象的可能,因此网络带宽会大约损失40%;
3) 由于是免费接口只提供总线抓包功能,所以不支持集群环境也不支持任何内网监控功能;
4) 由于是高层协议接口同时未提供适合监控的加密压缩数据库;所以不支持即时大规模数据存储,不适合大用户网络;不包含千M、无线网;如需支持多 VLAN或VPN应采用镜像技术,需额外投资支持双向镜像技术的交换机并正确设置和维护;
5) 由于提供的接口都是通用的有限代码,缺乏良好的可控性,所以很多功能无法实现;
7, Arp欺骗
欺骗局域网内计算机,使其他计算机误认为监控计算机为网关计算机,将所有数据发送到监控计算机,只能适合于小型的网络,且环境中不能有限制旁路模式;路由或防火墙的限制或被监视电脑安装了ARP防火墙都会导致无法旁路成功,因为你一边在禁止旁路一边却正在旁路,所以自相矛盾;同时如网内同时多个旁路将会导致混乱而中断网络。
7. 中间层的程序开发
1、设备数据库所在的注册表健值为: ENUM子项中是一个设备数据库,在数据库存放计算机中所有安装的,并且被系统认识到的设备。 所有的用户(包括管理员)都不能更改ENUM项的内容。这是为了保护操作系统和安装的设备的完整性。为了更改设备的设置,应该使用“设备管理器”。 为了在设备管理器中现实隐藏的,非即插即用的,以及没有连接到计算机上的所有设备,你应该首先在命令解释器中敲入命令set DEVMGR_SHOW_NONPRESENT_DEVICES=1,然后启动设备管理器,就可以在设备管理器中删除和重新配置这些设备了。
2、硬件设备类所在ntControlSetControlClass Class项下存放硬件设备类的配置信息。在Class项下的每个子项都代表一个设备类,子项的名称使用“唯一全局标识符(GUI)”,这些标识符存放该设备类的配置信息。在每个类标识符下,还会有以4位数命名的子项,他们代表该设备类里的具体设备,其他的配置数据只应用于该具体设备。 如网卡的设备类是{4D36E972-E325-11CE-BFC1-08002BE10318},并假定我们网卡对应的4为数命名子项名为0005。 其中{4D36E972-E325-11CE-BFC1-08002BE10318}5Linkage 中:Export:代表该设备在设备名字空间输出的设备名字。RootDevice:代表当前设备的GUID。中间层驱动这里有两个GUID,第一个是自己的GUID,第二个是该中间层驱动绑定的下层MINIPORT的GUID。UpperBind:代表上层绑定它的NDIS协议驱动或NDIS中间层驱动。当某个协议驱动绑定该MINIPORT设备时,则这个协议驱动的名字必须出现在UpperBind健值的字符串中,否则不能进行绑定。也就是说,UpperBind健值的字符串决定了那个协议驱动(当然也包括中间层驱动注册的协议)和当前的MINIPORT设备绑定,即,它决定了NDIS的上下层绑定关系。
注:一般添加中间层驱动后,中间层驱动只插入到真是网卡和相应协议中间,不会插入到虚拟网卡(如安装虚拟机后虚拟出来的网卡设备)和相应协议中间。
3、驱动程序所在的注册表健值为: 子项 通常如果某个服务下存在ENUM子项,表明该服务是用来控制某个设备或者设备交互的,它的下面存放该设备的实例。用户不要去试图修改该子项的内容,因为每次系统启动时,都会重写该子项的内容。LINKAGE子项 值项Bind 存放该协议所在绑定栈的最低层小端口设备实例(即MINIPORT)。 值项Export 存放该服务必须访问的对象,该对象必须已经安装在系统中,并且该服务能够使用。 值项Route 指定子项Linkage从那里获取绑定数据。Parameters Adapters子项 这里,我们只解释中间层驱动中该子项的意义。为此,我们假设当前我们讨论的中的XXXX为中间层驱动。 对于中间层驱动,该子项下含有一个子项,是以我们当前中间层驱动绑定的下层MINIPORT设备的GUID命名的,在我的系统中,健值如下:{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子项有个健,名称为UpperBindings,该健的健值是当前中间层驱动的MINIPORT设备名称,在我的系统中为如下健值:Device {5BF5A311-13E4-4746-8865-339DDD6C73AF} 在我们的函数NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()中,会调用一系列函数(如NdisOpenProtocolConfiguration、NdisReadConfiguration)来访问注册表,其实都是访问ParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子项。 注意,函数NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()的倒数第二个参数是SystemSpecific1,如果我们安装的是XPASSTHRU,则其具体指的是如下字符串: xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0} 其中xfilter 是XPASSTHRU的,而{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系统中不同。 函数NdisOpenProtocolConfiguration()其实只是构造一个查询注册表的RTL_QUERY_REGISTRY_TABLE结构(该结构在利用函数RtlQueryRegistryValues()查询注册表是使用)。并将这个结构封装到NDIS_WRAPPER_CONFIGURATION_HANDLE结构中,然后作为NdisOpenProtocolConfiguration()的第二个参数返回。 其实NdisOpenProtocolConfiguration()构造的RTL_QUERY_REGISTRY_TABLE结构的含义也就是查询 xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}下的健值(xfilter 会随着安装不同的中间层驱动而不同,{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系统中不同,下面均省略这些注释)。 函数NdisReadConfiguration()有两个作用,它首先修改在函数NdisOpenProtocolConfiguration()构造的RTL_QUERY_REGISTRY_TABLE结构。也就是在查询 xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}的基础上加上了一个健,将其变成 xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}UpperBindings。然后函数NdisReadConfiguration()会调用函数RtlQueryRegistryValues()查询新构造的这个注册表,并将结果存储在调用函数NdisReadConfiguration()时的第二个参数中。在我的系统中,RtlQueryRegistryValues()读出的这个新构造的这个注册表的健值是:Device {5BF5A311-13E4-4746-8865-339DDD6C73AF}(后面我们称为RESULT1),它其实是我们注册的中间层驱动(XPASSTHRU)的设备输出(其构造是Device+GUID)。 其实我们读出的这个中间层驱动(XPASSTHRU)的设备(即我们刚才读出的那个健值RESULT1)只在后面的函数()中才用得着,并且RESULT1是作为函数()的第二个参BindAdapterHandler()我们一旦调用了函数NdisOpenAdapter()绑定了一个下层的MINIPORT,为什么还要调用函数()初始化我们中间层驱动自己的MINIPORT(因为函数()的参数是RESULT1,而RESULT1代表我们中间层驱动的MINIPORT)。为了解释这个原因,我们先做如下假设。
我们假设我们系统安装了一个中间层驱动(假设为XPASSTRHU),在上图中,PROT-IM和MINIPORT-IM分别代表我们中间层驱动的协议驱动程序和小端口驱动程序,PROT-TCPIP代表真正的协议驱动程序,MINIPORT-NIC代表真是网卡的小端口驱动程序。 当PROT-TCPIP需要发送数据时,会调用函数NdisSend(),其实它会调用MINIPORT-IM中的发送数据函数,但是MINIPORT-IM和MINIPORT-NIC没联系,按照常规是不能发送数据到MINIPORT-NIC的。但是我们可以看到PROT-IM是可以和MINIPORT-NIC互相发送数据的,所以我们必须将MINIPORT-IM和PROT-IM联系起来。 另外当MINIPORT-NIC需要将数据提交给PROT-TCPIP时,只能首先将数据提交给PROT-IM,PROT-IM也只能通过MINIPORT-IM才能和PROT-TCPIP联系起来。 所以必须将PROT-IM和MINIPORT-IM联系起来。有人说这两个东西都是我们中间层驱动注册得,难道还联系不起来吗?不错,但是不管怎样你都得通过你得代码才能将他们联系起来呀!下面我们就介绍联系得方法。 我们以XPASSTHRU为例,在其函数ProtocolBindAdapter()中,先分配了一个ADAPT结构(这个结构是自己定义的,可根据用户的需要定义)。当调用函数ProtocolBindAdapter()调用函数NdisOpenAdapter()进行绑定时,是以&Adapt->BindingHandle作为函数NdisOpenAdapter()的第三个参数的,这样Adapt->BindingHandle就指向了NDIS_OPEN_BLOCK1(注意,调用函数NdisOpenAdapter()时的第三个参数会返回指向绑定以后的NDIS_OPEN_BLOCK指针)。然后函数ProtocolBindAdapter()会调用函数(),该函数会进一步调用XPASSTHRU的NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函数。上面我们讨论过,()中的第二个参数就是XPASSTHRU注册的小端口驱动的设备实例(即上面的RESULT1)。在函数()中会根据设备名称(RESULT1),找到对应的MINIPORT结构,并将其指针作为参数传递给NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函数(以后简称InitializeHandler()函数)。在InitializeHandler()函数中,会进一步将MINIPORT结构指针赋值给ADAPT->MiniportHandle(ADAPT就是上面在函数ProtocolBindAdapter()中分配的那个结构)。 这样数据结构ADAPT中就含有了两个指针,一个指向NDIS_OPEN_BLOCK1,另一个指向MINIPORT-IM,而NDIS_OPEN_BLOCK1和PROT-IM是密切联系的,所以ADAPT就将PROT-IM和MINIPORT-IM紧密的联系起来了。 另外注意,NDIS_MINIPORT_BLOCK->DeviceContext是指向我们的ADAPT结构的,这个赋值在函数()中完成。上面谈到了也是在函数()中完成了从ADAPT-> MiniportHandle到MINIPORT的绑定,所以在函数()中完成了ADAPT和MINIPORT的互相连接(即指针互相指向)。函数InitializeHandler()中可以利用句柄MINIPORT的句柄得到我们的ADAPT结构,具体实现这个功能的函数是NdisIMGetDeviceContext(),这个函数的参数是个NDIS_HANDLE类型,但是在该函数内部,会将这个参数转换成NDIS_MINIPORT_BLOCK结构,并返回NDIS_MINIPORT_BLOCK->DeviceContext。在函数NdisOpenAdapter()中,除了上面提到的完成了由Adapt->BindingHandle到NDIS_OPEN_BLOCK1的指向外,还完成了我们没有提到的由NDIS_OPEN_BLOCK1-> ProtocolBindingContext到ADAPT的指向,所以函数NdisOpenAdapter()完成了ADAPT和NDIS_OPEN_BLOCK1的互相连接(即指针互相指向)。 讲到这里,我们上图完善为下图。
8. 学习windows驱动编程有什么用
驱动程序(Device Driver)全称为“设备驱动程序”,是一种可以使计算机和设备通信的特殊程序。可以说相当于硬件的接口,操作系统只能通过这个接口,才能控制硬件设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。驱动程序在系统中所占的地位十分重要, 驱动程序给我的首先印象应该是面对设备与操作系统的,但是并不一定每一个驱动程序都是与硬件相关联的.在实际的驱动程序开发中不要狭义的理解为硬件,应该理解为设备,硬件也可以叫做设备,在计算机系统中虚拟的也可以是设备,比如 磁盘卷,分区、网络协议、以及其他的设备驱动程序都是设备,那么与硬件无关的驱动程序,比如NDIS驱动,文件过滤系统驱动、磁盘过滤系统驱动程序、文件透明加密驱动... 他们所面对的设备不一样而已 我们形象的理解为NDIS是与网络中间层通讯协议(设备)驱动,卷(设备)过滤驱动,文件系统(设备)过滤驱动。驱动程序的强大之处就是因为他在OS核心层(Ring0)运行,在RING0层运行有什么强大的呢,因为操作系统的保护模式限制,在RING3层很多操作受到限制,比如 直接IO硬件、开启/关闭中断等等特权指令必须在RING0层才能执行、如果你在RING3层执行此类代码就会收到一个类似于 【应用程序指令错误】的消息提示,而相关的应用程序也会被WINDOWS终止,在CPU的所有指令中,有一些指令是非常危险的,如果错用,将导致整个系统崩溃,所以在RING3受到限制.必须在RING0下运行. 如何理解驱动程序的重要性与强大之处,再看看我们在操作计算机的内部流程,我们简单的理解为 输入-应用程序--内核-设备,在这里在最后有个‘设备’但是某些操作的流程并不是一定是与设备有关的,可能仅仅是一系列的简单的操作仅仅是与API有关的.比如OpenProcess、 NtTerminateProcess 在应用程序调用的时候,在RING3的最后一步是在NTDLL 最终由NTDLL进入内核 ,基本上可以这样概括一下,就是所有的操作在进入计算机底层以后都要进过相关驱动程序,在这些功能调用上用个形象的说法 应用层是‘标’,那么驱动层就是‘本’,还有就是驱动层作为操作系统与设备(不一定是硬件)的中间桥梁,有着一夫当关的重大作用,哈哈.... 太多说不完,LZ自己找资料看看..
9. 如何把ndis filter框架利用到日膚indows驱动开发工作中
NDIS Filter NET_BUFFER_LIST NET_BUFFER MDL
1
网络数据结构如下图:
5
第二种方法:
/*******************************************************************GetNetBufferData函数的功能:从1个NET_BUFFER里面获取数据。1个NET_BUFFER里面含有1个或者多个的MDL*******************************************************************/VOIDGetNetBufferData(PNET_BUFFERNetBuffer,PUCHAROutputBuffer,ULONGOutputBufferSize,PULONGOutputBytesCopied){PMDLMdl=NetBuffer->CurrentMdl;*OutputBytesCopied=0;if(NetBuffer->DataLength>OutputBufferSize){#ifDBGDbgPrint("Notenoughoutputbufferspace,in:%d,out:%d ",NetBuffer->DataLength,OutputBufferSize);#endifreturn;}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;}#ifDBGDbgPrint("buffercopied:%dbytes ",*OutputBytesCopied);#endif}
6
上面的2种方法,只是获取数据。而原本NDISFilter框架提供的这4个函数默认的代码,都没有做任何操作,没有实质性质的功能,这4个函数原本默认的代码,我们都不需要,因为我们的驱动程序需要处理网络数据包。这4个函数分别是:
7
在我们的NDISFilter工程里面,我们需要修改掉这4个函数的功能,把它们替换成我们所想要的功能。比如,你在发送数据包或者接收数据包的时候,需要实现自己的一些业务逻辑,而不是去使用MicrosoftNDISFilter提供的原始代码的功能。
8
函数的功能:NDIS调用把发送的结构和数据返还给FilterDriver。NDIS可以收集多次NdisFSendNetBufferLists发送的结构和数据形成一个单链表传递给。除非到NDIS调用,否则一个发送请求的当前状态总是未知的。一个过滤驱动是不能在NDIS调用返回结构之前对NET_BUFFER_LIST和其关联的数据做检查的。要完成一个发送请求完成后的任何必要的后继处理。当NDIS调用时,FilterDriver就重新获地对结构及结构相关资源的所有权。可以在中释放相关的资源和准备下一个NdisFSendNetBufferLists调用。NDIS总是按照过滤驱动调用NdisFSendNetBufferLists提交的顺序传递给下层驱动,但是回返的顺序则是任意的。FilterDriver可以请求一个回环发送请求,只要把NdisFSendNetBufferLists的SendFlags设置成NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK就行了。NDIS会引发一个包含发送数据的接收包指示。
9
一个FilterDriver应该对自己引发的发送请求保持跟踪并确保在完成时不调用NdisFSendNetBufferComplete例程。
步骤阅读
10
FilterSendNetBufferLists函数的功能:NDIS调用一个FilterDriver的FilterSendNetBufferLists例程来过滤上层驱动的发送请求。FilterDriver不能改变其它驱动传来的NET_BUFFER_LIST结构中的SourceHandle成员的值。它可以过滤数据并发送过滤的数据到下层驱动。
11
对每一个提交到FilterSendNetBufferLists的NDIS_BUFFER_LIST,我们可做下面的操作:
1)可以把缓冲区通过NdisFSendBufferLists传递给下层驱动,NDIS保证上下文空间对FilterDriver的有效性。过滤驱动可以在发送前修改缓冲区的内容。可以像处理自己引发的发送请求的缓冲区一样处理这个缓冲区。2)可以调用拒绝传递这个包3)排队缓冲区内容到本地的供以后处理。例如要在一定超时后处理或要接收到特定包后才处理等。如果支持这种处理方式就要支持取消请求的操作。4)可以拷贝缓冲区并引发一个发送请求。它类似自己引发一个发送请求,但必须先调用NdisFSendNetBufferComplete返回上层驱动的缓冲区。
12
发送请求在驱动栈继续完成,当一个微端口驱动调用完成一个发送请求时,NDIS会调用微端口
13
在一个发送操作完成后,FilterDriver可以做在FilterSendNetBufferLists中所有修改的相反操作。返回一个NET_BUFFER_LIST结构的单链表和发送请求的最终状态给上层的驱动。当最顶层的FilterMole的被调用完成后NDIS会调用引发发送请求的协议驱动的。如果FilterDriver不提供FilterSendNetBufferLists它还是可以引发一个发送操作的,但它必须提供一个并且不能在这个例程里把这个事件传递给上层驱动。
14
一个FilterDriver可以传递或过滤一个上层驱动的回环请求,要传递一个回环请求,NDIS会设置FilterSendNetBufferLists的SendFlags参数为NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK,FilterDriver在调用NdisFSendNetBufferLists时把这个标记传给它即可。在回环请求的情况下NDIS会指示一个包含发送数据的接收包。
15
如果一个FilterDriver修改的任何行为不是NDIS提供的标准服务,那么它应该当自己为NDIS提供相应的服务。例如,如果一个FilterDriver修改了一个硬件地址请求,就必须处理直接到这个新地址回环包。在这种情况下,因为FilterDriver已经更改了地址NDIS是不能提供一个回环服务的。
16
_Use_decl_annotations_VOIDFilterSendNetBufferLists(NDIS_HANDLEFilterMoleContext,PNET_BUFFER_LISTNetBufferLists,NDIS_PORT_NUMBERPortNumber,ULONGSendFlags){PMS_FILTERpFilter=(PMS_FILTER)FilterMoleContext;PNET_BUFFERNetBuffer;UCHARTempBuffer[MAX_BUFFER_SIZE];ULONGBytesCopied;pEthHdrEthernetHeader;pIPHdrIpHeader;#ifDBGDbgPrint(">>>FilterSendNetBufferLists:%p ",NetBufferLists);#endiffor(NetBuffer=NetBufferLists->FirstNetBuffer;NetBuffer!=NULL;NetBuffer=NetBuffer->Next){GetNetBufferData(NetBuffer,TempBuffer,MAX_BUFFER_SIZE,&BytesCopied);if(BytesCopied==0){#ifDBGDbgPrint("Netbuffercatcherror ");#endif}else{EthernetHeader=TempBuffer;if(EthernetHeader->Type==0x0800)//以太网类型{IpHeader=EthernetHeader+sizeof(EthHdr);//去掉以太网头,抓出IP头#ifDBGDbgPrint("Getippacket ");#endif}}}NdisFSendNetBufferLists(pFilter->FilterHandle,NetBufferLists,PortNumber,SendFlags);}
17
FilterReturnNetBufferLists函数的功能:如果FilterDriver设置了的状态为NDIS_STATUS_SUCCESS,NDIS通过驱动的FilterReturnNetBufferLists返回指示数据。在这种情况下FilterDriver失去了对NET_BUFFER_LIST的所有权,直到FilterReturnNetBufferLists被调用。FilterDriver调用NdisFIndicateNetBufferLists传递接收指示给驱动栈上的上层驱动,如果上层驱动保留了对缓冲区(NET_BUFFER_LIST)的所有权,NDIS会调用FilterDriver的FilterReturnNetBufferLists例程。在FilterReturnNetBufferLists中应该撤消在接收路径上(如在FilterReciveNetBufferLists中做的一些处理)的操作。当最底层的FilterMole完成对缓冲区(NET_BUFFER_LIST)的处理后,NDIS把缓冲区返回给微端口驱动。如果FilterReceiveNetBufferLists的ReceiveFlags没有设置NDIS_RECEIVE_FLAGS_RESOURCES标记,FilterDriver调用NdisFReturnNetBufferList返回这个缓冲区数据,如果设置了FilterReceiveNetBufferLists直接返回时就把缓冲区返还给了下层微端口驱动。
步骤阅读
18
FilterReceiveNetBufferLists函数的功能:FilterDriver调用来指示发送数据。这个函数通过NET_BUFFER_LIST结构给上层驱动指示数据。FilterDriver可以从池中分配这个结构。如果FilterDriver设置了的状态为NDIS_STATUS_SUCCESS,NDIS通过驱动的FilterReturnNetBufferLists返回指示数据。在这种情况下FilterDriver失去了对NET_BUFFER_LIST的所有权直到FilterReturnNetBufferLists被调用。如果FilterDriver在调用时设置ReceiveFlags为NDIS_RECEIVE_FLAGS_RESOURCES,在函数返回后FilterDriver会立即恢复对NET_BUFFER_LIST的所有权,这时FilterDriver必须立即处理这个NET_BUFFER_LIST的返回,因为NDIS在这种情况下是不会调用FilterReturnNetBufferLists返回NET_BUFFER_LIST结构的。注意:一个FilterDriver应该跟踪自己引发的接收指示确保它在FilterReturnNetBufferLists中不调用NdisFReturnNetBufferLists。
19
_Use_decl_annotations_(NDIS_HANDLEFilterMoleContext,PNET_BUFFER_LISTNetBufferLists,NDIS_PORT_NUMBERPortNumber,ULONGNumberOfNetBufferLists,ULONGReceiveFlags){PMS_FILTERpFilter=(PMS_FILTER)FilterMoleContext;PNET_BUFFERNetBuffer;UCHARTempBuffer[MAX_BUFFER_SIZE];ULONGBytesCopied;pEthHdrEthernetHeader;pIPHdrIpHeader;#ifDBGDbgPrint(">>>FilterReceiveNetBufferLists:%p ",NetBufferLists,ReceiveFlags,NumberOfNetBufferLists);#endifdo{for(NetBuffer=NetBufferLists->FirstNetBuffer;NetBuffer!=NULL;NetBuffer=NetBuffer->Next){GetNetBufferData(NetBuffer,TempBuffer,MAX_BUFFER_SIZE,&BytesCopied);if(BytesCopied==0){#ifDBGDbgPrint("Netbuffercatcherror ");#endif}else{EthernetHeader=TempBuffer;if(EthernetHeader->Type==0x0800){IpHeader=EthernetHeader+sizeof(EthHdr);#ifDBGDbgPrint("IPpacketexist ");#endif}}}}while(FALSE);
20
调用来指示发送数据。如果FilterDriver设置了的状态为NDIS_STATUS_SUCCESS,NDIS通过驱动的FilterReturnNetBufferLists返回指示数据。如果FilterDriver设置了的ReceiveFlags值为NDIS_RECEIVE_FLAGS_RESOURCES,那么在函数返回后FilterDriver会立即恢复对NET_BUFFER_LIST的所有权,这时FilterDriver必须立即处理这个NET_BUFFER_LIST的返回。在这种情况下是不会调用FilterReturnNetBufferLists返回NET_BUFFER_LIST结构的。