http://blog.csdn.net/charlesprince/article/details/5924376

  TDI FILTER 过滤驱动的功能一般用来进行整个系统中的所有网络流量的分析,记录和管理,可以实现非常强大的管理功能,这里就将讨论它的设计架构,和具体实现的方法。

  进行系统级网络数据包的过滤,很明显,第一步需要在系统内核中截取到网络数据包,那么在WINDOWS平台下,应该如何实现这样的功能?
  在WINDOWS内核中,数据的通信载体是IRP包,如果希望截取到IRP数据包,当然必须生成核模块以驱动的方式加载至内核之中。如果只是需要用来进行IRP数据包的截取,进而进行数据的分析,及下一步工作的控制。比较合适的方式就是使用TDI FILTER驱动的方式。

它在内核中的结构如图所示:
TDI FILTER ( 你的DRIVER )
TDI DRIVER ( AFD.SYS )

附加至TDI设备的方法:
  在DriverEntry时,生成两个设备,将其附加至(Attach)至Tdi驱动的Udp和Tcp设备,实现IRP包过滤功能,具体代码如下:

#define UDP_DEVICE_NAME   L"//Device//Udp"
#define TCP_DEVICE_NAME   L"//Device//Tcp"
#define TDI_FILTER_DEVICE_NAME   L"//Device//TdiFilter"typedef struct __TDI_FILTER_DEVICE_EXTENSION
{//过滤设备至少需要记录下真正Tdi网络设备的指针,来调用真正的TDI设备功能。
    PDEVICE_OBJECT pTdiDeviceObject;
} TDI_FILTER_DEVICE_EXTENSION, *PTDI_FILTER_DEVICE_EXTENSION;DriverEntry( PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath )
{UNICODE_STRING TdiDeviceName;......RtlInitUnicodeString( ( PUNICODE_STRING )&TdiDeviceName, UDP_DEVICE_NAME );ntStatus = IoCreateDevice( DriverObject, sizeof( TDI_FILTER_DEVICE_EXTENSION ), //指定设备扩展长度
        NULL, FILE_DEVICE_NETWORK, //网络类型设备0, 0, &DeviceObject ); //生成一个无名、网络类型设备,附加至TDI TCP/UDP设备,实现过滤功能。if( NT_SUCCESS( ntStatus ) ){DeviceObject->Flags |= DO_DIRECT_IO; //生成新的页表将同样的用户内存空间映射至系统虚拟内存空间来进行通信ntStatus = IoAttachDevice( DeviceObject, TdiDeviceName, ( PDEVICE_OBJECT* )DeviceObject->DeviceExtension //附加至的设备的指针将会输出至此参数中,这样就将真正的TDI设备的指针记录在过滤设备的扩展中
        ); }
}

TDI驱动的组织结构分为两个部分:
1.庞大的INTERNAL IO CONTROL子功能,包括以下功能:
  TDI_ASSOCIATE_ADDRESS 可以通过它截取出自己和对端的套接字信息,一般就是IP地址+端口号,可以在此IRP功能响应中进行套接字信息的记录。
  TDI_DISASSOCIATE_ADDRESS 它的IRP包是在closesocket函数时发生的,所以如果我们在     TDI_ASSOCIATE_ADDRESS中记录了信息,需要在此IRP的功能响应中取消之前的记录。
  TDI_CONNECT:主动连接
  TDI_LISTEN
  TDI_ACCEPT
  TDI_DISCONNECT
  TDI_SEND 它的IRP包是在调用send函数时发生的,必然,对它的响应将会实现对基于TCP协议的网络上传流量的截取。
  TDI_RECEIVE 它的IRP包是在调用recv函数时发生的,必然,对它的响应将会实现对基于TCP协议的网络下载流量的截取。
  TDI_SEND_DATAGRAM 它的IRP包是在调用sendto函数时发生的,必然,对它的响应将会实现对基于UDP协议的网络上传流量的截取。
  TDI_RECEIVE_DATAGRAM 它的IRP包是在调用recvfrom函数时发生的,必然,对它的响应将会实现对基于UDP协议的网络下载流量的截取。
  TDI_SET_EVENT_HANDLER 它的IRP包是在TDI驱动中注册一些回调用函数,当接收到数据包时,将会首先执行它们,它的具体功能将会在下一步讲述。
  TDI_QUERY_INFORMATION
  TDI_SET_INFORMATION
  TDI_ACTION
  TDI_DIRECT_SEND
  TDI_DIRECT_SEND_DATAGRAM

