[版权所有]
本文作者是楚狂人,代码来源于开源工程tdifw与DDK的例子,
有问题欢迎与我联系讨论。
mail:*******************
QQ: 16191935
msn:************************入党申请书范文2010
-----------------------------------------------------------
Windows TDI过滤驱动开发
目 录
(0) TDI概要
(1) 准备工作
(2) TDI设备与驱动入手
(3) 绑定设备
(4) 简单的处理请求
(5) 基础过滤框架
(6) 主要过滤的请求类型
(7) CREATE的过滤
(8) 准备解析ip地址与端口
(9) 获取生成的IP地址和端口
(10) 连接终端的生成与相关信息的保存
写谷雨的古诗(11) TDI_ASSOCIATE_ADDRESS的过滤
(12) TDI_CONNECT的过滤
(13) TDI_SEND,TDI_RECEIVE,TDI_SEND_DATAGRAM,TDI_RECEIVE_DATAGRAM
(14) 设置事件
(15) TDI_EVENT_CONNECT类型的设置事件的过滤
英文月份(16) 一个传说中的问题
(17) 收尾与清理的工作
(0) TDI概要
最早出现的网络驱动应该是网卡驱动,这是Windows的理所当然的需求,为了进一步分割应用程序的网络数据传输与下层协议直到下层硬件的关系,又出现了协议驱动,后来微软和硬件商联合制定了NDIS标准,作为从硬件到协议的内核驱动程序的调用接口标准,而协议驱动与应用层的API之间,则出现了TDI接口。
最近国内安全软件的开发兴起,网络驱动的开发在其中有不少的应用,如果我们学习TDI接口的话,可能有以下一些目的:
自己要开发协议驱动,向上提供TDI接口,这种可能性存在,但不广泛。
我们想自己调用TDI接口,来进行网络数据传输,意义不大。
我们对TDI进行协议层过滤,开发防火墙或类似安全监控软件,这种应用还是比较多的。
(1) 准备工作
为了开始研究网络驱动开发,建议你做如下的准备:
安装VC、VC6.0或者更老的版本也可以编译驱动程序,但是本文提供的工程都是VC 工程,如果要看范例代码你可能必须安装VC。
然后需要安装DDK,另外 TDI过滤在DDK中并没有现成的例子(但是提供TDI接口的NDIS网络驱动应该是有的)。直接研究TDI接口是件痛苦的事情,这套接口秉承了微软公司各类接口的特点:臃肿而且复杂。幸运的是有用TDI过滤写成的本地防火墙的开源代码可以研究。
你必须自己学习DDK的编译方法,和一般的应用程序稍有不同。
tdifw是一个基于TDI过滤的开源本地防火墙,有兴趣的读者可以在这里下载代码:
tdifw.sourceforge/
这个防火墙有很多额外的代码,我把它进行了精简和修改,附在本文的范例代码中提供下载,工作空间为tdi_fw.sln。可以打开直接编译。
此外作为驱动开发者,你还必须准备一些工具:
驱动加载工具,编译好一个驱动你可以动态加载它,(NDIS网络驱动稍微有些不同,以后再详细介绍)。这样你需要一个工具加载它,我推荐。遗憾的是网络上有很多软件叫做installer,我只能说这个的图标是一个黄安全帽。
输出查看工具,推荐,你可以在以下地址下载:
www.sysinternals/Utilities/DebugView.html
给驱动程序配上界面绝对不是一件简单的工作,所以需要一个输出查看工具,这样至少在程序中可以print一些东西,用这个工具可以看到,在没法安装调试工具的情况下,print能起巨大的作用。我有softice老安装失败最后全部依靠print解决bug的经历。
调试工具,推荐windbg和softice。
windbg可以免费下载,地址为www.microsoft/whdc/devtools/debugging/default.mspx
windbg和softice的使用都需要专门的章节介绍,本文略过,所以有兴趣的读者请在驱动开发网上寻相关的介绍。
没有安装并不会使用调试工具的情况下,你也可以继续阅读并试用本文附带的代码。
(2) TDI设备与驱动入手
TDI是一组接口的名字,协议驱动本身都是NDIS协议驱动。但是其上提供TDI接口,Windows的上层网络组件调用这些接口来使用协议驱动。这些接口是可以被过滤的,下面以一个TDI过滤驱动为例。
TDI过滤相比NDIS过滤的一大好处是TDI离应用层比较近,容易得到应用程序的相关信息。比如一个连接建立,你可以获取打开这个连接的PID,也就得知了打开这个连接的应用程序。而不足之处则是安全性,若我想写一个木马来绕过TDI接口,我可以不调用一般网络API来避免调用TDI接口,不过NDIS过滤虽然相对保险,绝对的安全依然是不可能的。
提供TDI接口的Windows协议驱动将在Windows内核中生成所谓的TDI设备。设备是有路径和名字的,比较著名的设备有以下几个: "\\Device\\Tcp",对应TCP协议。
"\\Device\\Udp",对应UDP协议。
"\\Device\\RawIp",对应原始IP包。
如果你安装了TCPIP之外的协议,应该还有更多,既然我们要过滤TDI接口,那么首先就是生成我们自己的设备,来绑定这些设备。
这就是过滤的原理。如果我们用自己的设备绑定了原有的设备,那么Windows将把本来给原设备的请求给我们的新设备。从而可以过滤他们。
驱动开发的老手对生成设备和绑定设备再熟悉不过,但是没有开发过驱动的朋友可能有些困惑,我的建议是没有必要一开始就试图了解太多概念,只要了解代码如何写就可以了。
我们建立.c文件.包含如下文件:
#include <ntddk.h>
#include <tdikrnl.h>童装品牌排行榜
这两个文件都是ddk的头文件,这就是为何你得安装DDK,然后我们开始写一个函数DriverEntry,
这个函数相当与一般Windows应用程序之WinMain,原型如下:
NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
IN PUNICODE_STRING theRegistryPath)
IN是一个无任何内容的宏,代表后面的参数为输入参数,有些用来返回结果的指针前面会带OUT,仅仅起提示作用,最简单的写法为:
NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
IN PUNICODE_STRING theRegistryPath)
{
return STATUS_UNSUCCESSFUL;
}
这个驱动已经可以编译了,只是无法加载,总是返回STATUS_UNSUCCESSFUL错误。
(3) 绑定设备
下面我们在这个过程中,完成绑定主要的TDI设备的任务,下面这个函数来自tdi_fw工程,你可以在tdi_fw.c中到这些代码。
// 这个函数生成一个设备来绑定一个已知名字的设备。
驾NTSTATUS
c_n_a_device(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT *fltobj, PDEVICE_OBJECT *oldobj,
wchar_t *devname)
{
NTSTATUS status;
UNICODE_STRING str;
// 生成自己的新设备
status = IoCreateDevice(DriverObject,
0,
NULL,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
fltobj);
if (status != STATUS_SUCCESS) {
KdPrint(("[tdi_fw] c_n_a_device: IoCreateDevice(%S): 0x%x\n", devname, status));
return status;
}
// 设置设备IO方式为直接IO
(*fltobj)->Flags |= DO_DIRECT_IO;
// 将要绑定的设备名初始化为一个Unicode字符串
RtlInitUnicodeString(&str, devname);
// 绑定这个设备
status = IoAttachDevice(*fltobj, &str, oldobj);
if (status != STATUS_SUCCESS) {
KdPrint(("[tdi_fw] DriverEntry: IoAttachDevice(%S): 0x%x\n", devname, status));旅游交流
return status;
}
KdPrint(("[tdi_fw] DriverEntry: %S fileobj: 0x%x\n", devname, *fltobj));
return STATUS_SUCCESS;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论