NDIS网络封包的研究
来源:优易学  2011-12-26 16:39:55   【优易学:中国教育考试门户网】   资料下载   IT书店

  最近在研究一个修改网络封包的问题,研究了4天了,有点心得,害怕以后想不起来,所以放在博客上做个笔记。
  大多数高校采用了城市热点的Dr.com计费系统,不过说句实话,城市热点的那个DRCOM写的真的不怎么样。它采用的SPI的方式,主要过滤 Send 和 SendTo 两个函数,分别过滤TCP和UDP协议。
  城市热点的DRCOM实现方法其实不是很复杂,他先是和服务器交换数据,得到一个16字节的隧道码,然后TCP连接的时候,第一个数据包前面就加上16个字节的这个数据,然后经过城市热点的交换机时,交换机把这个数据去掉,然后实现正常的交换机功能。再说他的DRCOM,采用SPI的方法,SPI严格上应该算是应用层,虽然相对来说比较底层,但是毕竟是应用层,在SPI里实现加数据,造成很多软件都无法正常工作,我猜想原因应该是这些程序使用了特殊的发送数据的方法,或者其他原因,具体原因我也没研究,不过很明显,很多程序无法正常使用,比如NOD32就无法正常更新,操作系统也无法正常更新。
  从网上下了一个DRCOM的新版本,他写的FOR VISTA,青年人网提示安装上后发现新版本采用了NDIS的方式来附加数据,应该就是IMD驱动,直接作用在NIC和协议驱动之间,也是很多防火墙惯用的方式,这个版本的DRCOM不会造成杀软和操作系统无法更新的问题了。
  不过就着打破砂锅问到底的方式,我在 sourceforge.net 网站上找到了DRCOM的LINUX版本,也是一个高手破解出来写的,有个WIN32版本可惜没有提供代码,发邮件也不回,为此只得就着LINUX代码研究。
  经过2天研究把和DRCOM服务器交换数据的协议研究出来了,然后就是最关键的在数据包里加入16字节隧道码,我也采用的NDIS方式,微软的DDK自带了一个PASSTHRU的驱动程序就是一个IMD驱动的范本,不过他没有实现任何功能,只是对发送出去的数据包重新申请了一个数据包发送,并没有修改或者过滤。
  要实现过滤,首先必须得到要发送的数据,很不幸,NDIS里不是用一整块内存来储存数据的,虽然不知道为什么,不过记得很久以前在哪里看到过一个文章简单说明了原因,因为采用链表的形式是为了封包的时候方便,直接将IP头,ETH头和TCP头还有数据,分别存在一个节点里,然后用链表的形式挂接,这样避免了频繁的申请和回收内存。 不管怎么说,首先我们先要获得数据,我搜索了很多NDIS的资料,在安焦上找到一个文章,他是介绍的防火墙的,里面就有得到数据包的方法
  //获得数据大小
  NdisQueryPacket(MyPacket, NULL, NULL, NULL, &PacketSize);
  // KdPrint(("数据大小:%d\n", PacketSize));
  //申请数据缓冲区
  Status = NdisAllocateMemoryWithTag(&PacketContent, 2048, TAG);
  if (Status != NDIS_STATUS_SUCCESS)
  return;
  NdisZeroMemory(PacketContent, 2048);
  NdisQueryBufferSafe(MyPacket>Private.Head, &pBuf, &BufLength, HighPagePriority);
  NdisMoveMemory(PacketContent, pBuf, BufLength);
  i = BufLength;
  pNext = MyPacket>Private.Head;
  for(;;)
  {
  if(pNext == MyPacket>Private.Tail)
  break;
  pNext = pNext>Next; //指针后移
  if(pNext == NULL)
  break;
  NdisQueryBufferSafe(pNext,&pBuf,&BufLength,32);
  NdisMoveMemory(PacketContent+i,pBuf,BufLength);
  i+=BufLength;
  }
  他先获得了包的大小,估计是想动态申请内存,不过不知道为什么,后来直接写的2000,我后来改成的2048,不过我试过一次动态申请,结果蓝屏了,也没研究原因。可以看到,从数据包的链表里,提取数据然后储存在 PacketContent 里。直到链表到末尾。
  这样提取出来的数据实际是 ETH头部+IP头部+TCP头部+数据,也就是实际在网络传输的数据形式。
  因为我要过滤的是TCP协议,UDP协议是每个包都加了一个隧道码,很简单,TCP则是每个连接的第一个包才加,后面都不加,相对比较复杂,我开始想的是直接判断连接,但是网卡数据都是以包的形式,不存在连接问题,后来想想类似程序发现最明显的就是防火墙,因为防火墙在第一次连出的时候都会拦截,可惜这种商业级的防火墙代码一个都没找到,找到的都是简单的过滤型防火墙,无奈只有自己想,我想的方法是过滤PSH包,因为TCP连接建立时先是三次握手,这个玩过DDOS的基本都知道。
  连接发起者发送SYN包到对方。
  对方接收到后判断对应端口是否可以连接,如果可以发送SYN+ACK标志的包。
  接到后发送ACK包,至此连接就建立成功。
  当一方需要发送数据的时候,TCP的标志位是PSH+ACK, 对方收到后返回ACK包。
  我想的就是过滤PSH包。
  if (ipPacket>tcp.th_flag == 0x0018)

[1] [2] 下一页

责任编辑:小草

文章搜索:
 相关文章
热点资讯
资讯快报
热门课程培训