在TDI_SET_EVENT_HANDLER子功能中,可以注册以下回调涵数:
  TDI_EVENT_CONNECT:被动连接
  TDI_EVENT_DISCONNECT
  TDI_EVENT_ERROR
  TDI_EVENT_RECEIVE 对应于recv函数有返回数据时,将会调用此回调函数。
  TDI_EVENT_RECEIVE_DATAGRAM 对应于recvfrom函数接收到数据时,将会调用此回调函数。
  TDI_EVENT_RECEIVE_EXPEDITED 对应于函数接收到带外数据时,将会调用此回调函数。( 带外数也就是OOB数据, 在全部IRP数据包中会优先进行发送或接收,TCP协议功能 )
  TDI_EVENT_SEND_POSSIBLE

  以下将讲述数据具体传输回调功能的过滤方法

4.实现事件回调函数挂钩的方法:
  响应IRP_MJ_INTERNAL_DEVICE_CONTROL中的TDI_SET_EVENT_HANDLER子功能,记录下原始的注册事件回调函数和参数,但真正注册的是自己的回调函数,来截取所有的事件回调函数调用,实现过滤功能。
具体代码如下:

typedef struct __TDI_EVENT_CONTEXT_WRAP
{DWORD dwEventContextMark; //对自己生成的结构实例加一个四字节的标志,可以不使用。DWORD dwEventType; //记录事件回调函数的类型PVOID pOrgEventHandler; //记录原始的事件回调函数PVOID pOrgEventContext; //记录原始的事件回调函数参数PFILE_OBJECT pAssocAddr; //记录事件回调函数所绑定的本机套接字PDEVICE_OBJEXT pDeviceObjext; //记录注册事件IRP所发送至的TDI设备
} TDI_EVENT_HANDLER_WRAP, *PTDI_EVENT_HANDLER_WRAP;typedef struct __TDI_EVENT_HANDLER_LINK
{LIST_ENTRY List; //将事件回调钩子记录以链表形式进行管理
    PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrap;
} TDI_EVENT_HANDLER_LIST, *PTDI_EVENT_HANDLER_LIST;LIST_ENTRY g_TdiEventHandlerInfoList;NTSTATUS DeviceInternalIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp )
{PKIRQL OldIrql;PLIST_ENTRY pListEntry;PIO_STACK_LOCATION IrpSp;PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrap;PTDI_EVENT_HANDLER_LIST pTdiEventHandlerList;PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrap_;PTDI_EVENT_HANDLER_LIST pTdiEventHandlerList_;PTDI_FILTER_DEVICE_EXTENSION pTdiDeviceExtension; pTdiDeviceExtension = ( PTDI_FILTER_DEVICE_EXTENSION )DeviceObject->DeviceExtension;switch( IrpSp->MinorFunction ){case TDI_SET_EVENT_HANDLER:pTdiSetEvent = ( PTDI_REQUEST_KERNEL_SET_EVENT )&pIrpSp->Parameters;if( TDI_EVENT_RECEIVE == pTdiSetEvent->EventType )//|| TDI_EVENT_RECEIVE_EXPEDITED == pTdiSetEvent->EventType || TDI_EVENT_CHAINED_RECEIVE == pTdiSetEvent->EventType || TDI_EVENT_CHAINED_RECEIVE_EXPEDITED == pTdiSetEvent->EventType || TDI_EVENT_RECEIVE_DATAGRAM == pTdiSetEvent->EventType ){pTdiEventHandlerList = NULL;pTdiEventHandlerWrap = NULL;pProcessNetWorkTrafficInfo = NULL;if( NULL == pTdiSetEvent->EventHandler ){//注意!如果注册的事件回调函数是NULL的话,它表示的取消之前曾经注册过的事件回调函数, 这里当然不能挂钩,可以加入释放钩子资源的操作。goto CALL_PDO_DRIVER;}KeAcquireSpinLock( &g_SpLockTdiEventHandlerInfo, &OldIrql ); //对事件回调函数钩子列表写操作加锁保护
            pListEntry = g_TdiEventHandlerInfoList.Flink;for( ; ; ){if( pListEntry == &g_TdiEventHandlerInfoList ){pTdiEventHandlerWrap_ = NULL;break;}pTdiEventHandlerList_ = ( PTDI_EVENT_HANDLER_LIST )pListEntry;pTdiEventHandlerWrap_ = pTdiEventHandlerList_->pTdiEventHandlerWrap;if( pTdiEventHandlerWrap_->pAssocAddr == pFileObject &&pTdiEventHandlerWrap_->dwEventType == dwEventType ) //如果此本机套接字对象的相应事件回调函数已经存在,则直接对其进行修改就可以了,而不是不断的新建事件件回调钩子
                {pTdiEventHandlerWrap_->pOrgEventHandler = pEventHandler;pTdiEventHandlerWrap_->pOrgEventContext = pEventContext;break;}}if( NULL == pTdiEventHandlerWrap_ ) //没有找到,加入新的事件回调函数钩子
            {pTdiEventHandlerWrap = ( PTDI_EVENT_HANDLER_WRAP )ExAllocatePoolWithTag( NonPagedPool, sizeof( TDI_EVENT_HANDLER_WRAP ), 0 );if( NULL == pTdiEventHandlerWrap ){goto RELEASE_RESOURCE;}pTdiEventHandlerList = ( PTDI_EVENT_HANDLER_LIST )ExAllocatePoolWithTag( NonPagedPool, sizeof( TDI_EVENT_HANDLER_LIST ), 0 );if( NULL == pTdiEventHandlerList ){goto RELEASE_RESOURCE;}pTdiEventHandlerWrap->dwEventContextMark = TDI_EVENT_CONTEXT_MARK;pTdiEventHandlerWrap->dwEventType = dwEventType;pTdiEventHandlerWrap->pOrgEventHandler = pEventHandler;pTdiEventHandlerWrap->pOrgEventContext = pEventContext;pTdiEventHandlerWrap->pAssocAddr = pFileObject;pTdiEventHandlerWrap->pDeviceObject = pTdiDeviceExtension->pTdiDeviceObject;pTdiEventHandlerList->pTdiEventHandlerWrap = pTdiEventHandlerWrap;InsertTailList( &g_TdiEventHandlerInfoList, pTdiEventHandlerList );}else{pTdiEventHandlerWrap = pTdiEventHandlerWrap_;pTdiEventHandlerList = pTdiEventHandlerList_;}KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); //释放事件回调钩子列表锁if( TDI_EVENT_RECEIVE == pTdiSetEvent->EventType || TDI_EVENT_RECEIVE_EXPEDITED == pTdiSetEvent->EventType ){pTdiSetEvent->EventHandler = TdiFilterRecvEventHandler; //加入自己的事件过滤回调函数
            }else if( TDI_EVENT_CHAINED_RECEIVE == pTdiSetEvent->EventType ||TDI_EVENT_CHAINED_RECEIVE_EXPEDITED == pTdiSetEvent->EventType ){pTdiSetEvent->EventHandler = TdiFilterChainedRecvHandler;}else{pTdiSetEvent->EventHandler = TdiFilterRecvDatagramEventHandler;}pTdiSetEvent->EventContext = pTdiEventHandlerWrap;IoSkipCurrentIrpStackLocation( pIrp );ntStatus = IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp );if( !NT_SUCCESS( ntStatus ) ){if( NULL == pTdiEventHandlerWrap_ ){//如果是新加入的事件回调函数钩子,可以在出错时将其释放, 也可以保留至套接字关闭时,再进行释放KeAcquireSpinLock( &g_SpLockTdiEventHandlerInfo, &OldIrql ); //对事件回调函数钩子列表写操作加锁保护
                    RemoveEntryList( ( PLIST_ENTRY )pTdiEventHandlerList );ExFreePoolWithTag( pTdiEventHandlerWrap );ExFreePoolWithTag( pTdiEventHandlerList );KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); //释放事件回调钩子列表锁
                }}return ntStatus;}break;default:goto CALL_PDO_DRIVER;break;}RELEASE_RESOURCE:if( NULL != pTdiEventHandlerWrap ){ExFreePoolWithTag( pTdiEventHandlerWrap, NonPagedPool );}if( NULL != pTdiEventHandlerList ){ExFreePoolWithTag( pTdiEventHandlerList, NonPagedPool );}CALL_PDO_DRIVER:IoSkipCurrentIrpStackLocation( pIrp );return IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp );
}

  以上对事件回调函数加入了钩子,下一步,必须考虑对其释放的问题,否则,当原始回调函数对应的套接字释放后,你的系统将会崩溃,以下为具体代码:

