当前位置: 代码迷 >> 综合 >> TDIfw在windows 10 1903的测试
  详细解决方案

TDIfw在windows 10 1903的测试

热度:96   发布时间:2024-02-20 08:37:47.0

最近看了一下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 irpsirps->DeviceObject = ctx->new_devobj;// call new completion status = ctx->new_cr(ctx->new_devobj, Irp, ctx->new_context);//这里是到tdi_create_addrobj_complete 去执行}elsestatus = 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 objectirps->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) {// cancelif (ctx->old_control & SL_INVOKE_ON_CANCEL)b_call = TRUE;}else {if (Irp->IoStatus.Status >= STATUS_SUCCESS) {// successif (ctx->old_control & SL_INVOKE_ON_SUCCESS)b_call = TRUE;}else {// errorif (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 statusstatus = irp->IoStatus.Status = STATUS_ACCESS_DENIED;}else {// set IRP status unchangedstatus = irp->IoStatus.Status;}IoCompleteRequest(irp, IO_NO_INCREMENT);}else if (filter == FILTER_ALLOW) {if (cr != NULL) {// save old completion routine and contextTDI_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;//手动模拟setcompleteirps->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:portctx = (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_PENDINGDbgPrint("tdi_create_addrobj_complete: IoCallDriver: 0x%x   STATUS_PENDING==0x103\n", status);goto done;}status = STATUS_SUCCESS;done:// cleanupif (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;//搞一个空的irpquery_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和UDPswitch (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);}elsestatus = STATUS_NOT_IMPLEMENTED; // set fake statusif (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 driverstatus = 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;}}elsestatus = 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真的改了。

  相关解决方案