Tcp过滤器的实现

1 引言

前段时间做了一个基于IPFILTERDRIVER的ip过滤驱动,使用了一段时间却出现了不少问题:

1、首先,IPFILTERDRIVER只能挂接一个驱动。也就是说,如果其他的驱动先挂接了IPFILTERDRIVER,那么我们的安装将失败;
2、其次,有的2000pro系统下居然缺少IPFILTERDRIVER驱动组件;
3、最后,某些系统会出现997错误,即“重叠IO操作正在进行”。

基于上述问题,重新实现了一个Tcp设备的过滤驱动程序TcpFilter,使用它来拦截ip访问操作。

2 过滤驱动程序

在2000以上的系统中,都实现了一个Tcp设备"//Device//Tcp",大部分上层的Intel网络通信都是通过这个设备完成的,如果我们实现一个Tcp设备的上层过滤程序,便能拦截到用户的网络访问。Tcp设备过滤程序的实现和其他驱动的过滤程序没什么两样,其代码如下:

      RtlInitUnicodeString( &usFilterName, FILTER_NAME ); 
      IoCreateDevice( pDrvObj,
                     sizeof(DEVICE_EXTENSION),
                     &usFilterName,      // filter driver name
                     FILE_DEVICE_UNKNOWN,
                     0, TRUE,
                     &g_pFilterDevObj );
     
      RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME); 
      IoCreateSymbolicLink( &DosDeviceName, &usFilterName );

      RtlInitUnicodeString( &usTargetName, TARGET_NAME ); 
      IoGetDeviceObjectPointer( &usTargetName,
                                      FILE_ALL_ACCESS,
                                      &pTargetFileObj,
                                      &pTargetDevObj );

      // Initialize the Device Extension
      pDevExt = (PDEVICE_EXTENSION) g_pFilterDevObj->DeviceExtension;
      pDevExt->pDeviceObject = g_pFilterDevObj;    // back pointer
   
      // Pile this new filter on top of the existing target
      pDevExt->pTargetDevice =         // downward pointer
                  IoAttachDeviceToDeviceStack( g_pFilterDevObj, pdo);
      
      for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
            if (i!=IRP_MJ_POWER)
                  pDrvObj->MajorFunction[i] = Dispatch;

3 Dispatch函数

Dispatch函数的完整代码如下:

NTSTATUS Dispatch(
               IN PDEVICE_OBJECT pDevObj,
               IN PIRP pIrp )
{           
      PDEVICE_EXTENSION pFilterExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
           
      PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
           
      PIO_STACK_LOCATION pNextIrpStack;
  
      UCHAR MajorFunction = pIrpStack->MajorFunction; 
      UCHAR MinorFunction = pIrpStack->MinorFunction; 
  
      PVOID p = &pIrpStack->Parameters;
      if(MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL &&
            MinorFunction == TDI_CONNECT) // IOCTL_TDI_CONNECT
      {
            TDI_REQUEST_KERNEL_CONNECT* trk = (TDI_REQUEST_KERNEL_CONNECT*)p;
            TRANSPORT_ADDRESS* ta = (TRANSPORT_ADDRESS*)
            trk->RequestConnectionInformation->RemoteAddress;
            if(ta->Address[0].AddressType == TDI_ADDRESS_TYPE_IP)
            {// only handle ip address
                  TDI_ADDRESS_IP* ipaddr = (TDI_ADDRESS_IP*)&ta->Address[0].Address;
                  USHORT port = ((ipaddr->sin_port&0xff) << 8) |
                                          ((ipaddr->sin_port&0xff00) >> 8);
                  DbgPrint(" ==> %u.%u.%u.%u(%u)", 
                        ipaddr->in_addr&0xff, 
                        (ipaddr->in_addr&0xff00)>>8,
                        (ipaddr->in_addr&0xff0000)>>16,
                        (ipaddr->in_addr&0xff000000)>>24,
                        port);
                  if(CheckIPAddress(ipaddr->in_addr))
                  {
                        pIrp->IoStatus.Status = STATUS_REMOTE_NOT_LISTENING;
                        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
                        return STATUS_REMOTE_NOT_LISTENING;    
                  }
            }
      }
      else if(MajorFunction == IRP_MJ_DEVICE_CONTROL)
       {
            NTSTATUS status = STATUS_SUCCESS;
            // 处理用户自定义的IoControlCode
            switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode)
            {
            case ADD_FILTER:
                  DbgPrint("add filter %d", pIrpStack->Parameters.DeviceIoControl.InputBufferLength);
                  AddFilterIPList((PULONG)pIrp->AssociatedIrp.SystemBuffer, 
                        pIrpStack->Parameters.DeviceIoControl.InputBufferLength/4);
                  break;
            default:
                  goto passthru;
                  break;
            }

            IoCompleteRequest(pIrp, IO_NO_INCREMENT);

            return status;
      }

passthru:
      // Copy args to the next level
      pNextIrpStack = IoGetNextIrpStackLocation( pIrp );

/* IoCopyCurrentIrpStackLocationToNext( pIrp );
 // *pNextIrpStack = *pIrpStack;
  
//   DbgPrint("Dispatch: Majorfun: %d, MinorFun: %d.", pIrpStack->MajorFunction,
//    pIrpStack->MinorFunction);

   // Set up a completion routine to handle the bubbling
   // of the "pending" mark of an IRP
   IoSetCompletionRoutine(
          pIrp,
          GenericCompletion,
          NULL,
          TRUE, TRUE, TRUE );
   */
      // 如果使用上面的代码会出现NO_MORE_IRP_STACK_LOCATIONS蓝屏
      IoSkipCurrentIrpStackLocation( pIrp );  
      // Pass the IRP to the target.
      return IoCallDriver(
                pFilterExt->pTargetDevice,
                pIrp );
}

3.1 函数流程

Dispatch函数捕获上层的所有命令,首先拦截上层的Tcp连接操作,如果上层连接的地址没通过测试(CheckIPAddress),则中断此次连接return STATUS_REMOTE_NOT_LISTENING。其次,捕获应用层发给驱动的命令字,最后,把所有其他的命令传递给下层驱动处理。

3.2 TDI客户端

Dispatch函数接收到的命令由TDI客户端发送,如果想详细了解TDI的通信过程可以参考DDK或使用上述函数跟踪。TDI的网络命令其MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL,当TDI企图建立远程连接时,MinorFunction == TDI_CONNECT。此时远程地址的解析方式可参考上述完整代码。

3.3 IoSkipCurrentIrpStackLocation

刚开始的时候,我使用的是IoCopyCurrentIrpStackLocationToNext。但启动驱动不久便会出现蓝屏,bug码为:NO_MORE_IRP_STACK_LOCATIONS,费了很长时间也没解决此问题,最后索性改为IoSkipCurrentIrpStackLocation才一切正常。至今仍不知问题出在哪里,望高人指点迷津。

4 UnLoad问题

本来实现了一个unload函数,可每次卸载驱动的时候都蓝屏,错误码DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS,搞不定他,所以硬着头皮每次重起系统来调试程序。我写的unload函数的代码如下,希望有高人指点。

VOID
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
 UNICODE_STRING DosDeviceName;
 PDEVICE_OBJECT pFilterObj = DriverObject->DeviceObject;
 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pFilterObj->DeviceExtension;

 // Remove symbolic link
 RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME);
 IoDeleteSymbolicLink(&DosDeviceName); 

 // detach
 ObDereferenceObject(pTargetFileObj);
 IoDetachDevice(pDevExt->pTargetDevice);

 // Remove the device
 IoDeleteDevice(pFilterObj);
 DbgPrint("tcp filter unload ok");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值