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

📄 iphook.cpp

📁 WMD驱动编程,本人收集整理的10多个例子和编程环境配置文档,特别是8139驱动,加了许多说明,并测试通过.
💻 CPP
字号:
///////////////////////////////////////////////////////////////////////////////
//
//	(C) Copyright 1999 - 2000 Mark Roddy
//	All Rights Reserved
//
//	Hollis Technology Solutions
//	94 Dow Road
//	Hollis, NH 03049
//	info@hollistech.com
//
//	Synopsis: 
// 
//
//	Version Information:
//
//	$Header: /iphook/sys/driver/iphook.cpp 4     1/27/00 10:35p Markr $ 
//
///////////////////////////////////////////////////////////////////////////////
#include "iphookKrnl.h"

HTS_DEBUG_THIS_FILE


//
// local functions
//
NTSTATUS
	IpfStartHooking(PVOID context);

NTSTATUS 
	IpfStopHooking(PVOID context);

IP_HOOK_GLOBAL_DATA ipGlobal;


CPP_DRIVER_ENTRY(PDRIVER_OBJECT DriverObject,
                 PUNICODE_STRING RegistryPath)
{
	NTSTATUS Status = STATUS_SUCCESS;

	//
	// setup our standard entry points
	//
	DriverObject->MajorFunction[IRP_MJ_CREATE]         = IpHookCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = IpHookClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IpHookDeviceControl;
	DriverObject->DriverUnload = IpHookUnload;
	//
	// before we get too deeply involved in this mess, lets see if the
	// ipfilter driver is actually installed.
	//
	Status = ipGlobal.initDevice();

	if (!NT_SUCCESS(Status)) {

		HtsDebugPrint(HTS_DEBUG_HIGH, "initDevice failed error %x\n", Status);
		return Status;
	}

	Status = ipGlobal.createThread();

	if (!NT_SUCCESS(Status)) {

		HtsDebugPrint(HTS_DEBUG_HIGH, "createThread failed error %x\n", Status);
		return Status;

	}  
	//
	// create a device object that applications can open to control the ip hook driver.
	//
	UNICODE_STRING deviceName;

	RtlInitUnicodeString(&deviceName, IPHOOK_DEV_NAME);

	PDEVICE_OBJECT ourDevice = NULL;

	Status = IoCreateDevice(
				DriverObject,
				0,
				&deviceName,
				IPHOOK_DEVICE_TYPE,
				0,
				FALSE, // well perhaps this should be true.
				&ourDevice);  

	if (!NT_SUCCESS(Status)) {

		//
		// oh well, what can we do?
		//
		HtsDebugPrint(HTS_DEBUG_HIGH, "IoCreateDevice failed status %x\n", Status);

		return Status;
	}

	UNICODE_STRING SymbolicLinkName;

	RtlInitUnicodeString(&SymbolicLinkName, IPHOOK_USER_DEV_NAME);

	//
	// create a symbolic link that exposes our device object to user space.
	//
	Status = IoCreateSymbolicLink(
				&SymbolicLinkName,
				&deviceName);

	if (!NT_SUCCESS(Status)) {
		//
		// we have to delete the device object here
		//
		IoDeleteDevice(ourDevice);

		HtsDebugPrint(HTS_DEBUG_HIGH, "IoCreateSymbolicLink failed status %x\n", Status);
	}

	return Status;
}

void
	IpHookUnload(PDRIVER_OBJECT DriverObject)
{
	HtsDebugPrint(HTS_DEBUG_LOW, "IpHookUnload\n");

	//
	HtsAssert(!ipGlobal.owned()); 
	//
	// delete our symbolic link
	//
	UNICODE_STRING SymbolicLinkName;

	RtlInitUnicodeString(&SymbolicLinkName, IPHOOK_USER_DEV_NAME);


	(void) IoDeleteSymbolicLink( &SymbolicLinkName );

	//
	// delete our device object(s)
	//
	while (DriverObject->DeviceObject) {
		
		IoDeleteDevice(DriverObject->DeviceObject);
	}

}