在套接字关闭后,要在IRP_MJ_CLEANUP功能函数中将相关的事件回调钩子释放掉:

NTSTATUS TdiFilterCleanUp(PDEVICE_OBJECT DeviceObject, PIRP pIrp )
{NTSTATUS ntStatus;KIRQL OldIrql;PTDI_EVENT_HANDLER_LIST pTdiEventHandlerList;PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrap;PFILE_OBJECT pFileObject;TDI_FILTER_DEVICE_EXTENSION *pDeviceExtension;PIO_STACK_LOCATION pIrpSp;pDeviceExtension = ( TDI_FILTER_DEVICE_EXTENSION* )DeviceObject->DeviceExtension;pIrpSp = IoGetCurrentIrpStackLocation( pIrp );pFileObject = pIrpSp->FileObject;...//如果是主控制设备,要将调用IoCompleteIrp完成Irp, 如果是过滤设备,调用PDO设备驱动
IoSkipCurrentIrpStackLocation( pIrp );ntStatus = IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp );if( !NT_SUCCESS( ntStatus ) ){DebugPrintEx( CLEANUP_INFO,"netmon TdiFilterCleanUp IoCallDriver return ERROR/n" );return ntStatus;}//下一步,释放套接字对应的事件回调钩子KeAcquireSpinLock( &g_SpLockTdiEventHandlerInfo, &OldIrql );FIND_LIST_AGAIN:pListEntry = g_TdiEventHandlerInfoList.Flink;for( ; ; ){if( pListEntry == &g_TdiEventHandlerInfoList ){break;}pTdiEventHandlerList = ( PTDI_EVENT_HANDLER_LIST )pListEntry;pTdiEventHandlerWrap = pTdiEventHandlerList->pTdiEventHandlerWrap;if( pTdiEventHandlerWrap->pAssocAddr == pFileObject ){RemoveEntryList( pListEntry );ExFreePoolWithTag( pTdiEventHandlerWrap, 0 );ExFreePoolWithTag( pTdiEventHandlerList, 0 );goto FIND_LIST_AGAIN;}pListEntry = pListEntry->Flink;}KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql );return ntStatus;
}

