用Visual studio2012在Windows8上開發核心驅動監視程序建立
阿新 • • 發佈:2019-02-20
在Windows NT中,80386保護模式的“保護”比Windows 95中更堅固,這個“鍍金的籠子”更加結實,更加難以打破。在Windows 95中,至少應用程式I/O操作是不受限制的,而在Windows NT中,我們的應用程式連這點許可權都被剝奪了。在NT中幾乎不太可能進入真正的ring0層。
在Windows NT中,存在三種Device Driver:
1.“Virtual device Driver” (VDD)。通過VDD,16位應用程式,如DOS 和Win16應用程式可以訪問特定的I/O埠(注意,不是直接訪問,而是要通過VDD來實現訪問)。
2.“GDI Driver”,提供顯示和列印所需的GDI函式。
3.“Kernel Mode Driver”,實現對特定硬體的操作,比如說CreateFile, CloseHandle (對於檔案物件而言), ReadFile, WriteFile, DeviceIoControl 等操作。“Kernel Mode Driver”還是Windows NT中唯一可以對硬體中斷和DMA進行操作的Driver。SCSI 小埠驅動和 網絡卡NDIS 驅動都是Kernel Mode Driver的一種特殊形式。
Visual studio2012與Windows8帶來格外不同的新體驗
1.啟動Vs2012
2.看見滿目的驅動開發模板
3.選擇一個驅動模式,有核心模式與使用者模式兩種的驅動
4.建立一個驅動程式,KMDF DriverMVP
5.我們選擇的是核心模式的驅動程式,下面是建立成功後的介面,分別是驅動程式本身,與驅動安裝包
6.按下F5,選擇驅動編譯,
插入下列程式碼實現核心的程序建立
#include "ProcMon.h" #include "../inc/ioctls.h" // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // 全域性變數 // PDEVICE_OBJECT g_pDeviceObject; // ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // // 函式實現 // NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING ntDeviceName; UNICODE_STRING dosDeviceName; UNICODE_STRING ProcessEventString; PDEVICE_EXTENSION deviceExtension; PDEVICE_OBJECT deviceObject = NULL; KdPrint(("[ProcMon] DriverEntry: %wZ\n", RegistryPath)); // // 建立裝置物件 // RtlInitUnicodeString(&ntDeviceName, PROCMON_DEVICE_NAME_W); Status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), // DeviceExtensionSize &ntDeviceName, // DeviceName FILE_DEVICE_PROCMON, // DeviceType 0, // DeviceCharacteristics TRUE, // Exclusive &deviceObject // [OUT] ); if(!NT_SUCCESS(Status)) { KdPrint(("[ProcMon] IoCreateDevice Error Code = 0x%X\n", Status)); return Status; } // // 設定擴充套件結構 // deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; // // Set up synchronization objects, state info,, etc. // deviceObject->Flags |= DO_BUFFERED_IO; // // 建立符號連結 // RtlInitUnicodeString(&dosDeviceName, PROCMON_DOS_DEVICE_NAME_W); Status = IoCreateSymbolicLink(&dosDeviceName, &ntDeviceName); if(!NT_SUCCESS(Status)) { KdPrint(("[ProcMon] IoCreateSymbolicLink Error Code = 0x%X\n", Status)); IoDeleteDevice(deviceObject); return Status; } // // 分發IRP // DriverObject->MajorFunction[IRP_MJ_CREATE] = ProcmonDispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = ProcmonDispatchClose; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ProcmonDispatchDeviceControl; DriverObject->DriverUnload = ProcmonUnload; // // 儲存裝置物件指標 // g_pDeviceObject = deviceObject; // // 建立事件物件與應用層通訊 // RtlInitUnicodeString(&ProcessEventString, EVENT_NAME); deviceExtension->ProcessEvent = IoCreateNotificationEvent(&ProcessEventString, &deviceExtension->hProcessHandle); KeClearEvent(deviceExtension->ProcessEvent); // 非受信狀態 // // 設定回撥例程 // Status = PsSetCreateProcessNotifyRoutine(ProcessCallback, FALSE); return Status; } NTSTATUS ProcmonDispatchCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; KdPrint(("[ProcMon] IRP_MJ_CREATE\n")); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } NTSTATUS ProcmonDispatchClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; KdPrint(("[ProcMon] IRP_MJ_CLOSE\n")); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } NTSTATUS ProcmonDispatchDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION deviceExtension; ULONG inBufLength, outBufLength; ULONG ioControlCode; PCALLBACK_INFO pCallbackInfo; // 獲取當前裝置棧 irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; // 提取資訊 pCallbackInfo = Irp->AssociatedIrp.SystemBuffer; inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; // 處理不同的IOCTL switch (ioControlCode) { case IOCTL_PROC_MON: { KdPrint(("[ProcMon] IOCTL: 0x%X", ioControlCode)); if (outBufLength >= sizeof(PCALLBACK_INFO)) { pCallbackInfo->hParentId = deviceExtension->hParentId; pCallbackInfo->hProcessId = deviceExtension->hProcessId; pCallbackInfo->bCreate = deviceExtension->bCreate; Irp->IoStatus.Information = outBufLength; } break; } default: { Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; KdPrint(("[ProcMon] Unknown IOCTL: 0x%X (%04X,%04X)", \ ioControlCode, DEVICE_TYPE_FROM_CTL_CODE(ioControlCode), \ IoGetFunctionCodeFromCtlCode(ioControlCode))); break; } } Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } VOID ProcmonUnload( IN PDRIVER_OBJECT DriverObject ) { UNICODE_STRING dosDeviceName; // // Free any resources // // 解除安裝回撥例程 PsSetCreateProcessNotifyRoutine(ProcessCallback, TRUE); // // Delete the symbolic link // RtlInitUnicodeString(&dosDeviceName, PROCMON_DOS_DEVICE_NAME_W); IoDeleteSymbolicLink(&dosDeviceName); // // Delete the device object // IoDeleteDevice(DriverObject->DeviceObject); KdPrint(("[ProcMon] Unloaded")); } VOID ProcessCallback( IN HANDLE ParentId, // 父程序ID IN HANDLE ProcessId, // 發生事件的程序ID IN BOOLEAN Create // 程序是建立還是終止 ) { PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)g_pDeviceObject->DeviceExtension; deviceExtension->hParentId = ParentId; deviceExtension->hProcessId = ProcessId; deviceExtension->bCreate = Create; // 觸發事件,通知應用程式 KeSetEvent(deviceExtension->ProcessEvent, 0, FALSE); KeClearEvent(deviceExtension->ProcessEvent); } // //////////////////////////////////////////////////////////////////////////
ring3實現應用層的呼叫,搞定程序建立的監視
#include "windows.h"
#include "winioctl.h"
#include "stdio.h"
#include "../inc/ioctls.h"
#define SYMBOL_LINK "\\\\.\\ProcMon"
//#define SYMBOL_LINK "\\\\.\\slNTProcDrv"
int main()
{
CALLBACK_INFO cbkinfo, cbktemp = {0};
// 開啟驅動裝置物件
HANDLE hDriver = ::CreateFile(
SYMBOL_LINK,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDriver == INVALID_HANDLE_VALUE)
{
printf("開啟驅動裝置物件失敗!\n");
return -1;
}
// 開啟核心事件物件
HANDLE hProcessEvent = ::OpenEventW(SYNCHRONIZE, FALSE, EVENT_NAME);
while (::WaitForSingleObject(hProcessEvent, INFINITE))
{
DWORD dwRet;
BOOL bRet;
bRet = ::DeviceIoControl(
hDriver,
IOCTL_PROC_MON,
NULL,
0,
&cbkinfo,
sizeof(cbkinfo),
&dwRet,
NULL);
if (bRet)
{
if (cbkinfo.hParentId != cbktemp.hParentId || \
cbkinfo.hProcessId != cbktemp.hProcessId || \
cbkinfo.bCreate != cbktemp.bCreate)
{
if (cbkinfo.bCreate)
{
printf("有程序被建立,PID = %d\n", cbkinfo.hProcessId);
}
else
{
printf("有程序被終止,PID = %d\n", cbkinfo.hProcessId);
}
cbktemp = cbkinfo;
}
}
else
{
printf("\n獲取程序資訊失敗!\n");
break;
}
}
::CloseHandle(hDriver);
return 0;
}