//
// Create
//
//	If we are going to support a read data interface then
//	we need to do something here to track operations.
//
//
NTSTATUS 
	IpHookCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
	HtsDebugPrint(HTS_DEBUG_LOW, "IpHookCreate\n");

	return STATUS_SUCCESS;
}

//
// Close
//
//	If we are going to support a read data interface then
//	we need to do something here to track operations.
//
//	On last close terminate hooking if active.
//
NTSTATUS 
	IpHookClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{

	PVOID context = IoGetCurrentIrpStackLocation(Irp)->FileObject;

	HtsDebugPrint(HTS_DEBUG_LOW, "IpHookClose context %x\n", context);

	//
	// ok lets see if the caller owned the interface and do an implicit release if he did.
	//
	if (ipGlobal.IsOwner(context)) {
		//
		// bingo!
		//
		(void) IpfStopHooking(context);
	}


	return STATUS_SUCCESS;
}

//
// DeviceControl
//
//	Provide an interface to start Ip Hooking, stop Ip Hooking.
//
NTSTATUS 
	IpHookDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
	HtsDebugPrint(HTS_DEBUG_LOW, "IpHookDeviceControl\n");
	//
	// get our stack location so we can decode this fellow
	//
	PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);

	//
	// get the control code.
	//
	ULONG controlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;

	NTSTATUS Status = STATUS_SUCCESS;

	switch (controlCode) {

	case START_IP_HOOK:

		Status = IpfStartHooking(IoStack->FileObject);

		break;


	case STOP_IP_HOOK:

		Status = IpfStopHooking(IoStack->FileObject);

		break;

	case HOOK_THIS:

		//
		// see if we are hooking,
		// a stronger test would be to see
		// if this caller owns the interface
		// as in 
		//		ipGlobal.IsOwner(IoStack->FileObject);
		//
		if ( !ipGlobal.owned() ) {
			//
			// bag it
			//
			Status = STATUS_UNSUCCESSFUL;
			break;
		}

		{
			//
			// make sure the buffer makes sense, we will not
			// revalidate later.
			//
			PIPHOOK_BUFFER buffer = (PIPHOOK_BUFFER) MmGetSystemAddressForMdl(Irp->MdlAddress);

			if (!validIpHookBuffer(buffer)) {

				HtsDebugPrint(HTS_DEBUG_LOW, "Invalid Buffer Tag\n");

				return HtsIrpReturn(Irp, STATUS_DATA_ERROR);

			}

			ULONG size = sizeof(IPHOOK_BUFFER) + 
				((buffer->entries - 1) * sizeof(IPHOOK_DATA));

			if (size > IoStack->Parameters.DeviceIoControl.OutputBufferLength) {

				HtsDebugPrint(HTS_DEBUG_LOW, "Invalid buffer length\n");

				return HtsIrpReturn(Irp, STATUS_INFO_LENGTH_MISMATCH);

			}
		}

		IoMarkIrpPending(Irp);

		ipGlobal.queueRequest(Irp);

		return STATUS_PENDING;
		
	default:

		HtsDebugPrint(HTS_DEBUG_HIGH, "Unexpected control code %x\n", controlCode);
		//
		// we don't understand this so get rid of it.
		//		
		Status = STATUS_INVALID_DEVICE_REQUEST;
		break;
	}

	return HtsIrpReturn(Irp, Status);

}