那么,可以在事件回调过滤钩子函数对数据进行处理了

NTSTATUS TdiFilterRecvEventHandler( IN PVOID TdiEventContext,IN CONNECTION_CONTEXT ConnectionContext,IN ULONG ReceiveFlags,IN ULONG BytesIndicated,IN ULONG BytesAvailable,OUT ULONG *BytesTaken,IN PVOID Tsdu,OUT PIRP *IoRequestPacket)
{NTSTATUS ntStatus;PIO_STACK_LOCATION pIrpSp;PTDI_EVENT_HANDLER_WRAP pEventHandlerWrap;PTDI_COMPLETION_WRAP pCompletionWrap;LARGE_INTEGER RecvedDataSize;pEventHandlerWrap = ( PTDI_EVENT_HANDLER_WRAP )TdiEventContext;if( FALSE == g_bFiltering ) //是否进行过滤
    {goto CALL_ORIGINAL_EVENT_HANDLER;}if( FALSE != bStopRecv ){ ntStatus = STATUS_DATA_NOT_ACCEPTED;goto RELEASE_PROCESS_IO_INFO_RETURN;}ntStatus = ( ( ClientEventReceive )pEventHandlerWrap->pOrgEventHandler )( pEventHandlerWrap->pOrgEventContext, ConnectionContext, ReceiveFlags, BytesIndicated, BytesAvailable, BytesTaken, Tsdu, IoRequestPacket );if( NULL != BytesTaken && 0 != *BytesTaken ){//这里对数据进行处理, 比如可以进行通信数据量的统计
    }if( STATUS_MORE_PROCESSING_REQUIRED != ntStatus ){goto RELEASE_PROCESS_IO_INFO_RETURN;}if( NULL == *IoRequestPacket ){goto RELEASE_PROCESS_IO_INFO_RETURN;}//IoRequestPacket表示当前接收IRP中的数据如果并不完整, 并且认为接下来的数据是有价值,需要接收的话,那么需要自己新建一个IRP包,将其指针传入此参数中,并返回STATUS_MORE_PROCESSING_REQUIRED,通知IO管理不终止此IRP,TDI驱动将继续接收接下来的数据。//所以如果此IRP包存在,可以截取它的信息,具体方法下一步讲述。return ntStatus;CALL_ORIGINAL_EVENT_HANDLER:return ( ( ClientEventReceive )pEventHandlerWrap->pOrgEventHandler )( //直接调用原始的IRP钩子函数,不进行处理pEventHandlerWrap->pOrgEventContext, ConnectionContext, ReceiveFlags, BytesIndicated, BytesAvailable, BytesTaken, Tsdu, IoRequestPacket);
}

  上面讲述了使用事件回调函数钩子的方式进行通信数据的截取方法,下面讲述直接IRP包数据传输方式,也就是以下4个子功能的截取方法:

  TDI_SEND
  TDI_RECEIVE
  TDI_SEND_DATAGRAM
  TDI_RECEIVE_DATAGRAM

  在IRP_MJ_INTERNAL_DEVICE_CONTROL函数中响应以上子功能时,确认参数DeviceObject为TDI过滤设备,对所有截取到的IRP加入自己的完成函数,在此IRP被完成时( 调用IoCompleteRequest )此完成函数被调用,取得IRP处理的返回结果,进行处理。具体数据的处理对应于TDI_SEND子功能可以在IoCallDriver之前得到,因为它是应用程序传给你的,而TDI_RECEIVE子功能,应该在TDI事件回调函数或Completion回调函数中取得。
