科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网网络频道简析windows软件防火墙实现技术

简析windows软件防火墙实现技术

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

从Windows软件防火墙的诞生开始,这种安全防护产品就在跟随着不断深入的黑客病毒与反黑反毒之争,不断的进化与升级。

作者:中国IT实验室 2007年7月23日

关键字: 防火墙 软件防火墙 Windows

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共3页)

应用程序访问网络控制

  以往的防火墙只能古板的允许或者禁止整个系统去访问网络上的目标,比如允许了系统可以访问外网的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就可以得到进程号。

  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
      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",
        ((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);
          //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";
        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....//判断进程号

  ....
}
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章