//
// the hooker herself!
//
PF_FORWARD_ACTION 
	IpHookFilter(IN unsigned char *PacketHeader,
				 IN unsigned char *Packet, 
				 IN unsigned int PacketLength, 
				 IN unsigned int RecvInterfaceIndex, 
				 IN unsigned int SendInterfaceIndex, 
				 IN IPAddr RecvLinkNextHop, 
				 IN IPAddr SendLinkNextHop)
{
	PF_FORWARD_ACTION action = PF_PASS;

	__try {
		//
		// is this interface single threaded or multi threaded?
		//
		ULONG sequence = ipGlobal.getSequence();

		HtsDebugPrint(HTS_DEBUG_LOW, "IpHookFilter PacketHeader %x Packet %x PacketLength %x\n",
					  PacketHeader, Packet, PacketLength);

		UCHAR header0 = *PacketHeader; //see what this is		
		//
		// if iph_verlen & 0xf0 != 0x40 we have 
		// something other than an IPV4 packet.
		//
		// if iph_verlen & 0xf0 != 0x60 then not
		// only is this not an IPV4 packet, but it 
		// isn't an IPV6 packet either.
		//

		if ((header0 & 0xf0) == 0x40) {

			PIPHOOK_DATA iphookdata = ipGlobal.getBuffer();
			//
			// ok its IPv4 or reasonably close!
			//
			if (iphookdata) {

				ULARGE_INTEGER ticks;
				
				KeQueryTickCount((PLARGE_INTEGER)&ticks);

				iphookdata->tag = IPHOOK_DATA_TAG;
  
				iphookdata->sequence = sequence; // ? see above ?
				iphookdata->header = *(IPHeader *) PacketHeader;
				iphookdata->timestamp = ticks.QuadPart;
				iphookdata->dataLength = PacketLength;
				if (RecvInterfaceIndex != INVALID_PF_IF_INDEX ) {

					iphookdata->direction = 0;
					iphookdata->nextHop = RecvLinkNextHop;
					iphookdata->ifIndex = RecvInterfaceIndex;

				} else {

					iphookdata->direction = 1;
					iphookdata->nextHop = SendLinkNextHop;
					iphookdata->ifIndex = SendInterfaceIndex;

				}

			} else {

				HtsDebugPrint(HTS_DEBUG_LOW, "IpHookFilter: no buffer\n");
			}
		}
	}

	__except(HTS_EXCEPTION_FILTER ) {

		//
		// cross your fingers and keep going
		//
		HtsDebugPrint(HTS_DEBUG_HIGH, "IpHookFilter continuing from exception");

	}

	return action;
}


NTSTATUS
	IpfStartHooking(PVOID context)
{
	HtsDebugPrint(HTS_DEBUG_LOW, "IpfStartHooking context %x owner %x\n",
				  PsGetCurrentThread(),
				  ipGlobal.owner());

	if (FALSE == ipGlobal.setOwner(context)) {
		//
		// some other thread owns the interface,
		// bail out
		//
		HtsDebugPrint(HTS_DEBUG_LOW, "In Use\n");

		return STATUS_CONNECTION_IN_USE; 

	} 
	//
	// we own the interface! now try to start it up
	//
	PF_SET_EXTENSION_HOOK_INFO extensionHook = { IpHookFilter, };

	KEVENT event;

	KeInitializeEvent(&event, NotificationEvent, FALSE);

	IO_STATUS_BLOCK IoStatus;

	PIRP Irp = 
		IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,
									  ipGlobal.getIpDevice(),
									  (PVOID) &extensionHook,
									  sizeof(PF_SET_EXTENSION_HOOK_INFO),
									  NULL,
									  0,
									  FALSE,
									  &event,
									  &IoStatus);

	if (!Irp) {
		//
		// we need to free up the interface!
		//
		HtsDebugPrint(HTS_DEBUG_HIGH, "IoBuildDeviceIoControlRequest no IRP!\n");

		ipGlobal.freeOwner(context);

		return STATUS_INSUFFICIENT_RESOURCES;

	}

	//
	// ok now send our IRP to the filter driver
	//
	NTSTATUS Status = IoCallDriver(ipGlobal.getIpDevice(), Irp);

	if (Status == STATUS_PENDING) {

		NTSTATUS WaitStatus = KeWaitForSingleObject(&event, UserRequest, KernelMode, FALSE, NULL);

		if (WaitStatus 	!= STATUS_SUCCESS ) {
			//
			// bummer!
			//
			HtsDebugPrint(HTS_DEBUG_HIGH, "KeWaitForSingleObject failed status %x\n", WaitStatus);
			//
			// we need to free up the interface!
			//		
			ipGlobal.freeOwner(context);

			return WaitStatus;
		}
	}

	Status = IoStatus.Status;

	if (!NT_SUCCESS(Status)) {
		//
		// we need to free up the interface!
		//		
		ipGlobal.freeOwner(context);
	}

	HtsDebugPrint(HTS_DEBUG_LOW, "IpfStartHooking returns %x\n", Status);
	
	return Status;

}


