NDIS中间层驱动实现网页跳转_ndis中间层驱动资料

2020-02-26 其他范文 下载本文

NDIS中间层驱动实现网页跳转由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“ndis中间层驱动资料”。

在编写windows网络驱动之前,需要具备一定的计算机网络知识。包括OSI/ISO 七层体系结构,常见的网络协议TCP/TP, UDP,ICMP,HTTP,FTP,SMTP/POP3等。因为整个windows网络驱动就是建立在网络协议栈基础之上的。

Windows网络驱动有两个重要的规范:TDI,NDIS。TDI(Transport Driver Interface)传输层接口,顾名思义,这个技术是建立在传输层之上的。传输层位于七层协议的第三次,常见的TCP/UDP协议就属于传输层。我们知道,传输层提供的服务包括:连接管理、差错检测、按端口号寻址。事实上,TDI驱动主要作用就是过滤端口。

TDI是即将被淘汰的技术,微软宣布,vista之后的操作系统将不再提供TDI支持,取代它的是Windows Filter Platform和Winsock Kernel,有兴趣的朋友可以搜集一下相关的资料。这里注重分析一下NDIS驱动框架。

NDIS(Network Driver Interface Specification)网络驱动接口标准,相比TDI,它位于七层协议的更低层次。能够捕获更详细的信息。可以做更多的事。它是微软联合3com公司发布的一个标准。NDIS网络驱动有3种表现形式:协议驱动、中间层驱动、小端口驱动。它们的作用范围大致按照传输层、网络层、数据链路层依次往下排。小端口驱动miniport,一般是网卡厂商提供,协议层驱动一般用来捕获数据包,大名鼎鼎的winpcap就是基于协议层驱动编写,而本文主要关心中间层驱动。

WDK文档的例子中,提供了一个中间层驱动,我的电脑中的路径是C:WinDDK6001.18002srcnetworkndispathru。

Pathru位于协议驱动和小端口驱动之间,比较灵活。类似于它们两个的综合体。它能捕获所有流入流出本机的数据,非常强悍。常见的个人防火墙基本都是用中间层驱动写的。它可以做的事情包括,过滤IP和端口号,禁止某类协议(ping/arp),加密解密数据流等,基本上你能想到的事它都可以干。在我做的一个项目中,用到了中间层驱动,来实现一个网址跳转的功能。下面免费贡献出我的经验。整个跳转是在pathru的基础上稍加改动实现的。所以,一定要多看看pathru。

要想实现网址跳转,比如ie中你输入www.daodoc.com,结果页面打开的是腾讯的首页,你就必须对从地址栏键入www.daodoc.com开始,到最终网页呈现出来的过程非常了解。在了解了整个过程后,我们就可以伪装,篡改,让客户端和服务器都被蒙蔽。

现在的java语言,php语言等,都能实现页面跳转,而且极其简单,基本上就是一条代码的事儿。这个做法是在应用层实现的,不靠谱,很容易被360视作非法操作,被强制干掉。因为应用层ring3的东西没有内存保护,谁都可以去探测。

回到正题上,从请求到回送页面,这个过程包括两个阶段:发送和接收。发送是这样走的:http-》tcp-》ip-》ether。接收正好相反。分别对应驱动中MpSend和PtReceive/PtReceivePacket。接收比较复杂,有可能调用PtReceive,也有可能调用PtReceivePacket,这个最后再做讨论,现在先把整个流程捋清楚。

好,既然流程就是这样,我们要做的东西就很明确了。一句话,篡改发送时候的目的ip。将121.194.0.239改为59.64.114.98.(现在大多数网站的ip不一定只有一个,这里把这个问题留到最后再说)。篡改的对象是发送包中目的ip为121.194.0.239的包。于是,又来一个问题,怎么解析包?MpSend的时候,数据的参数是PNDIS_PACKET。这个东西叫做包描述符。描述符描述符,它不是真正的数据。要想获得连续的数据,就要从它描述的内存中一块块拼接起来。事实上的确是这样,NDIS_PACKET实际上包含了一个链式数据缓冲区,利用head,tail,next等联系起来。好,获取连续包的代码如下:

VOID PMgrGetPktData(IN PNDIS_PACKET Packet, OUT PUCHAR pDst, IN ULONG length){

PNDIS_BUFFER pNdisBuffer;

UINT BytesAvailable;UINT BytesRemaining = length;PUCHAR pSrc;

pNdisBuffer = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);

while(BytesRemaining &&(pNdisBuffer!= NULL))

{

NdisQueryBuffer(pNdisBuffer,(PVOID*)&pSrc, &BytesAvailable);

if(BytesAvailable)

{

ULONG

BytesToCopy = MIN(BytesAvailable, BytesRemaining);

NdisMoveMemory(pDst, pSrc, BytesToCopy);

BytesRemaining-= BytesToCopy;

pDst += BytesToCopy;

}

NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);

} } 其中pDst是预先用NdisAllocateMemoryWithTag分配好的一块内存。

这样,我们就把包装进pDst中了。下面开始进行包的解析。以太网包格式多种多样,不过绝大多数都是ETHER V2格式。这里以我要处理的http请求包为例说明,格式大致如下:

