寒江獨釣-Windows核心安全程式設計筆記-第4章程式碼
阿新 • • 發佈:2019-02-09
#ifndef __CTRL2CAP_H__ #define __CTRL2CAP_H__ #pragma once typedef struct _C2P_DEV_EXT { // 結構的大小 ULONG NodeSize; // 過濾裝置物件 PDEVICE_OBJECT pFilterDeviceObject; // 同時呼叫時的保護鎖 KSPIN_LOCK IoRequestsSpinLock; // 程序間同步處理 KEVENT IoInProgressEvent; // 繫結的裝置物件 PDEVICE_OBJECT TargetDeviceObject; // 繫結前底層裝置物件 PDEVICE_OBJECT LowerDeviceObject; } C2P_DEV_EXT, *PC2P_DEV_EXT; // Kbdclass驅動的名字 #define KBD_DRIVER_NAME L"\\Driver\\kbdclass" #define DELAY_ONE_MICROSECOND (-10) #define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000) #define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000) NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt , IN PDEVICE_OBJECT pFilterDeviceObject , IN PDEVICE_OBJECT pTargetDeviceObject , IN PDEVICE_OBJECT pLowerDeviceObject); // 這個函式是事實存在的,只是文件中沒有公開。宣告一下 // 就可以直接使用了。 NTSTATUS ObReferenceObjectByName( PUNICODE_STRING ObjectName , ULONG Attributes , PACCESS_STATE AccessState , ACCESS_MASK DesiredAccess , POBJECT_TYPE ObjectType , KPROCESSOR_MODE AccessMode , PVOID ParseContext , PVOID *Object); NTSTATUS c2pDispatchGeneral(IN PDEVICE_OBJECT DeviceObject , IN PIRP irp); NTSTATUS c2pPower(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp); NTSTATUS c2pDispatchRead(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp); NTSTATUS c2pReadComplete(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp , IN PVOID Context); NTSTATUS c2pPnp(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp); VOID c2pDetach(IN PDEVICE_OBJECT pDeviceObject); VOID c2pUnload(IN PDRIVER_OBJECT DriverObject); NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt , IN PDEVICE_OBJECT pFilterDeviceObject , IN PDEVICE_OBJECT pTargetDeviceObject , IN PDEVICE_OBJECT pLowerDeviceObject); // 開啟驅動物件Kbdclass,然後繫結它下面的所有的裝置: NTSTATUS c2pAttachDevices(IN PDRIVER_OBJECT DriverObject , IN PUNICODE_STRING RegistryPath); #endif // __CTRL2CAP_H__#include #include "ctrl2cap.h" // IoDriverObjectType extern POBJECT_TYPE *IoDriverObjectType; ULONG gC2pKeyCount = 0; PDRIVER_OBJECT gDriverObject = NULL; NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { ULONG i; NTSTATUS status; KdPrint(("MyAttach: enter DriverEntry!\n")); for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i) { DriverObject->MajorFunction[i] = c2pDispatchGeneral; } DriverObject->MajorFunction[IRP_MJ_READ] = c2pDispatchRead; DriverObject->MajorFunction[IRP_MJ_POWER] = c2pPower; DriverObject->MajorFunction[IRP_MJ_PNP] = c2pPnp; DriverObject->DriverUnload = c2pUnload; gDriverObject = DriverObject; status = c2pAttachDevices (DriverObject, RegistryPath); return status; } NTSTATUS c2pDispatchGeneral(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp) { KdPrint(("Other Dispath!")); IoSkipCurrentIrpStackLocation (Irp); return IoCallDriver(((PC2P_DEV_EXT)DeviceObject->DeviceExtension)->LowerDeviceObject, Irp); } NTSTATUS c2pDispatchRead(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; PC2P_DEV_EXT devExt; PIO_STACK_LOCATION currentIrpStack; KEVENT waitEvent; KeInitializeEvent (&waitEvent, NotificationEvent, FALSE); if (Irp->CurrentLocation == 1) { ULONG Returnedinformation = 0; KdPrint(("Dispatch encountered bogus current location \n")); status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; Irp->IoStatus.Information = Returnedinformation; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } gC2pKeyCount++; devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension; currentIrpStack = IoGetCurrentIrpStackLocation (Irp); IoCopyCurrentIrpStackLocationToNext (Irp); IoSetCompletionRoutine (Irp, c2pReadComplete, DeviceObject, TRUE, TRUE, TRUE); return IoCallDriver(devExt->LowerDeviceObject, Irp); } NTSTATUS c2pPower(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp) { PC2P_DEV_EXT devExt; devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension; PoStartNextPowerIrp (Irp); IoSkipCurrentIrpStackLocation (Irp); return PoCallDriver (devExt->LowerDeviceObject, Irp); } NTSTATUS c2pPnp(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp) { PC2P_DEV_EXT devExt; PIO_STACK_LOCATION irpStack; NTSTATUS status = STATUS_SUCCESS; KIRQL oldIrql; KEVENT event; devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension; irpStack = IoGetCurrentIrpStackLocation (Irp); switch (irpStack->MinorFunction) { case IRP_MN_REMOVE_DEVICE: KdPrint(("IRP_MN_REMOVE_DEVICE\n")); IoSkipCurrentIrpStackLocation (Irp); IoCallDriver(devExt->LowerDeviceObject, Irp); IoDetachDevice (devExt->LowerDeviceObject); IoDeleteDevice (DeviceObject); return STATUS_SUCCESS; default: // 對於其他型別的IRP,全部都直接下發即可。 IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(devExt->LowerDeviceObject, Irp); } return status; } NTSTATUS c2pAttachDevices( IN PDRIVER_OBJECT DriverObject , IN PUNICODE_STRING RegistryPath) { NTSTATUS status = 0; UNICODE_STRING uniNtNameString; PC2P_DEV_EXT devExt; PDEVICE_OBJECT pFilterDeviceObject = NULL; PDEVICE_OBJECT pTargetDeviceObject = NULL; PDEVICE_OBJECT pLowerDeviceObject = NULL; PDRIVER_OBJECT KbdDriverObject = NULL; KdPrint(("MyAttach!\n")); // 初始化Kdbclass驅動的名字。 RtlInitUnicodeString (&uniNtNameString, KBD_DRIVER_NAME); // 開啟驅動物件 status = ObReferenceObjectByName(&uniNtNameString , OBJ_CASE_INSENSITIVE , NULL , 0 , *IoDriverObjectType , KernelMode , NULL , &KbdDriverObject); // 如果失敗了就直接返回 if (!NT_SUCCESS(status)) { KdPrint(("MyAttach: couldn't get the MyTest Device Object\n")); return status; } else { // 這個開啟需要解引用。早點解除了免得之後忘記。 ObDereferenceObject(DriverObject); } // 裝置鏈中的第一個裝置 pTargetDeviceObject = KbdDriverObject->DeviceObject; // 遍歷這個裝置鏈 while (pTargetDeviceObject) { // 生成一個過濾裝置 status = IoCreateDevice (DriverObject , sizeof(C2P_DEV_EXT) , NULL , pTargetDeviceObject->DeviceType , pTargetDeviceObject->Characteristics , FALSE , &pFilterDeviceObject); // 如果失敗了就直接退出。 if (!NT_SUCCESS(status)) { KdPrint(("MyAttach: couldn't create the MyFilter Filter Device Object!\n")); return status; } // 繫結。pLowerDeviceObject是繫結之後得到的下一個裝置。 // 也就是所謂真實裝置。 pLowerDeviceObject = IoAttachDeviceToDeviceStack (pFilterDeviceObject, pTargetDeviceObject); // 如果繫結失敗了,放棄之前的操作,退出。 if (!pLowerDeviceObject) { KdPrint(("MyAttach: couldn't attach to MyTest Device Object!\n")); IoDeleteDevice(pFilterDeviceObject); pFilterDeviceObject = NULL; return status; } // 取到裝置擴充套件 devExt = (PC2P_DEV_EXT)(pFilterDeviceObject->DeviceExtension); c2pDevExtInit (devExt , pFilterDeviceObject , pTargetDeviceObject , pLowerDeviceObject); pFilterDeviceObject->DeviceType = pLowerDeviceObject->DeviceType; pFilterDeviceObject->Characteristics = pLowerDeviceObject->Characteristics; pFilterDeviceObject->StackSize = pLowerDeviceObject->StackSize+1; pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE); pTargetDeviceObject = pTargetDeviceObject->NextDevice; } return status; } NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt , IN PDEVICE_OBJECT pFilterDeviceObject , IN PDEVICE_OBJECT pTargetDeviceObject , IN PDEVICE_OBJECT pLowerDeviceObject) { memset (devExt, 0, sizeof(C2P_DEV_EXT)); devExt->NodeSize = sizeof(C2P_DEV_EXT); devExt->pFilterDeviceObject = pFilterDeviceObject; devExt->TargetDeviceObject = pTargetDeviceObject; devExt->LowerDeviceObject = pLowerDeviceObject; KeInitializeSpinLock (&(devExt->IoRequestsSpinLock)); KeInitializeEvent(&(devExt->IoInProgressEvent), NotificationEvent, FALSE); return STATUS_SUCCESS; } // WIN7解除安裝的時候會導致電腦藍屏重啟。新手不知道什麼原因。 VOID c2pUnload(IN PDRIVER_OBJECT DriverObject) { PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT OldDeviceObject; PC2P_DEV_EXT devExt; LARGE_INTEGER lDelay; PRKTHREAD Currentthread; lDelay = RtlConvertLongToLargeInteger (100* DELAY_ONE_MILLISECOND); Currentthread = KeGetCurrentThread (); KeSetPriorityThread (Currentthread, LOW_REALTIME_PRIORITY); UNREFERENCED_PARAMETER(DeviceObject); KdPrint(("DriverEntry unLoading...\n")); DeviceObject = DriverObject->DeviceObject; while (DeviceObject) { c2pDetach(DeviceObject); DeviceObject = DeviceObject->NextDevice; } ASSERT(NULL == DriverObject->DeviceObject); while (gC2pKeyCount) { KeDelayExecutionThread (KernelMode, FALSE, &lDelay); } KdPrint(("DriverEntry unLoad Ok!\n")); return ; } NTSTATUS c2pReadComplete(IN PDEVICE_OBJECT DeviceObject , IN PIRP Irp , IN PVOID Context) { PIO_STACK_LOCATION Irpsp; ULONG buf_len = 0; PUCHAR buf = NULL; size_t i; Irpsp = IoGetCurrentIrpStackLocation (Irp); if (NT_SUCCESS(Irp->IoStatus.Status)) { buf = Irp->AssociatedIrp.SystemBuffer; buf_len = Irp->IoStatus.Information; for (i =0; i < buf_len; ++i) { DbgPrint("ctrl2cap: %2x\r\n", buf[i]); } } gC2pKeyCount--; if (Irp->PendingReturned) { IoMarkIrpPending (Irp); } return Irp->IoStatus.Status; } VOID c2pDetach(IN PDEVICE_OBJECT pDeviceObject) { PC2P_DEV_EXT devExt; BOOLEAN NoRequestsOutstanding = FALSE; devExt = (PC2P_DEV_EXT)pDeviceObject->DeviceExtension; __try { __try { IoDetachDevice(devExt->TargetDeviceObject); devExt->TargetDeviceObject = NULL; IoDeleteDevice(pDeviceObject); devExt->pFilterDeviceObject = NULL; DbgPrint(("Detach Finished\n")); } __except (EXCEPTION_EXECUTE_HANDLER){} } __finally{} return; }!IF 0 Copyright (C) Microsoft Corporation, 1997 - 1999 Module Name: sources. !ENDIF TARGETNAME=ctrl2cap TARGETPATH=obj TARGETTYPE=DRIVER SOURCES =ctrl2cap.c!IF 0 Copyright (C) Microsoft Corporation, 1997 - 1998 Module Name: makefile. !ENDIF # # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source # file to this component. This file merely indirects to the real make file # that is shared by all the components of Windows NT # # # if building in a DDK environment # !IF defined(DDK_TARGET_OS) # # ensure that said build environment is at least Windows XP # 0x500 == Windows 2000 # 0x501 == Windows XP # 0x502 == Windows .NET # ! IF defined(_NT_TARGET_VERSION) && $(_NT_TARGET_VERSION)>=0x501 ! INCLUDE $(NTMAKEENV)\makefile.def ! ELSE ! message BUILDMSG: Warning : The sample "$(MAKEDIR)" is not valid for the current OS target. ! ENDIF !ELSE # # not a DDK environment, probably RAZZLE, so build # ! INCLUDE $(NTMAKEENV)\makefile.def !ENDIF