⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdi_fw.c

📁 开源的防火墙代码
💻 C
📖 第 1 页 / 共 2 页
字号:
						
						break;
						}
					
					// if dispatch function hasn't been found
					if (g_tdi_ioctls[i].MinorFunction == 0)
						{
						// send IRP to original driver
						status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW, NULL, NULL);
						}
					
					break;
					}
				
			case IRP_MJ_CLEANUP:		/* cleanup fileobject */
				
				result = tdi_cleanup(irp, irps, &completion);
				
				status = tdi_dispatch_complete(DeviceObject, irp, result,
							       completion.routine, completion.context);
				break;
				
			case IRP_MJ_CLOSE:
				KdPrint(("[tdi_fw] DeviceDispatch: IRP_MJ_CLOSE fileobj 0x%x\n", irps->FileObject));
				
				// passthrough IRP
				status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW,
							       completion.routine, completion.context);
				
				break;
				
			default:
				KdPrint(("[tdi_fw] DeviceDispatch: major 0x%x, minor 0x%x for 0x%x\n",
					irps->MajorFunction, irps->MinorFunction, irps->FileObject));
				
				// passthrough IRP
				status = tdi_dispatch_complete(DeviceObject, irp, FILTER_ALLOW,
							       completion.routine, completion.context);
			}
		
		}
	else if (DeviceObject == g_devcontrol)
		{
		
		/*
		* this IRP is for control device
		*/
		
		// set default status
		status = STATUS_SUCCESS;
		
		if (irps->MajorFunction == IRP_MJ_CREATE)
			{
			
			// initialize for user-mode part (exclusive access - 1 user-mode logging part)
			filter_init_2();
			
			g_got_log = TRUE;
			
			}
		else if (irps->MajorFunction == IRP_MJ_CLOSE)
			{
			
			// cleanup for user-mode logging part
			filter_free_2();
			
			g_got_log = FALSE;
			
			}
		if (irps->MajorFunction == IRP_MJ_DEVICE_CONTROL)
			{
			
			/*
			* control request
			*/
			
			ULONG ioctl = irps->Parameters.DeviceIoControl.IoControlCode,
				      len = irps->Parameters.DeviceIoControl.InputBufferLength,
				      size = irps->Parameters.DeviceIoControl.OutputBufferLength;
			char *out_buf;
			
			if (IOCTL_TRANSFER_TYPE(ioctl) == METHOD_NEITHER)
				{
				// this type of transfer unsupported
				out_buf = NULL;
				}
			else
				out_buf = (char *)irp->AssociatedIrp.SystemBuffer;
			
			// process control request
			status = process_request(ioctl, out_buf, &len, size);
			
			irp->IoStatus.Information = len;
			
			}
		
		irp->IoStatus.Status = status;
		
		IoCompleteRequest(irp, IO_NO_INCREMENT);
		
		}
	else if (DeviceObject == g_devnfo)
		{
		
		/*
		* this IRP is for information device
		*/
		
		// set default status
		status = STATUS_SUCCESS;
		
		if (irps->MajorFunction == IRP_MJ_DEVICE_CONTROL)
			{
			
			/*
			* control request
			*/
			
			ULONG ioctl = irps->Parameters.DeviceIoControl.IoControlCode,
				      len = irps->Parameters.DeviceIoControl.InputBufferLength,
				      size = irps->Parameters.DeviceIoControl.OutputBufferLength;
			char *out_buf;
			
			if (IOCTL_TRANSFER_TYPE(ioctl) == METHOD_NEITHER)
				{
				// this type of transfer unsupported
				out_buf = NULL;
				}
			else
				out_buf = (char *)irp->AssociatedIrp.SystemBuffer;
			
			// process control request
			status = process_nfo_request(ioctl, out_buf, &len, size);
			
			irp->IoStatus.Information = len;
			
			}
		
		irp->IoStatus.Status = status;
		
		IoCompleteRequest(irp, IO_NO_INCREMENT);
		
		}
	else	{
		
		KdPrint(("[tdi_fw] DeviceDispatch: ioctl for unknown DeviceObject 0x%x\n", DeviceObject));
		
#ifndef USE_TDI_HOOKING
		// ??? just complete IRP
		status = irp->IoStatus.Status = STATUS_SUCCESS;
		IoCompleteRequest(irp, IO_NO_INCREMENT);
#else
		// call original handler
		status = g_old_DriverObject.MajorFunction[irps->MajorFunction](
										 DeviceObject, irp);
#endif
		}
	
	return status;
}

