• TDIfw在windows 10 1903的测试


    最近看了一下TDI的网络过滤驱动,在Vista之后就不支持了,但是据说windows7还是能用,于是想试试在win10上还能不能玩。需要注意的是在win10上的TCP和UDP设备对象的驱动对象变成了tdx,于是有了下面的代码。

    #include <Ntifs.h>
    #include <ntimage.h>
    #include <ntstrsafe.h>
    #include <Tdikrnl.h>
    #define MEM_TAG		'YCAI'
    #define malloc_np(size)	ExAllocatePoolWithTag(NonPagedPool, (size), MEM_TAG)
    #define free(ptr)		ExFreePool(ptr)
    #define TDI_ADDRESS_MAX_LENGTH	TDI_ADDRESS_LENGTH_OSI_TSAP
    #define TA_ADDRESS_MAX			(sizeof(TA_ADDRESS) - 1 + TDI_ADDRESS_MAX_LENGTH)
    #define TDI_ADDRESS_INFO_MAX	(sizeof(TDI_ADDRESS_INFO) - 1 + TDI_ADDRESS_MAX_LENGTH)
    /* filter result */
    enum {
    	FILTER_ALLOW = 1,
    	FILTER_DENY,
    	FILTER_PACKET_LOG,
    	FILTER_PACKET_BAD,
    	FILTER_DISCONNECT
    };
    typedef struct {
    	PIO_COMPLETION_ROUTINE	old_cr;			/* old (original) completion routine */
    	PVOID					old_context;	/* old (original) parameter for old_cr */
    	PIO_COMPLETION_ROUTINE	new_cr;			/* new (replaced) completion routine */
    	PVOID					new_context;	/* new (replaced) parameter for new_cr */
    	PFILE_OBJECT			fileobj;		/* FileObject from IO_STACK_LOCATION */
    	PDEVICE_OBJECT			new_devobj;		/* filter device object */
    	UCHAR					old_control;	/* old (original) irps->Control */
    } TDI_SKIP_CTX;
    struct completion {
    	PIO_COMPLETION_ROUTINE	routine;
    	PVOID					context;
    };
    typedef struct {
    	TDI_ADDRESS_INFO	*tai;		/* address info -- result of TDI_QUERY_ADDRESS_INFO */
    	PFILE_OBJECT		fileobj;	/* FileObject from IO_STACK_LOCATION */
    } TDI_CREATE_ADDROBJ2_CTX;
    struct tdi_obj {
    	PFILE_OBJECT fileobj, associate_obj;
    	UCHAR   local_addr[TA_ADDRESS_MAX];
    };
    
    NTKERNELAPI NTSTATUS ObReferenceObjectByName(IN PUNICODE_STRING ObjectName, IN ULONG Attributes, IN PACCESS_STATE	PassedAccessState OPTIONAL, IN ACCESS_MASK DesiredAccess OPTIONAL, IN POBJECT_TYPE ObjectType OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, OUT	PVOID *Object);
    extern PVOID *IoDriverObjectType;
    PDEVICE_OBJECT g_tcpfltobj = NULL;
    PDEVICE_OBJECT g_udpfltobj = NULL;
    PDEVICE_OBJECT g_tcpfltobj6 = NULL;
    PDEVICE_OBJECT g_udpfltobj6 = NULL;
    DRIVER_OBJECT g_old_DriverObject;
    PDRIVER_OBJECT new_DriverObject;
    unsigned long ntohl(unsigned long netlong)
    {
    	unsigned long result = 0;
    	((char *)&result)[0] = ((char *)&netlong)[3];
    	((char *)&result)[1] = ((char *)&netlong)[2];
    	((char *)&result)[2] = ((char *)&netlong)[1];
    	((char *)&result)[3] = ((char *)&netlong)[0];
    	return result;
    }
    
    unsigned short ntohs(unsigned short netshort)
    {
    	unsigned short result = 0;
    	((char *)&result)[0] = ((char *)&netshort)[1];
    	((char *)&result)[1] = ((char *)&netshort)[0];
    	return result;
    }
    
    
    NTSTATUS get_device_object(wchar_t *name, PDEVICE_OBJECT *devobj) {
    	UNICODE_STRING str;
    	NTSTATUS status;
    	PFILE_OBJECT fileobj;
    
    	RtlInitUnicodeString(&str, name);
    
    	status = IoGetDeviceObjectPointer(&str, FILE_ALL_ACCESS, &fileobj, devobj);
    	if (status == STATUS_SUCCESS)
    		ObDereferenceObject(fileobj);
    
    	return status;
    }
    
    
    NTSTATUS tdi_skip_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) {
    	TDI_SKIP_CTX *ctx = (TDI_SKIP_CTX *)Context;
    	NTSTATUS status = STATUS_SUCCESS;
    	PIO_STACK_LOCATION irps;
    
    	if (Irp->IoStatus.Status != STATUS_SUCCESS)
    		DbgPrint("tdi_skip_complete: status 0x%x\n", Irp->IoStatus.Status);
    
    
    	//这里是回到之前的那一层
    	Irp->CurrentLocation--;
    	Irp->Tail.Overlay.CurrentStackLocation--;
    
    
    	irps = IoGetCurrentIrpStackLocation(Irp);
    
    	DeviceObject = irps->DeviceObject;//保存一下当前的设备对象
    
    	if (ctx->new_cr != NULL) {
    		// restore fileobject (it's NULL)
    		irps->FileObject = ctx->fileobj;
    		// set new device object in irps
    		irps->DeviceObject = ctx->new_devobj;
    
    		// call new completion 
    		status = ctx->new_cr(ctx->new_devobj, Irp, ctx->new_context);//这里是到tdi_create_addrobj_complete 去执行
    
    	}
    	else
    		status = STATUS_SUCCESS;
    
    
    	// restore routine and context (and even control!)
    	irps->CompletionRoutine = ctx->old_cr;
    	irps->Context = ctx->old_context;
    	irps->Control = ctx->old_control;
    
    	// restore device object
    	irps->DeviceObject = DeviceObject;
    
    	Irp->CurrentLocation++;
    	Irp->Tail.Overlay.CurrentStackLocation++;
    
    
    	if (ctx->old_cr != NULL) {
    		if (status != STATUS_MORE_PROCESSING_REQUIRED) {
    			BOOLEAN b_call = FALSE;
    			if (Irp->Cancel) {
    				// cancel
    				if (ctx->old_control & SL_INVOKE_ON_CANCEL)
    					b_call = TRUE;
    			}
    			else {
    				if (Irp->IoStatus.Status >= STATUS_SUCCESS) {
    					// success
    					if (ctx->old_control & SL_INVOKE_ON_SUCCESS)
    						b_call = TRUE;
    				}
    				else {
    					// error
    					if (ctx->old_control & SL_INVOKE_ON_ERROR)
    						b_call = TRUE;
    				}
    			}
    			if (b_call)
    				status = ctx->old_cr(DeviceObject, Irp, ctx->old_context);//之前老的complete如果有的话
    		}
    		else {
    			irps->Control = ctx->old_control;
    		}
    	}
    
    	free(ctx);
    
    	return status;
    }
    
    
    
    NTSTATUS tdi_dispatch_complete(PDEVICE_OBJECT devobj, PIRP irp, int filter, PIO_COMPLETION_ROUTINE cr, PVOID context) {
    	PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(irp);
    	NTSTATUS status;
    
    	if (filter == FILTER_DENY) {
    		if (irp->IoStatus.Status == STATUS_SUCCESS) {
    			// change status
    			status = irp->IoStatus.Status = STATUS_ACCESS_DENIED;
    		}
    		else {
    			// set IRP status unchanged
    			status = irp->IoStatus.Status;
    		}
    
    		IoCompleteRequest(irp, IO_NO_INCREMENT);
    	}
    	else if (filter == FILTER_ALLOW) {
    
    		if (cr != NULL) {
    			// save old completion routine and context
    			TDI_SKIP_CTX *ctx = (TDI_SKIP_CTX *)malloc_np(sizeof(*ctx));
    			if (ctx == NULL) {
    				DbgPrint("tdi_send_irp_to_old_driver: malloc_np\n");
    
    				status = irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
    				IoCompleteRequest(irp, IO_NO_INCREMENT);
    
    				return status;
    			}
    
    			ctx->old_cr = irps->CompletionRoutine;
    			ctx->old_context = irps->Context;
    			ctx->new_cr = cr;
    			ctx->new_context = context;
    			ctx->fileobj = irps->FileObject;
    			ctx->new_devobj = devobj;
    
    			ctx->old_control = irps->Control;
    
    			//手动模拟setcomplete
    			irps->Context = ctx;
    			irps->CompletionRoutine = (PIO_COMPLETION_ROUTINE)tdi_skip_complete;
    			irps->Control = SL_INVOKE_ON_ERROR | SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_CANCEL;
    			//IoSetCompletionRoutine(irp, tdi_skip_complete, ctx, TRUE, TRUE, TRUE);
    		}
    		/* call original driver */
    		status = g_old_DriverObject.MajorFunction[irps->MajorFunction](devobj, irp);
    	}
    	else {	/* FILTER_UNKNOWN */
    		status = irp->IoStatus.Status = STATUS_SUCCESS;	// ???
    		IoCompleteRequest(irp, IO_NO_INCREMENT);
    	}
    
    	return status;
    }
    
    
    NTSTATUS tdi_create_addrobj_complete2(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) {
    	NTSTATUS status;
    	TDI_CREATE_ADDROBJ2_CTX *ctx = (TDI_CREATE_ADDROBJ2_CTX *)Context;
    	TA_ADDRESS *addr = ctx->tai->Address.Address;
    	struct tdi_obj* obj_item = NULL;
    	unsigned long  Ip= ntohl(((TDI_ADDRESS_IP *)(addr->Address))->in_addr);//得到地址
    	unsigned long * IpAddress =&Ip;
    	//打印一下ip地址和端口
    	DbgPrint("tdi_create_addrobj_complete2: IPaddress : %d.%d.%d.%d:%u fileobj0x%llX\n",((UCHAR *)IpAddress)[3], ((UCHAR *)IpAddress)[2], ((UCHAR *)IpAddress)[1], ((UCHAR *)IpAddress)[0], ntohs(((TDI_ADDRESS_IP *)(addr->Address))->sin_port), ctx->fileobj);
    
    	status = STATUS_SUCCESS;
    	if (Irp->MdlAddress != NULL) {
    		IoFreeMdl(Irp->MdlAddress);
    		Irp->MdlAddress = NULL;
    	}
    
    	free(ctx->tai);
    	free(ctx);
    
    	return STATUS_SUCCESS;
    }
    
    NTSTATUS tdi_generic_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) {
    
    	if (Irp->PendingReturned) {
    		DbgPrint("tdi_generic_complete: PENDING\n");
    		IoMarkIrpPending(Irp);
    	}
    
    	return STATUS_SUCCESS;
    }
    
    NTSTATUS tdi_create_addrobj_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) {
    	NTSTATUS status = STATUS_SUCCESS;
    	PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(Irp);
    	PIRP query_irp = (PIRP)Context;
    	PDEVICE_OBJECT devobj;
    	TDI_CREATE_ADDROBJ2_CTX *ctx = NULL;
    	PMDL mdl = NULL;
    
    	if (Irp->IoStatus.Status != STATUS_SUCCESS) {
    		DbgPrint("tdi_create_addrobj_complete: status 0x%x\n", Irp->IoStatus.Status);
    		status = Irp->IoStatus.Status;
    		goto done;
    	}
    
    	// query addrobj address:port
    
    	ctx = (TDI_CREATE_ADDROBJ2_CTX *)malloc_np(sizeof(TDI_CREATE_ADDROBJ2_CTX));
    	if (ctx == NULL) {
    		DbgPrint("tdi_create_addrobj_complete: malloc_np\n");
    		status = STATUS_INSUFFICIENT_RESOURCES;
    		goto done;
    	}
    
    	ctx->fileobj = irps->FileObject;
    
    	ctx->tai = (TDI_ADDRESS_INFO *)malloc_np(TDI_ADDRESS_INFO_MAX);
    	if (ctx->tai == NULL) {
    		DbgPrint("tdi_create_addrobj_complete: malloc_np!\n");
    		status = STATUS_INSUFFICIENT_RESOURCES;
    		goto done;
    	}
    
    	mdl = IoAllocateMdl(ctx->tai, TDI_ADDRESS_INFO_MAX, FALSE, FALSE, NULL);
    	if (mdl == NULL) {
    		DbgPrint("tdi_create_addrobj_complete: IoAllocateMdl!\n");
    		status = STATUS_INSUFFICIENT_RESOURCES;
    		goto done;
    	}
    	MmBuildMdlForNonPagedPool(mdl);
    
    	devobj = DeviceObject;
    	if (devobj == NULL) {
    		DbgPrint("tdi_create_addrobj_complete: get_original_devobj!\n");
    
    		status = STATUS_INVALID_PARAMETER;
    		goto done;
    	}
    
    	TdiBuildQueryInformation(query_irp, devobj, irps->FileObject, tdi_create_addrobj_complete2, ctx, TDI_QUERY_ADDRESS_INFO, mdl);
    
    	status = IoCallDriver(devobj, query_irp);//这里需要继续往下传
    	query_irp = NULL;
    	mdl = NULL;
    	ctx = NULL;
    
    	if (status != STATUS_SUCCESS) {//STATUS_PENDING
    		DbgPrint("tdi_create_addrobj_complete: IoCallDriver: 0x%x   STATUS_PENDING==0x103\n", status);
    		goto done;
    	}
    
    	status = STATUS_SUCCESS;
    
    done:
    	// cleanup
    	if (mdl != NULL)
    		IoFreeMdl(mdl);
    
    	if (ctx != NULL) {
    		if (ctx->tai != NULL)
    			free(ctx->tai);
    		free(ctx);
    	}
    
    	if (query_irp != NULL)
    		IoCompleteRequest(query_irp, IO_NO_INCREMENT);
    
    	Irp->IoStatus.Status = status;
    
    	return tdi_generic_complete(DeviceObject, Irp, Context);
    }
    
    
    
    
    int tdi_create(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) {
    	FILE_FULL_EA_INFORMATION *ea = (FILE_FULL_EA_INFORMATION *)irp->AssociatedIrp.SystemBuffer;
    
    	if (ea != NULL) {
    		PDEVICE_OBJECT devobj;
    
    		devobj = irps->DeviceObject;
    		if (devobj == NULL) {
    			DbgPrint("tdi_create: unknown device object 0x%llX!\n", irps->DeviceObject);
    			return FILTER_DENY;
    		}
    
    		if (ea->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH && memcmp(ea->EaName, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH) == 0) {//传输
    			PIRP query_irp;
    			//搞一个空的irp
    			query_irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, devobj, irps->FileObject, NULL, NULL);
    			if (query_irp == NULL) {
    				DbgPrint("tdi_create: TdiBuildInternalDeviceControlIrp\n");
    				return FILTER_DENY;
    			}
    
    			completion->routine = tdi_create_addrobj_complete;//这里是设置完成的回调
    			completion->context = query_irp;
    
    		}
    		else if (ea->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH && memcmp(ea->EaName, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH) == 0) {//连接
    
    			CONNECTION_CONTEXT conn_ctx = *(CONNECTION_CONTEXT *)(ea->EaName + ea->EaNameLength + 1);//这个是链接上下文
    		}
    
    	}
    
    	return FILTER_ALLOW;
    }
    
    int tdi_connect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion){
    	PTDI_REQUEST_KERNEL_CONNECT param = (PTDI_REQUEST_KERNEL_CONNECT)(&irps->Parameters);
    	TA_ADDRESS *remote_addr = ((TRANSPORT_ADDRESS *)(param->RequestConnectionInformation->RemoteAddress))->Address;
    	unsigned long  Ip = ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr);//得到地址
    	unsigned long * IpAddress = &Ip;
    
    	// 监控TCP外连参数 ---在这里处理
    	DbgPrint("pid:%d tdi_connect: connobj 0x%llX, remote:%d.%d.%d.%d:%u\n",
    		PsGetCurrentProcessId(),
    		irps->FileObject,
    		((UCHAR *)IpAddress)[3], ((UCHAR *)IpAddress)[2], ((UCHAR *)IpAddress)[1], ((UCHAR *)IpAddress)[0],
    		ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port));
    
    
    	return FILTER_ALLOW;
    }
    int tdi_associate_address(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion){
    	HANDLE addr_handle = ((TDI_REQUEST_KERNEL_ASSOCIATE *)(&irps->Parameters))->AddressHandle;
    	PFILE_OBJECT addrobj = NULL;
    	NTSTATUS status;
    	int result = FILTER_DENY;
    
    	status = ObReferenceObjectByHandle(addr_handle, GENERIC_READ, NULL, KernelMode, &addrobj, NULL);
    	if (status != STATUS_SUCCESS) {
    		DbgPrint("[tdi_fw] tdi_associate_address: ObReferenceObjectByHandle: 0x%x\n", status);
    	}
    
    	DbgPrint("tdi_associate_address: connobj = 0x%llX ---> addrobj = 0x%llX\n",irps->FileObject, addrobj);//这里是绑定本地的transport,只打印不记录
    
    	result = FILTER_ALLOW;
    	if (addrobj != NULL)
    		ObDereferenceObject(addrobj);
    
    	return result;
    }
    
    NTSTATUS TdiHookDeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp) {
    	PIO_STACK_LOCATION irps;
    	NTSTATUS status;
    	int result;
    	struct completion completion = { 0 };
    	//假装检查一下
    	if (irp == NULL)
    		return STATUS_SUCCESS;
    
    	irps = IoGetCurrentIrpStackLocation(irp);
    
    
    	if (DeviceObject == g_tcpfltobj || DeviceObject == g_udpfltobj) {//这里过滤TCP和UDP
    		switch (irps->MajorFunction) {
    		case IRP_MJ_CREATE:
    			result = tdi_create(irp, irps, &completion);
    			status = tdi_dispatch_complete(DeviceObject, irp, result, completion.routine, completion.context);
    			//DbgPrint("IRP_MJ_CREATE \n");
    			break;
    		/*case IRP_MJ_DEVICE_CONTROL:
    			if (KeGetCurrentIrql() == PASSIVE_LEVEL) {
    				status = TdiMapUserRequest(DeviceObject, irp, irps);
    			}else
    				status = STATUS_NOT_IMPLEMENTED; // set fake status
    
    			if (status != STATUS_SUCCESS) {
    				void *buf = (irps->Parameters.DeviceIoControl.IoControlCode == IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER) ?irps->Parameters.DeviceIoControl.Type3InputBuffer : NULL;
    				//这里的buf是send的指针,目前不用
    				// send IRP to original driver
    				status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW, NULL, NULL);
    				break;
    			}*/
    		case IRP_MJ_INTERNAL_DEVICE_CONTROL:
    			/* 根据irps->MinorFunction类型进行处理 */
    			if (irps->MinorFunction == TDI_CONNECT) {
    				tdi_connect(irp, irps, &completion);
    			}
    			else if (irps->MinorFunction == TDI_ASSOCIATE_ADDRESS) {
    				tdi_associate_address(irp, irps, &completion);
    			}
    
    			status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW,completion.routine, completion.context);
    			break;
    		default:
    			DbgPrint("default \n");
    			status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW, NULL, NULL);
    			return status;
    		}
    
    
    
    
    	}
    	else
    		status = g_old_DriverObject.MajorFunction[irps->MajorFunction](DeviceObject, irp);//避免二次完成
    
    
    	return status;
    }
    
    void HookTcpIp() {
    
    	UNICODE_STRING drv_name;
    	NTSTATUS status;
    	int i;
    
    	//之后用来做过滤的
    	status = get_device_object(L"\\Device\\Tcp", &g_tcpfltobj);
    	status = get_device_object(L"\\Device\\Udp", &g_udpfltobj);
    	//status = get_device_object(L"\\Device\\Tcp6", &g_tcpfltobj6);
    	//status = get_device_object(L"\\Device\\Udp6", &g_udpfltobj6);
    	//DbgPrint("Tcp  %llX  Udp  %llX  Tcp6  %llX  Udp6  %llX \n", g_tcpfltobj, g_udpfltobj, g_tcpfltobj6, g_udpfltobj6);
    	RtlInitUnicodeString(&drv_name, L"\\Driver\\tdx");//tdx 
    
    	status = ObReferenceObjectByName(&drv_name, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, KernelMode, NULL, &new_DriverObject);
    	if (status != STATUS_SUCCESS) {
    		DbgPrint("ObReferenceObjectByName failed \n");
    		return;
    	}
    	ObDereferenceObject(new_DriverObject);//解引用
    
    	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
    		g_old_DriverObject.MajorFunction[i] = new_DriverObject->MajorFunction[i];
    		new_DriverObject->MajorFunction[i] = TdiHookDeviceDispatch;//替换方法
    	}
    }
    
    
    
    
    
    VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
    	int i;
    	for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
    		new_DriverObject->MajorFunction[i] = g_old_DriverObject.MajorFunction[i];//还原
    	DbgPrint("See You !\n");
    }
    
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath) {
    
    	DriverObject->DriverUnload = DriverUnload;
    	HookTcpIp();
    	return STATUS_SUCCESS;
    }
    

    经过测试无法在打开ie的时候无法拦截到connect请求,但是如果关闭网卡之后在打开,可以看到IRP_MJ_CREATE和IRP_MJ_INTERNAL_DEVICE_CONTROL(TDI_ASSOCIATE_ADDRESS)的消息,由于技术有限也不知道是不是姿势不对还是说windows真的改了。

  • 相关阅读:
    HTTP的传输编码(Transfer-Encoding:chunked)
    单向链表寻找入环点算法的证明
    Java容器解析系列(17) LruCache详解
    Java容器解析系列(16) android内存优化之SparseArray
    Java容器解析系列(15) HashTable Dictionary & Properties
    Java容器解析系列(14) IdentityHashMap详解
    Swift开发之iOS11下UIToolBar非正常显示问题
    Python爬虫之Scrapy框架爬取XXXFM音频文件
    ARKit文档翻译之ARTrackable协议
    ARKit文档翻译之ARAnchor类
  • 原文地址:https://www.cnblogs.com/csnd/p/16675601.html
Copyright © 2020-2023  润新知