源mac地址+目的mac地址+ip头+tcp头+http数据。其中ip头格式: typedef struct IPHeader {

UCHAR versionLen;//version和首部长度 决定是否有option字段 UCHAR serviceType;USHORT ipPackLen;// USHORT flag;USHORT pieceFlag;UCHAR ttl;UCHAR protocol;USHORT headerCheckSum;UCHAR srcIpAddr[4];UCHAR dstIpAddr[4];}IPHeader;看到没有,只要修改ip头的最后四个字节dstIpAddr,就可以实现以假乱真。在实际项目中,我修改了这个地址后,用wireshark抓包工具发现,服务器根本没有响应,也就是说,这个包在客户端就被丢弃了。原因是什么?原因是没有进行校验和。Ip,tcp,udp三个协议,哪怕修改一点点,它都要重新校验,将结果写回到headerCheckSum。修改校验和字段后,果然,腾讯有反应了,给回送包了。这里再贴出校验算法,c语言版的:

USHORT CheckSum(USHORT *buff, int size)//计算校验和

{

USHORT* buffer = buff;unsigned long cksum=0;while(size >1){

} cksum += * buffer++;size-= sizeof(USHORT);if(size){ } cksum += *(UCHAR*)buffer;cksum =(cksum >> 16)+(cksum & 0xffff);cksum +=(cksum >>16);return(USHORT)(~cksum);} 到这里,tcp连接开始了第一次握手,并且腾讯有回应了。可是,客户端自己有问题了。它收到腾讯的回应包后,不再进行第二次握手,而是选择了关闭连接。这个问题困扰了我很久。后来在一个英文资料中发现一些蛛丝马迹,大致意思是说,tcp在发生数据前,回记住目的ip,等它收到回应包后,将包的源ip和它保存的目的ip进行对比,如果发现不一致,它会认为是不安全的,直接丢弃了。Tcp的事儿真多。没办法,这个东西是协议规定的,绕不过去,只能继续伪造了。怎么伪造,继续篡改回送包的源ip。Tcp是传输层的东西,PtReceive是链路层的东西,还好,在到达传输层之前,我们就收到了这个包,来得及。将源ip修改后,重新发出去。这个时候,tcp终于消停了,三次握手可以顺利进行,连接正式建立。

到这个时候,用wireshark抓包可以发现,客户端已经发出http的get请求包了。可是,腾讯这个时候又出问题了,它没有回应任何包,单方面把连接关掉了(FIN,ACK)!什么情况!

没办法,只能硬着头皮上了。仔细查看这个http包,发现host字段是www.daodoc.com。而正确的请求腾讯时该字段是www.daodoc.com。难怪它关掉连接,原来它认为客户端在捉弄它,你ip请求是对的,http却不对,我就不给你回应。好了,继续伪装吧。客户端在发送时,如果有http包头,就篡改包头里面host字段。篡改之后,一定要重新校验,将校验和写回tcp的checkSum字段。Tcp头格式:

Tcp头格式:

typedef struct TCPHeader {

USHORT srcPort;USHORT dstPort;UINT seqNum;UINT ackNum;

UCHAR rsvLen;//首部长度 UCHAR rsvFlag;//Flag USHORT windowSize;USHORT checkSum;USHORT urgentPointer;}TCPHeader;

好了,见证奇迹的时刻到了,我在IE中轻轻键入www.daodoc.com,刷的一下,腾讯的页面出来了!可是没等我高兴太久,又出问题了。我把ie关了,重开,重新键入,发现打不开。不该啊!第一次可以打开,第二次打不开,是不是cookie啥的问题?果然,wireshark验证了我的猜测,虽然host里面sina改成qq了,可cookie却是sina的东西。怎么办,果断丢掉cookie!重新校验。我们知道,cookie的用处主要有加速页面载入速度,保存用户名密码等,去掉后影响也就只有这些。

网址重定向大致就这些东西了。在实际测试中发现,有很多问题,包括不是顶级域名怎么办?有些网址还要求必须有cookie,有些网站本身也有自跳转功能,http协议也有1.1,1.0之分。由于我的项目是在遇到某些网址时,弹出一个固定页面,所有情况都是可预知的,不存在前面的问题。

看来,要想在驱动级完美实现网页跳转,要走的路还很长。

现在回过头来聊下前面的问题。一是不固定ip,而是pathru在接收时的处理。第一个问题,没办法,只能让应用程序传参数的时候,将域名和ip一块传过来。第二个问题比较麻烦。慢慢展开。

根据网卡型号不同,PtReceive和PtReceivePacket都会被调到。我也不知道原因,反正在windbg中看的时候,发现两个都可能被调用。所以这两个都要处理。后者接收到的都是完整的包描述符,处理起来较为简单。前者可能取到完整的,也可能取不到完整

Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);如果Packet不为空,说明取到了完整的包描述符,下面该咋处理就咋处理,否则就不是一个完整的描述符,需要等。它要调用NdisTransferData,然后就等,知道返回的status不是NDIS_STATUS_PENDING为止。

本人对网络驱动开发有着浓厚的兴趣,在阅读本文过程中如果有疑问,欢迎随时和我联系。

《NDIS中间层驱动实现网页跳转.docx》
将本文的Word文档下载,方便收藏和打印
推荐度:
NDIS中间层驱动实现网页跳转
点击下载文档
相关专题 ndis中间层驱动资料 中间层 跳转 网页 ndis中间层驱动资料 中间层 跳转 网页
[其他范文]相关推荐
    [其他范文]热门文章
      下载全文