/*
* Dispatch routines call this function to complete their processing.
* They _MUST_ call this function anyway.
*/
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)
		{
		
		/*
		* DENY: complete request with status "Access violation"
		*/
		
		KdPrint(("[tdi_fw] tdi_dispatch_complete: [DROP!]"
			" major 0x%x, minor 0x%x for devobj 0x%x; fileobj 0x%x\n",
			irps->MajorFunction,
			irps->MinorFunction,
			devobj,
			irps->FileObject));
		
		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)
		{
		
		/*
		* ALLOW: pass IRP to the next driver
		*/
		
#ifndef USE_TDI_HOOKING
		
		PDEVICE_OBJECT old_devobj = get_original_devobj(devobj, NULL);
		
		if (old_devobj == NULL)
			{
			KdPrint(("[tdi_fw] tdi_send_irp_to_old_driver: Unknown DeviceObject 0x%x!\n", devobj));
			
			status = irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
			IoCompleteRequest (irp, IO_NO_INCREMENT);
			
			return status;
			}
		
#endif
		
		KdPrint(("[tdi_fw] tdi_dispatch_complete: [ALLOW.]"
			" major 0x%x, minor 0x%x for devobj 0x%x; fileobj 0x%x\n",
			irps->MajorFunction,
			irps->MinorFunction,
			devobj,
			irps->FileObject));
		
#ifndef USE_TDI_HOOKING
		
		if (cr == NULL || irp->CurrentLocation <= 1)
			{
			/*
			* we use _THIS_ way of sending IRP to old driver
			* a) to avoid NO_MORE_STACK_LOCATIONS
			* b) and if we haven't our completions - no need to copy stack locations!
			*/
			
			// stay on this location after IoCallDriver
			IoSkipCurrentIrpStackLocation(irp);
			
#endif
			
			if (cr != NULL)
				{
				/*
				* set completion routine (this way is slow)
				*/
				
				// save old completion routine and context
				TDI_SKIP_CTX *ctx = (TDI_SKIP_CTX *)malloc_np(sizeof(*ctx));
				if (ctx == NULL)
					{
					KdPrint(("[tdi_fw] 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;
				
				IoSetCompletionRoutine(irp, tdi_skip_complete, ctx, TRUE, TRUE, TRUE);
				}
			
#ifndef USE_TDI_HOOKING
			}
		else	{
			PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(irp),
						  next_irps = IoGetNextIrpStackLocation(irp);
			
			//memcpy(next_irps, irps, sizeof(*irps));
			IoCopyCurrentIrpStackLocationToNext(irp);
			
			if (cr != NULL)
				{
				/*
				* this way for completion is more quicker than used above
				*/
				
				IoSetCompletionRoutine(irp, cr, context, TRUE, TRUE, TRUE);
				}
			else
				IoSetCompletionRoutine(irp, tdi_generic_complete, NULL, TRUE, TRUE, TRUE);
			}
#endif
		
		/* call original driver */
		
#ifndef USE_TDI_HOOKING
		status = IoCallDriver(old_devobj, irp);
#else
		status = g_old_DriverObject.MajorFunction[irps->MajorFunction](devobj, irp);
#endif
		
		}
	else	{	/* FILTER_UNKNOWN */
		
		/*
		* UNKNOWN: just complete the request
		*/
		
		status = irp->IoStatus.Status = STATUS_SUCCESS;	// ???
		IoCompleteRequest (irp, IO_NO_INCREMENT);
		}
	
	return status;
}

/*
* completion routine for case if we use IoSkipCurrentIrpStackLocation way
* or we USE_TDI_HOOKING
*/
NTSTATUS	tdi_skip_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
	TDI_SKIP_CTX *ctx = (TDI_SKIP_CTX *)Context;
	NTSTATUS status;
	PIO_STACK_LOCATION irps;
	
	if (Irp->IoStatus.Status != STATUS_SUCCESS)
		KdPrint(("[tdi_fw] tdi_skip_complete: status 0x%x\n", Irp->IoStatus.Status));
	
	// restore IRP for using in our completion
	
	Irp->CurrentLocation--;
	Irp->Tail.Overlay.CurrentStackLocation--;
	
	irps = IoGetCurrentIrpStackLocation(Irp);
	
	KdPrint(("[tdi_fw] tdi_skip_complete: DeviceObject = 0x%x; FileObject = 0x%x\n",
		DeviceObject, irps->FileObject));
	
	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);
		
		}
	else
		status = STATUS_SUCCESS;
	
	/* patch IRP back */
	
	// 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)
			{
			// call old completion (see the old control)
			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);
			
			}
		else	{
			
			/*
			* patch IRP to set IoManager to call completion next time
			*/
			
			// restore Control
			irps->Control = ctx->old_control;
			
			}
		}
	
	free(ctx);
	
	return status;
}


