网管联盟 | 网管论坛 | 网管u家 | 网管博客 | 网管软件 | 网管求职 | 小游戏 | 网管搜索 | 网管原创 | 网管聚合 | 网管读摘 | 网管焦点 | 世界素材 | 会员投稿 | 会员中心 
中国网管联盟
Windows Linux Cisco 网络技术 数据库 黑客攻防 DotNet Java PHP 认证 新闻资讯 服务器 存储资讯 网络设备 网管学堂 技术专题 焦点 网吧频道
 当前位置: > bitsCN.com > windows > 系统安全 > 防火墙 > 微软Windows软件防火墙实现技术简述  

微软Windows软件防火墙实现技术简述

2007-07-21  作者:bitsCN整理  来源:中国网管联盟  点评 投稿 收藏

应用程序访问网络控制

  以往的防火墙只能古板的允许或者禁止整个系统去访问网络上的目标,比如允许了系统可以访问外网的http端口,就允许了所有进程,不能只控制IE等几个进程有权这样做。该技术的出现解决了这个问题,对每个陌生的进程都会询问客户是否允许访问网络,因此还有一定的查杀未知木马病毒的能力。

  由于NDIS里面的那些send/receive handler全都是由tdi缓冲之后再调用的,运行的上下文全都是kernel,并且不保存原先进行tdi操作的进程号,因此在封包过滤的NDIS钩子层次无法取得进行操作的进程ID。想要解决应用程序访问网络控制的问题,就需要在tdi或者更高的层次上使用钩子。一般来说,主流是使用tdi钩子,在进程的网络调用栈进行到tdi的TDI_CONNECT,TDI_LISTEN,TDI_RECEIVE,TDI_SET_EVENT_HANDLER等调用时,进行进程判断和提示。

  对于winsock的应用程序来说,最重要的是主动连接请求,TDI_CONNECT;接受连接请求,TDI_SET_EVENT_HANDLER中的TDI_EVENT_CONNECT。对于udp收发,还要处理TDI_SEND_DATAGRAM,TDI_RECEIVE_DATAGRAM和TDI_SET_EVENT_HANDLER中的TDI_EVENT_RECEIVE_DATAGRAM请求。这个时候,直接PsGetCurrentProcessId就可以得到进程号。 中国网管联盟bitsCN.com

  tdi钩子有一个问题,就是对于TDI_SET_EVENT_HANDLER的hook,很可能不能及时发挥作用,必须要重起以后。由于不像ndis钩子需要hook系统函数或者修改系统数据结构,tdi钩子可以直接使用微软提供的过滤器驱动程序接口,在安装编写上要比ndis钩子简单的多,IoAttachDeviceToDeviceStack就可以了。

  给出一段detour的tdi的dispatch routine的代码:


