關於《竹林蹊徑 深入淺出Windows驅動開發》第一個例子在Win7下藍屏
阿新 • • 發佈:2019-01-10
在嘗試執行《竹林蹊徑 深入淺出Windows驅動開發》的第一個例子-HelloDRIVER時,在XP下沒有問題,但在Win7下卻發生藍屏,藍屏發生點在於解除安裝函式DriverUnload。
先看看解除安裝驅動的程式碼
很通用的解除安裝驅動例程,按道理是不會出現問題的,從dump檔案進行進一步分析,定位到deviceObject = deviceObject->NextDevice;這一句藍屏,複製操作會導致藍屏?什麼鬼,再看下呼叫堆疊 原來還沒到賦值語句,在處於IoDeleteSymbolicLink階段就發生藍屏了,於是就斷點除錯看下IoDeleteSymbolicLink的引數linkName是否正常,一除錯發現memory can't access, 為什麼會出現記憶體不可訪問,於是追溯到DriverEntry,下面看下這個函式裡面做了什麼操作VOID DriverUnload ( __in PDRIVER_OBJECT DriverObject ) { PDEVICE_OBJECT deviceObject; UNICODE_STRING linkName; KdPrint(("Enter HelloDRIVER DriverUnload!\n")); deviceObject = DriverObject->DeviceObject; while(NULL != deviceObject) { PDEVICE_EXTENSION deviceExtesion = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; // 刪除符號連結與裝置 linkName = deviceExtesion->SymbolicLink; IoDeleteSymbolicLink(&linkName); deviceObject = deviceObject->NextDevice; IoDeleteDevice(deviceExtesion->DeviceObject); } KdPrint(("End of HelloDRIVER DriverUnload!\n")); }
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) { NTSTATUS status; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION deviceExtension; UNICODE_STRING symbolicLink; UNICODE_STRING deviceName; ULONG i; KdPrint(("Enter HelloDRIVER DriverEntry!\n")); UNREFERENCED_PARAMETER(RegistryPath); RtlInitUnicodeString(&deviceName, L"\\Device\\HelloDRIVER"); // 處理派遣例程 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = DefaultDispatch; } DriverObject->DriverUnload = DriverUnload; DriverObject->MajorFunction[IRP_MJ_CREATE] = DefaultDispatch; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DefaultDispatch; DriverObject->MajorFunction[IRP_MJ_READ] = DefaultDispatch; DriverObject->MajorFunction[IRP_MJ_WRITE] = DefaultDispatch; // 建立裝置 status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), &deviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &deviceObject); if(!NT_SUCCESS(status)) { return status; } deviceObject->Flags = DO_BUFFERED_IO; deviceExtension = (PDEVICE_EXTENSION)deviceObject->DeviceExtension; deviceExtension->DeviceObject = deviceObject; deviceExtension->DeviceName = deviceName; RtlInitUnicodeString(&symbolicLink, L"\\??\\HelloDRIVER"); deviceExtension->SymbolicLink = symbolicLink; // 建立符號連結 status = IoCreateSymbolicLink(&symbolicLink, &deviceName); if(!NT_SUCCESS(status)) { IoDeleteDevice(deviceObject); return status; } KdPrint(("End of HelloDRIVER DriverEntry!\n")); return status; }
重點在於這兩句
RtlInitUnicodeString(&symbolicLink, L"\\??\\HelloDRIVER");
deviceExtension->SymbolicLink = symbolicLink;
在網上查詢資料RtlInitUnicodeString並沒有動態分配記憶體,而是指向應用,而由於
#pragma alloc_text(INIT, DriverEntry)
DriverEntry函式是執行完後就退出記憶體,所以 RtlInitUnicodeString(&deviceName, L"\\Device\\HelloDRIVER");這個賦值方式不可靠。
解決方案:
在標頭檔案或者函式外宣告一個全域性變數來儲存符號連結,如
WCHAR linkNameBuffer[] = L"\\??\\HelloDRIVER";
然後再在函式內
RtlInitUnicodeString(&symbolicLink, linkNameBuffer);
即可解決讀取符號連結不可訪問的問題。
總結:
1.Win7會出現藍屏,而XP不會,可能涉及到IoDeleteSymbolicLink裡面的實現,會判斷字串的合法性問題
2.INIT和PAGE的區別,在驅動載入入口函式要注意字串變數的生命週期
3.學會利用windbg進行除錯分析