//
// NB failure modes here other than the caller isn't the owning thread are
// truly bogus. Only a cursory attempt is made to deal with them. Basically the 
// strategy is to propogate the failure back to the caller but leave the 
// filter interface in place.
//
NTSTATUS
	IpfStopHooking(PVOID context)
{
	HtsDebugPrint(HTS_DEBUG_LOW, "IpfStopHooking context %x owner %x\n",
				  context,
				  ipGlobal.owner());

	//
	// see if this is even legitimate
	//
	if (ipGlobal.IsOwner(context) == FALSE) {

		return STATUS_INVALID_OWNER;
	}
	//
	// ok so it is us, and we is the thread, so we can only be here ONCE
	// so we are already serialized, so everything is groovey. Except other
	// threads could open the hook device after we release ownership,
	// and new reads could arrive (but not on this thread.)
	//
	//
	// we own the interface! now try to start it up
	//
	PF_SET_EXTENSION_HOOK_INFO extensionHook = { (PacketFilterExtensionPtr) NULL, };

	KEVENT event;

	KeInitializeEvent(&event, NotificationEvent, FALSE);

	IO_STATUS_BLOCK IoStatus;

	PIRP Irp = 
		IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,
									  ipGlobal.getIpDevice(),
									  (PVOID) &extensionHook,
									  sizeof(PF_SET_EXTENSION_HOOK_INFO),
									  NULL,
									  0,
									  FALSE,
									  &event,
									  &IoStatus);

	if (!Irp) {

		HtsDebugPrint(HTS_DEBUG_HIGH,  "IoBuildDeviceIoControlRequest No IRP\n");
		
		return STATUS_INSUFFICIENT_RESOURCES;

	}

	//
	// ok now send our IRP to the filter driver
	//
	NTSTATUS Status = IoCallDriver(ipGlobal.getIpDevice(), Irp);

	if (Status == STATUS_PENDING) {

		NTSTATUS WaitStatus = KeWaitForSingleObject(&event, UserRequest, KernelMode, FALSE, NULL);


		if (WaitStatus 	!= STATUS_SUCCESS ) {

			HtsDebugPrint(HTS_DEBUG_HIGH, "KeWaitForSingleObject failed status %x\n", WaitStatus);
			//
			// bummer!
			//
			return WaitStatus;
		}
	}

	Status = IoStatus.Status;

	if (NT_SUCCESS(Status)) {
		//
		// we need to free up the interface!
		//
		ipGlobal.freeOwner(context);
	}

	HtsDebugPrint(HTS_DEBUG_LOW, "IpfStopHooking return %x\n", Status);

	return Status;

}

//
// IP_HOOK_GLOBAL_DATA and associates, LLC
//

VOID
GlobalCancel(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
	KIRQL irql = Irp->CancelIrql;

	IoReleaseCancelSpinLock(irql);

	PVOID context;

	ipGlobal.lock(context);
	//
	// this irp is in our queue
	//
	RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

	HtsIrpReturn(Irp, STATUS_CANCELLED);

	ipGlobal.unlock(context);

}
///////////////////////////////////////////////////////////////////////////////
// 
// Change History Log
//
// $Log: /iphook/sys/driver/iphook.cpp $
// 
// 4     1/27/00 10:35p Markr
// Prepare to release!
//
///////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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