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真的改了。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值