NTSTATUS hook_disp(IN PDEVICE_OBJECT parampdrvob, IN PIRP irp)
{
  ....

  case IRP_MJ_INTERNAL_DEVICE_CONTROL:
    switch(irpsp->MinorFunction)
  {
      ///原来想得要监控的几个似乎afd并不使用,而是用set event handler
    case TDI_LISTEN:
#ifdef bydbg
      DbgPrint("bytdiflt:TDI_LISTEN traped.should caused by kmd other than AFD.\n");

#endif
      stat=gettcpportbyfile(irpsp->FileObject);
#ifdef bydbg
      DbgPrint("bytdiflt:**********TDI_EVENT_CONNECT port:%d.***********\n",stat);
#endif
      if(stat==0 || stat==-1){break;}//non-tcp or internal error

网管网www_bitscn_com


      if(denyport[(unsigned short)stat]==1)//直接失败请求
      {
#ifdef bydbg
        DbgPrint("bytdiflt:*********port %d blocked!!*********\n",stat);
        //DbgBreakPoint();
#endif
        stat=STATUS_ACCESS_VIOLATION;
        irp->IoStatus.Status=stat;
        irp->IoStatus.Information=0;
        IoCompleteRequest(irp, IO_NO_INCREMENT);

        return stat;
      }
      break;

    case TDI_RECEIVE:
#ifdef bydbg
      DbgPrint("bytdiflt:TDI_RECEIVE traped.should caused by kmd other than AFD.\n");
      //DbgBreakPoint();
#endif
      break;
    case TDI_SET_EVENT_HANDLER:
#ifdef bydbg
      DbgPrint("bytdiflt:TDI_SET_EVENT_HANDLER traped.req local_node:%x\n",irpsp->FileObject);
      DbgPrint("TDI_SET_EVENT_HANDLER EventType:%d EventHandler:%x EventContext:%x\n",
网管网www.bitscn.com

        ((TDI_REQUEST_KERNEL_SET_EVENT*)&(irpsp->Parameters))->EventType,
        ((TDI_REQUEST_KERNEL_SET_EVENT*)&(irpsp->Parameters))->EventHandler,
        ((TDI_REQUEST_KERNEL_SET_EVENT*)&(irpsp->Parameters))->EventContext
        );
#endif
      switch(((TDI_REQUEST_KERNEL_SET_EVENT*)&(irpsp->Parameters))->EventType){
      case TDI_EVENT_CONNECT:
        tmpstrptr="TDI_EVENT_CONNECT";
        stat=gettcpportbyfile(irpsp->FileObject);
#ifdef bydbg
        DbgPrint("bytdiflt:**********TDI_EVENT_CONNECT port:%d.***********\n",stat);
#endif
        if(stat==0 || stat==-1){break;}//non-tcp or internal error
        if(denyport[(unsigned short)stat]==1)//完成请求但不做事情
        {
#ifdef bydbg
          DbgPrint("bytdiflt:*********port %d blocked!!*********\n",stat);

网管网www.bitscn.com


          //DbgBreakPoint();
#endif
          stat=STATUS_SUCCESS;
          irp->IoStatus.Status=stat;
          irp->IoStatus.Information=0;
          IoCompleteRequest(irp, IO_NO_INCREMENT);
          return stat;
        }
        break;

      case TDI_EVENT_RECEIVE:
        tmpstrptr="TDI_EVENT_RECEIVE";
        break;
      case TDI_EVENT_CHAINED_RECEIVE:
        tmpstrptr="TDI_EVENT_CHAINED_RECEIVE";
        break;
      case TDI_EVENT_RECEIVE_EXPEDITED:
        tmpstrptr="TDI_EVENT_RECEIVE_EXPEDITED";
        break;
      case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED:
        tmpstrptr="TDI_EVENT_CHAINED_RECEIVE_EXPEDITED";
        break;
      case TDI_EVENT_RECEIVE_DATAGRAM:
        tmpstrptr="TDI_EVENT_RECEIVE_DATAGRAM";

网管网www.bitscn.com


        break;

      default:
        tmpstrptr="Other TDI_EVENT";
        break;
      }
#ifdef bydbg
      DbgPrint("EventType is:%s\n",tmpstrptr);
#endif
      break;
    case TDI_CONNECT://处理主动外出连接
      stat=gettcpportbyfile(irpsp->FileObject);
#ifdef bydbg
      if(stat==0 || stat==-1)//non-tcp or internal error
      {DbgPrint("bytdiflt:**********TDI_CONNECT local port UNKNOWN.***********\n");}
      else
      {DbgPrint("bytdiflt:**********TDI_CONNECT local port:%d.************\n",stat);}
      //DbgBreakPoint();
#endif
      break;

  ....


  PsGetCurrentProcessId....//判断进程号

  ....
}
中国网管联盟bitsCN.com


TAGs技术   实现   防火墙   软件   stat   一个   ndis   break   监控    
 上一篇:Windows 防火墙探究   下一篇:Windows Vista防火墙全攻略
微软Windows软件防火墙实现技术简述 评论:
loading.. 评论加载中…
评论:请自觉遵守互联网相关政策法规,评论不得超过250字。

验证码: 注册用户
本类热门排行:
最新推荐文章:
网管论坛交流: