阅读:4147回复:40
通过tdi如何监听、判断外部对本机的访问请求
请问大家:
我最近有个新任务,意思就是: 取代各通信程序(例如apache)的监听端口,在他们之前统一分配一个唯一的监控端口,对来访的消息进行监控,然后根据来访的消息进行判断,首先判断出是不是我们自己的用户,如果是继续判断他选择的应用是什么(比如说浏览网页,即想要与apache进行通信),最后给他开辟对应应用程序的端口放他进来,比如他想浏览网页,那么就把apache的端口给他打开。 我觉得这就是个类似于防火墙的东西。我想虽然这个唯一的监控端口可以控制所有的应用端口开闭,但既然是测试,我就只针对一个apache来做,也就是说一个访问网页的请求过来,我先在apache之前拦下它(通过唯一的那个控制/监听端口),然后判断它是不是自己的用户,如果合法,我再把apache端口给他打开,让他访问。 要做这个东西,应该是用到tdi吧?我最近一直在研究tdi,所以希望以这个方向为突破口。可是思路是什么呢?请问各位有例子或者建议吗?还有,我应该怎么建这个模型呢?如何给老板演示呢?如何知道(监听到)访问请求? 谢谢各位了,急!大家多帮我,我是菜鸟! 我的邮箱:wuxo@sina.com 如果哪位好心人能帮我编写一些简单的例子,真的是感激不尽!!! |
|
沙发#
发布于:2008-03-23 21:36
我也想学习看来的看开源的防火墙了,呵呵
|
|
板凳#
发布于:2007-08-13 11:07
好
谢谢各位,我从新开贴,探讨一些与驱动有关的,比较基本的问题,希望大家多来参与,任何人都可以发问题,大家一起探讨。 希望大家首先心态要好,本着共同学习共同进步的原则。 |
|
地板#
发布于:2007-08-10 23:09
TRANSPORT_ADDRESS *pTransAddr=(TRANSPORT_ADDRESS*)pRemoteAddress;
TDI_ADDRESS_IP *pIPAddress=(TDI_ADDRESS_IP*)(unsigned char*)&pTransAddr->Address[0].Address; ulRemoteIP=htonl(pIPAddress->in_addr); nRemotePort=ntohs(pIPAddress->sin_port); |
|
|
地下室#
发布于:2007-08-10 23:04
我再回答一次,这个贴子。以后靠你自己了。你并没有去搜索以前的贴子,也没有去认真的看资料,这种态度不行的!这也是其它的牛不想回答的原因!我不是好心,纯粹路过,兼测试驱动!所以不必谢我!
|
|
|
5楼#
发布于:2007-08-10 17:49
代码最新版,请执教,谢谢
#include <ntddk.h> #include <tdikrnl.h> //定义了一个上下文信息结构,为了保存需要的信息 typedef struct{ PFILE_OBJECT fileobj; //address object PVOID old_handler; //old event handler PVOID old_context; //old event handler context }TDI_EVENT_CONTEXT; //自己的回调函数 NTSTATUS mytdi_event_connect( IN PVOID TdiEventContext, IN LONG RemoteAddressLength, IN PVOID RemoteAddress, IN LONG UserDataLength, IN PVOID UserData, IN LONG OptionsLength, IN PVOID Options, OUT CONNECTION_CONTEXT *ConnectionContext, OUT PIRP *AcceptIrp) { KdPrint(("oh? someone is coming~ no way~!!!\n")); return STATUS_CONNECTION_REFUSED; } //TDI派遣函数 NTSTATUS TDIDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { NTSTATUS status; PIO_STACK_LOCATION irps= IoGetCurrentIrpStackLocation(irp); if(irps->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL && irps->MinorFunction == TDI_SET_EVENT_HANDLER) { TDI_REQUEST_KERNEL_SET_EVENT r = (TDI_REQUEST_KERNEL_SET_EVENT)&irps->Parameters; if(r->EventType == TDI_EVENT_CONNECT && r->EventHandler != NULL) { TDI_EVENT_CONTEXT cxt; cxt->fileobj = irps->FileObject; //这么写对么??? cxt->old_handler = r->EventHandler; ctx->old_context = r->EventContext; r->EventHandler = mytdi_event_connect; r->EventContext = ctx; //自己的调用函数处理完毕后,调用原来的回调函数 status = ((PTDI_IND_CONNECT)(ctx->old_handler)) (ctx->old_context, RemoteAddressLength, RemoteAddress, UserDataLength, UserData, OptionsLength, Options, ConnectionContext, AcceptIrp); } } } ////卸载驱动 NTSTATUS ReleaseTDIDevices(void) { NTSTATUS Status; UNICODE_STRING usDriverName; PDRIVER_OBJECT DriverObjectToHookPtr; UINT i; RtlInitUnicodeString(&usDriverName,L"\\Driver\\Tcpip"); Status = ObReferenceObjectByName(&usDriverName,OBJ_CASE_INSENSITIVE,NULL,0,IoDriverObjectType,KernelMode,NULL,&DriverObjectToHookPtr); if(Status != STATUS_SUCCESS) return Status; for(i = 0;i < IRP_MJ_MAXIMUM_FUNCTION;i++) DriverObjectToHookPtr->MajorFunction = RealTDIDriverObject.MajorFunction; return STATUS_SUCCESS; } //TDI入口函数 NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) { NTSTATUS ntStatus=STATUS_SUCCESS; DRIVER_OBJECT RealTDIDriverObject; UNICODE_STRING myDriverName; PDRIVER_OBJECT DriverObjectToHookPtr; UINT i; RtlInitUnicodeString(&myDriverName,L"\\Driver\\Tcpip"); Status = ObReferenceObjectByName( &myDriverName, OBJ_CASE_INSENSITIVE, NULL, 0, IoDriverObjectType, KernelMode, NULL, &DriverObjectToHookPtr ); if(Status != STATUS_SUCCESS) { KdPrint(("failed at: ObReferenceObjectByName\n")); return Status; } for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { RealTDIDriverObject.MajorFunction = DriverObjectToHookPtr->MajorFunction; DriverObjectToHookPtr->MajorFunction = TDIDeviceDispatch; } return STATUS_SUCCESS; } |
|
6楼#
发布于:2007-08-10 14:51
目前我所能完成的代码,麻烦斑竹帮我看一下吧,谢谢
//定义了一个上下文信息结构,为了保存需要的信息 typedef struct{ PFILE_OBJECT fileobj; //address object PVOID old_handler; //old event handler PVOID old_context; //old event handler context }TDI_EVENT_CONTEXT; DRIVER_OBJECT RealTDIDriverObject; //TDI入口函数 NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) { NTSTATUS ntStatus=STATUS_SUCCESS; UNICODE_STRING myDriverName; PDRIVER_OBJECT DriverObjectToHookPtr; UINT i; RtlInitUnicodeString(&myDriverName,L"\\Driver\\Tcpip"); Status = ObReferenceObjectByName( &myDriverName, OBJ_CASE_INSENSITIVE, NULL, 0, IoDriverObjectType, KernelMode, NULL, &DriverObjectToHookPtr ); if(Status != STATUS_SUCCESS) { KdPrint(("failed on: ObReferenceObjectByName\n")); return Status; } for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { RealTDIDriverObject.MajorFunction = DriverObjectToHookPtr->MajorFunction; DriverObjectToHookPtr->MajorFunction = TDIDeviceDispatch; } return STATUS_SUCCESS; } //TDI派遣函数 NTSTATUS TDIDeviceDispatch(IN PDEVICE_OBJECT DriverObject, IN PIRP irp) { PIO_STACK_LOCATION irps= IoGetCurrentIrpStackLocation(irp); if(irps->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL && irps->MinorFunction == TDI_SET_EVENT_HANDLER) { TDI_REQUEST_KERNEL_SET_EVENT r = (TDI_REQUEST_KERNEL_SET_EVENT)&irps->Parameters; if(r->EventType == TDI_EVENT_CONNECT && r->EventHandler != NULL) { TDI_EVENT_CONTEXT cxt; cxt->fileobj = irps->FileObject; //这么写对么??? cxt->old_handler = r->EventHandler; ctx->old_context = r->EventContext; r->EventHandler = my_handler; //my_handler大致应该怎么写??? r->EventContext = ctx->old_context; //自己的调用函数处理完毕后,调用原来的回调函数 status = ((PTDI_IND_CONNECT)(ctx->old_handler)) (ctx->old_context, RemoteAddressLength, RemoteAddress, UserDataLength, UserData, OptionsLength, Options, ConnectionContext, AcceptIrp); //......要控制自己的回调函数返回值还是原回调函数返回值???? } } } |
|
7楼#
发布于:2007-08-10 14:12
请问版主:
在得知TDI_EVENT_CONNECT请求之后,如何写自己的回调函数?逻辑是要先获得对方的IP,然后与我写的一个值对比,比如192.168.0.1,如果相同返回STATUS_MORE_PROCESSING_REQUIRED ,如果不是这台机器返回STATUS_CONNECTION_REFUSED,之后调用原有的回调函数。 自己的回调函数是应该定义成这种格式么?直接提取RemoteAddress???怎么比对呢???谢谢~ NTSTATUS mytdi_event_connect( IN PVOID TdiEventContext, IN LONG RemoteAddressLength, IN PVOID RemoteAddress, IN LONG UserDataLength, IN PVOID UserData, IN LONG OptionsLength, IN PVOID Options, OUT CONNECTION_CONTEXT OUT PIRP *AcceptIrp) |
|
8楼#
发布于:2007-08-10 10:15
ok
我知道了,RegistryPath是驱动在注册表里的路径是吧? 入口函数是由系统调用的,不用管它的参数。分派函数也是这样对吧?? to ProPlayboy 麻烦您指导我一下关于RemoteAddressLength, RemoteAddress这方面的东西可以吗? |
|
9楼#
发布于:2007-08-10 10:05
您说我要都会了,我还这么着急干吗???
DriverEntry()是入口函数我知道,就想问您一下后面那个参数的意义? 如果对您小菜一碟的话,希望您能指点我。 我初学tdi,有很多很幼稚的问题,希望您能帮我,谢谢 |
|
10楼#
发布于:2007-08-09 23:43
连最基本的DriverEntry()都不懂,你怎么写啊?
![]() |
|
|
11楼#
发布于:2007-08-09 23:39
![]() |
|
|
12楼#
发布于:2007-08-09 17:59
引用第24楼ProPlayboy于2007-08-09 14:16发表的 : to ProPlayboy 您能把这里将得再细一些吗?如果您有时间的话,您能写几行代码吗?我理解起来太抽象了,当然我会去查ddk的~~~有劳您啦!! |
|
13楼#
发布于:2007-08-09 15:50
二位前辈,我大致的写了一些代码,您们帮我看看我理解的对不对,或者是不是靠近了,至少没走偏~~~
DRIVER_OBJECT RealTDIDriverObject; //TDI入口函数 NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) //以上的两个形参是从什么地方传递进来的?代表什么意思呢-尤其是后面那个?直接这么写就可以了? { NTSTATUS ntStatus=STATUS_SUCCESS; UNICODE_STRING myDriverName; PDRIVER_OBJECT DriverObjectToHookPtr; UINT i; RtlInitUnicodeString(&myDriverName,L"\\Driver\\Tcpip"); Status = ObReferenceObjectByName( &myDriverName, OBJ_CASE_INSENSITIVE, NULL, 0, IoDriverObjectType, KernelMode, NULL, &DriverObjectToHookPtr ); if(Status != STATUS_SUCCESS) return Status; for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { RealTDIDriverObject.MajorFunction = DriverObjectToHookPtr->MajorFunction; DriverObjectToHookPtr->MajorFunction = hook_disp(DriverObjectToHookPtr,...); //以上实参是应该填DriverObjectToHookPtr吧?第二个参数irp怎么得到? } return STATUS_SUCCESS; } //TDI派遣函数 NTSTATUS hook_disp(IN PDEVICE_OBJECT DriverObject, IN PIRP irp) { PIO_STACK_LOCATION irps= IoGetCurrentIrpStackLocation(irp); //case.... case IRP_MJ_INTERNAL_DEVICE_CONTROL: switch(irps->MinorFunction) { //case.... case TDI_SET_EVENT_HANDLER: switch(((TDI_REQUEST_KERNEL_SET_EVENT*)&(irps->Parameters))->EventType) { case TDI_EVENT_CONNECT: //自己的判断逻辑代码 //case.... } break; //case.... } //case.... } |
|
14楼#
发布于:2007-08-09 14:34
![]() |
|
|
15楼#
发布于:2007-08-09 14:31
cool~~~~
谢谢二位前辈~~~~再去学习一下~~~~ |
|
16楼#
发布于:2007-08-09 14:18
![]() |
|
|
17楼#
发布于:2007-08-09 14:16
RemoteAddressLength, RemoteAddress, 在EventConnect中,通过这二个参数获取Remote的IP,Port
![]() |
|
|
18楼#
发布于:2007-08-09 14:14
EventType,EventHandler,EventContext指的是你回调的函数类型,函数地址,及参数。
TDI_REQUEST_KERNEL_SET_EVENT是给你安装Event回调使用的,具体查DDK。 gettcpportbyfile一看就知道不是TDI提供的了. |
|
|
19楼#
发布于:2007-08-09 12:23
1.这个是安装TDI_EVENT_CONNECT函数,tcp协议会在收到第一个syn包的时候,调用这个回调.你在这里替换这个函数,你就可以实现hook tdi_event_connect的目的了
2.监听外部访问请求,处理TDI_EVENT_CONNECT,就够了 |
|
上一页
下一页