相关代码如下:

typedef struct __TDI_COMPLETION_WRAP
{...//可以加入用来记录/处理数据的成员, 比如通信标志, 流量统计等
  PIO_COMPLETION_ROUTINE pCompletionRoutine;LPVOID pContext;
} TDI_COMPLETION_WRAP, *PTDI_COMPLETION_WRAP;

加入自定义的CompletionRoutine的方法:

if( TDI_SEND == MinorFunction ||TDI_SEND_DATAGRAM == MinorFunction || TDI_RECEIVE == MinorFunction || TDI_RECEIVE_DATAGRAM == MinorFunction )
{if( TDI_RECEIVE == MinorFunction && TDI_RECEIVE_PEEK == ( ULONG )pIrpSp->Parameters.Others.Argument2 ){//TDI_RECEIVE_PEEK不会真正接收数据,可以不需要对其进行过滤。goto SKIP_CURRENT_STACK_LOCATION;}pCompletionWrap = ( PTDI_COMPLETION_WRAP )ExAllocateFromNPagedLookasideList( &g_CompletionWrapList ); //可以使用链表或HASH等数据结构来管理所有的CompletionRoutine包装信息,这里使用了NPAGED_LOOKASIDE_LIST,它的优势在于系统中所有的NPAGED_LOOKASIDE_LIST资源的最大占用量将会被内存管理器动态管理if( NULL == pCompletionWrap ){goto SKIP_CURRENT_STACK_LOCATION;}//这里可以设置CompletionRoutine的具体工作参数,比如具体操作的类型,原始的Completion函数等,在用户层传送至的IRP中是不会设置CompletionRoutine函数的,但其它驱动传送至的IRP中可能会进行设置,如在Receive事件回调函数中的IoRequestPacket参数IoCopyCurrentIrpStackLocationToNext( pIrp ); //设置下一个设备栈工作参数
IoSetCompletionRoutine( pIrp, TdiFilterCompletion, pCompletionWrap, TRUE, TRUE, TRUE);//这里就为这个IRP加入自己的CompletionRoutine函数goto CALL_PDO_DRIVER;SKIP_CURRENT_STACK_LOCATION:IoSkipCurrentIrpStackLocation( pIrp );CALL_PDO_DRIVER:return IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp );
}

具体的Completion函数的工作:

NTSTATUS TdiFilterCompletion( PDEVICE_OBJECT pDeviceObject, PIRP pIrp, LPVOID pContext )
{NTSTATUS ntStatus;PTDI_COMPLETION_WRAP pCompletionWrap;LARGE_INTEGER TransferredDataSize;PIRP pMasterIrp;PIO_STACK_LOCATION pIrpSp;ntStatus = pIrp->IoStatus.Status;pCompletionWrap = ( PTDI_COMPLETION_WRAP )pContext;if( NT_SUCCESS( ntStatus ) ){//可以在这里对成功传输的数据进行处理
    }//这里可以调用原始的Completion函数
    RETURN_SUCCESS:return ntStatus;
}

  需要注意的是,如果为IRP包加入了CompletionRoutine之后,那么在驱动卸载( Unload )之前,必须保证所有IRP已经执行过此Completion函数, 如果在驱动被从内存中卸载后才执行, 将会使系统崩溃。
处理方法为:
  1.不实现DriverUnload函数,使驱动只有在系统关闭,底层设备被卸载时,才能完成真正的卸载。这是的一般    FILTER驱动的工作方式,
  2.使用线程同步的方法保证Completion函数的执行,Windows XP或之后的系统也提供了一个API,         SetCompletionRoutineEx来保证驱动在Completion函数完成前不被卸载。

  至此,讲述TDI过滤驱动组织框架,可以为它添加一些更加完善的功能。

转载于:https://www.cnblogs.com/himessage/archive/2013/01/15/2860834.html

(转)TDI FILTER 网络过滤驱动完全解析相关推荐

  1. NDIS LWF网络过滤驱动开发(一):LWF简介及数据结构说明

    写在之前:换工作了,做Win驱动开发,还是网络过滤驱动.之前从未接触过这些,只是做着单机的桌面应用程序,所以一切是从头开始.从驱动到网络,很多的不懂,一步步走来,现在多少有些进展了,现在就总结下这段过 ...

  2. WFP网络过滤驱动-限制网站访问

    文章目录 前言 WFP入门介绍 WFP基本架构 名词解释 代码基本结构 代码示例 前言 WFP Architecture - Win32 apps | Microsoft Learn是一个网络流量处理 ...

  3. wfp 禁用ip_WFP网络过滤驱动——限制网站访问

    [md] 0x1前言 文中的注释有的来自微软官方的解释翻译,有的来自Windows内核安全与驱动开发书中的解释,也有的来自我个人的理解.代码功能是在Windows内核安全与驱动开发第15章中Wfpsa ...

  4. wfp 禁用ip_[原创]WFP网络过滤驱动——限制网站访问

    0x1前言 文中的注释有的来自微软官方的解释翻译,有的来自Windows内核安全与驱动开发书中的解释,也有的来自我个人的理解.代码功能是在Windows内核安全与驱动开发第15章中Wfpsample代 ...

  5. TDI Filter 过滤驱动

    By Fanxiushu  2013, 引用和转载请注明原作者 为了让大家有兴趣阅读下去, 举个正在使用的可能大家都比较熟悉的例子: 360 的安全卫士里,有个流量防火墙的功能, 它可以监视每个进程的 ...

  6. WIN7以上系统WDDM虚拟显卡开发(WDDM Filter/Hook Driver 显卡过滤驱动开发之一)

    by fanxiushu 2018-09-16 转载或引用请注明原始作者. 这里讨论的都是win7以上平台的WDDM模型的显卡驱动,而不是WINXP之前的XPDM模型的显卡驱动. 实际上没有" ...

  7. windows7以上平台 NDISFilter 网卡过滤驱动开发

    by fanxiushu 2019-01-16 转载或引用请注明原始作者 这里讨论的都是基于WIN7以上平台,NDIS 6.0以上版本的网络驱动. 做个驱动的目的,是因为很早之前,我使用 TDI 和 ...

  8. Windows 文件系统过滤驱动开发教程 (第二版)

    Windows 文件系统过滤驱动开发教程 (第二版)       楚狂人-2007-上海 (MSN:walled_river@hotmail.com)          -1.  改版序....... ...

  9. tdi_fw贴码析(TDI开源网络防火墙分析)

    tdi_fw是一个基于TDI的网络防火墙,继承自tdifw,完全采用AttachDevice的方式来实现功能,目标是成为一个高效轻巧的架构,并稳定运行于xp,win7的32位与64位版本. memtr ...

最新文章

  1. 互联网协议 — RTSP 实时流传输协议
  2. 「数据库系列三」磁盘、内存和带宽
  3. java socket 报文解析_java socket解析和发送二进制报文工具(附java和C++转化问题)
  4. luogu P1578 奶牛浴场
  5. Oracle/云MySQL/MsSQL“大迁移”真相及最优方案
  6. 业内为啥如此恨视觉中国
  7. sqldependency 实现原理_2020阿图什方形摇摆筛安装原理
  8. 送书 | 别泡枸杞,别晒步数!7招搞懂健康数据,有型有颜等TA来撩
  9. 按键精灵手机助手之实战篇(四)项目源码
  10. GlusterFS 4.0开发计划解读
  11. torch的maximum与max以及导出onnx
  12. SpringBoot整合IoTDB
  13. 心学与技术-大学之道和尽心知性
  14. 醉袖迎风受落花——好代码的10条认知
  15. iMX6ul开发指导
  16. 学生管理系统--【Java+MySQL】--数据库系统概论综合性实验
  17. Linux学习之查看log与查看进程_Sinno_Song_新浪博客
  18. Delphi与Windows 7下的用户账户控制(UAC)机制(加小盾牌),注册表没反应
  19. flash幻灯片动画模板
  20. matlab 控制硬件,自动控制原理实验教程(硬件模拟与MATLAB仿真)

热门文章

  1. 2011年的MVP礼包
  2. 四色原型图进行业务建模的思考
  3. HP_UX常用指令列表(转,整理过,方便使用)
  4. Windows10家庭版安装Docker Desktop(非Docker Toolbox)
  5. keras模型中的默认初始化权重
  6. COM组件的运行机制
  7. Cocos2D将v1.0的tileMap游戏转换到v3.4中一例(八)
  8. 解决SQL命令行回退的问题
  9. ZooKeeper1 利用虚拟机搭建自己的ZooKeeper集群
  10. 利用百度LBS做一个小Demo