/* get original device object by filtered */
PDEVICE_OBJECT	get_original_devobj(PDEVICE_OBJECT flt_devobj, int *proto)
{
#ifndef USE_TDI_HOOKING
	PDEVICE_OBJECT result;
	int ipproto;
	
	if (flt_devobj == g_tcpfltobj)
		{
		result = g_tcpoldobj;
		ipproto = IPPROTO_TCP;
		}
	else if (flt_devobj == g_udpfltobj)
		{
		result = g_udpoldobj;
		ipproto = IPPROTO_UDP;
		}
	else if (flt_devobj == g_ipfltobj)
		{
		result = g_ipoldobj;
		ipproto = IPPROTO_IP;
		}
	else	{
		KdPrint(("[tdi_fw] get_original_devobj: Unknown DeviceObject 0x%x!\n",
			flt_devobj));
		ipproto = IPPROTO_IP;		// what else?
		result = NULL;
		}
	
	if (result != NULL && proto != NULL)
		*proto = ipproto;
	
	return result;
	
#else	/* USE_TDI_HOOKING */
	
	// just stub for original devobj; return proto by devobj
	int ipproto;
	
	if (flt_devobj == g_tcpfltobj)
		ipproto = IPPROTO_TCP;
	else if (flt_devobj == g_udpfltobj)
		ipproto = IPPROTO_UDP;
	else if (flt_devobj == g_ipfltobj)
		ipproto = IPPROTO_IP;
	else	{
		KdPrint(("[tdi_fw] get_original_devobj: Unknown DeviceObject 0x%x!\n",
			flt_devobj));
		ipproto = IPPROTO_IP;		// what else?
		flt_devobj = NULL;
		}
	
	if (proto != NULL)
		*proto = ipproto;
	
	return flt_devobj;
	
#endif
}

/*
* Completion routines must call this function at the end of their execution
*/
NTSTATUS	tdi_generic_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
	KdPrint(("[tdi_fw] tdi_generic_complete: STATUS = 0x%x\n", Irp->IoStatus.Status));
	
	if (Irp->PendingReturned)
		{
		KdPrint(("[tdi_fw] tdi_generic_complete: PENDING\n"));
		IoMarkIrpPending(Irp);
		}
	
	return STATUS_SUCCESS;
}

/*
* for IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER
*/
NTSTATUS	new_TCPSendData(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp)
{
	struct completion completion;
	int result;
	
	KdPrint(("[tdi_fw] new_TCPSendData\n"));
	
#if 1
	memset(&completion, 0, sizeof(completion));
	
	result = tdi_send(Irp, IrpSp, &completion);
	
	// complete request
	return tdi_dispatch_complete(IrpSp->DeviceObject, Irp, result,
				     completion.routine, completion.context);
#else
	return g_TCPSendData(Irp, IrpSp);
#endif
}

/*
* deny stub for dispatch table
*/
int	tdi_deny_stub(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion)
{
	KdPrint(("[tdi_fw] tdi_deny_stub!\n"));
	return FILTER_DENY;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -