回顧驅動與用戶層通信
阿新 • • 發佈:2018-11-09
註冊表 程序 size ems driver symbol array proc stack 環境:win10 64位
先關簽名
先關簽名
bcdedit.exe /set nointegritychecks on
1。緩沖區方式讀寫
橋梁是用一個buf
將數據存儲在AssociatedIrp.SystemBuffer
pDevObj->Flags |= DO_BUFFERED_IO
用戶層
main.cpp
#include <windows.h> #include <stdio.h> #define GetFilePointer(hFile) SetFilePointer(hFile, 0, NULL, FILE_CURRENT) int main() { HANDLE hDevice = CreateFile("\\\\.\\HelloDDK", GENERIC_READ | GENERIC_WRITE, 0, // share mode none NULL, // no security OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // no template if (hDevice == INVALID_HANDLE_VALUE) { printf("Failed to obtain file handle to device: " "%s with Win32 error code: %d\n", "MyWDMDevice", GetLastError()); //return 1; } UCHAR buffer[10]; memset(buffer, 0xBB, 10); ULONG ulRead; ULONG ulWrite; BOOL bRet; bRet = WriteFile(hDevice, buffer, 10, &ulWrite, NULL); if (bRet) { printf("Write %d bytes\n", ulWrite); } bRet = ReadFile(hDevice, buffer, 10, &ulRead, NULL); if (bRet) { printf("Read %d bytes:", ulRead); for (int i = 0; i<(int)ulRead; i++) { printf("%02X ", buffer[i]); } printf("\n"); } printf("file length:%d\n", GetFileSize(hDevice, NULL)); CloseHandle(hDevice); getchar(); return 0; }
驅動層
test.c
#include "Driver.h" /************************************************************************ * 函數名稱:DriverEntry * 功能描述:初始化驅動程序,定位和申請硬件資源,創建內核對象 * 參數列表: pDriverObject:從I/O管理器中傳進來的驅動對象 pRegistryPath:驅動程序在註冊表的中的路徑 * 返回 值:返回初始化驅動狀態 *************************************************************************/ #pragma INITCODE NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath) { NTSTATUS status; KdPrint(("Enter DriverEntry\n")); //設置卸載函數 pDriverObject->DriverUnload = HelloDDKUnload; //設置派遣函數 for (int i = 0; i < arraysize(pDriverObject->MajorFunction); ++i) pDriverObject->MajorFunction[i] = HelloDDKDispatchRoutin; pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDWrite; pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead; //用戶層獲取文件長度時用產生這個irp pDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = HelloDDKQueryInfomation; //創建驅動設備對象 status = CreateDevice(pDriverObject); KdPrint(("Leave DriverEntry\n")); return status; } /************************************************************************ * 函數名稱:CreateDevice * 功能描述:初始化設備對象 * 參數列表: pDriverObject:從I/O管理器中傳進來的驅動對象 * 返回 值:返回初始化狀態 *************************************************************************/ #pragma INITCODE NTSTATUS CreateDevice( IN PDRIVER_OBJECT pDriverObject) { NTSTATUS status; PDEVICE_OBJECT pDevObj; PDEVICE_EXTENSION pDevExt; //創建設備名稱 UNICODE_STRING devName; RtlInitUnicodeString(&devName, L"\\Device\\MyDDKDevice"); //創建設備 status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj); if (!NT_SUCCESS(status)) return status; pDevObj->Flags |= DO_BUFFERED_IO; pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; pDevExt->pDevice = pDevObj; pDevExt->ustrDeviceName = devName; //申請模擬文件的緩沖區 pDevExt->buffer = (PUCHAR)ExAllocatePool(PagedPool, MAX_FILE_LENGTH); //設置模擬文件大小 pDevExt->file_length = 0; //創建符號鏈接 UNICODE_STRING symLinkName; RtlInitUnicodeString(&symLinkName, L"\\??\\HelloDDK"); pDevExt->ustrSymLinkName = symLinkName; status = IoCreateSymbolicLink(&symLinkName, &devName); if (!NT_SUCCESS(status)) { IoDeleteDevice(pDevObj); return status; } return STATUS_SUCCESS; } /************************************************************************ * 函數名稱:HelloDDKUnload * 功能描述:負責驅動程序的卸載操作 * 參數列表: pDriverObject:驅動對象 * 返回 值:返回狀態 *************************************************************************/ #pragma PAGEDCODE VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject) { PDEVICE_OBJECT pNextObj; KdPrint(("Enter DriverUnload\n")); pNextObj = pDriverObject->DeviceObject; while (pNextObj != NULL) { PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pNextObj->DeviceExtension; if (pDevExt->buffer) { ExFreePool(pDevExt->buffer); pDevExt->buffer = NULL; } //刪除符號鏈接 UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName; IoDeleteSymbolicLink(&pLinkName); pNextObj = pNextObj->NextDevice; IoDeleteDevice(pDevExt->pDevice); } } /************************************************************************ * 函數名稱:HelloDDKDispatchRoutin * 功能描述:對讀IRP進行處理 * 參數列表: pDevObj:功能設備對象 pIrp:從IO請求包 * 返回 值:返回狀態 *************************************************************************/ #pragma PAGEDCODE NTSTATUS HelloDDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("Enter HelloDDKDispatchRoutin\n")); PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); //建立一個字符串數組與IRP類型對應起來 static char* irpname[] = { "IRP_MJ_CREATE", "IRP_MJ_CREATE_NAMED_PIPE", "IRP_MJ_CLOSE", "IRP_MJ_READ", "IRP_MJ_WRITE", "IRP_MJ_QUERY_INFORMATION", "IRP_MJ_SET_INFORMATION", "IRP_MJ_QUERY_EA", "IRP_MJ_SET_EA", "IRP_MJ_FLUSH_BUFFERS", "IRP_MJ_QUERY_VOLUME_INFORMATION", "IRP_MJ_SET_VOLUME_INFORMATION", "IRP_MJ_DIRECTORY_CONTROL", "IRP_MJ_FILE_SYSTEM_CONTROL", "IRP_MJ_DEVICE_CONTROL", "IRP_MJ_INTERNAL_DEVICE_CONTROL", "IRP_MJ_SHUTDOWN", "IRP_MJ_LOCK_CONTROL", "IRP_MJ_CLEANUP", "IRP_MJ_CREATE_MAILSLOT", "IRP_MJ_QUERY_SECURITY", "IRP_MJ_SET_SECURITY", "IRP_MJ_POWER", "IRP_MJ_SYSTEM_CONTROL", "IRP_MJ_DEVICE_CHANGE", "IRP_MJ_QUERY_QUOTA", "IRP_MJ_SET_QUOTA", "IRP_MJ_PNP", }; UCHAR type = stack->MajorFunction; if (type >= arraysize(irpname)) KdPrint((" - Unknown IRP, major type %X\n", type)); else KdPrint(("\t%s\n", irpname[type])); //對一般IRP的簡單操作,後面會介紹對IRP更復雜的操作 NTSTATUS status = STATUS_SUCCESS; // 完成IRP pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = 0; // bytes xfered IoCompleteRequest(pIrp, IO_NO_INCREMENT); KdPrint(("Leave HelloDDKDispatchRoutin\n")); return status; } NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("Enter HelloDDKRead\n")); //在 IoCreateDevice申請模擬文件的緩沖區 //pDevExt->buffer = (PUCHAR)ExAllocatePool(PagedPool, MAX_FILE_LENGTH); PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); ULONG ulReadLength = stack->Parameters.Read.Length; ULONG ulReadOffset = (ULONG)stack->Parameters.Read.ByteOffset.QuadPart; if (ulReadOffset + ulReadLength>MAX_FILE_LENGTH) { status = STATUS_FILE_INVALID; ulReadLength = 0; } else { //將數據存儲在AssociatedIrp.SystemBuffer,以便應用程序使用 memcpy(pIrp->AssociatedIrp.SystemBuffer, pDevExt->buffer + ulReadOffset, ulReadLength); status = STATUS_SUCCESS; } pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = ulReadLength; // bytes xfered IoCompleteRequest(pIrp, IO_NO_INCREMENT); KdPrint(("Leave HelloDDKRead\n")); return status; } NTSTATUS HelloDDWrite(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("Enter HelloDDWrite\n")); NTSTATUS status = STATUS_SUCCESS; //在 IoCreateDevice申請模擬文件的緩沖區 //pDevExt->buffer = (PUCHAR)ExAllocatePool(PagedPool, MAX_FILE_LENGTH); PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); //獲取存儲的長度 ULONG ulWriteLength = stack->Parameters.Write.Length; //獲取存儲的偏移量 就是buffer中從哪裏開始 ULONG ulWriteOffset = (ULONG)stack->Parameters.Write.ByteOffset.QuadPart; if (ulWriteOffset + ulWriteLength>MAX_FILE_LENGTH) { //如果存儲長度+偏移量大於緩沖區長度,則返回無效 status = STATUS_FILE_INVALID; ulWriteLength = 0; } else { //將寫入的數據,存儲在緩沖區內 memcpy(pDevExt->buffer + ulWriteOffset, pIrp->AssociatedIrp.SystemBuffer, ulWriteLength); status = STATUS_SUCCESS; //設置新的文件長度 if (ulWriteLength + ulWriteOffset>pDevExt->file_length) { pDevExt->file_length = ulWriteLength + ulWriteOffset; } } pIrp->IoStatus.Status = status; //用戶的返回值是這個 pIrp->IoStatus.Information = ulWriteLength; // bytes xfered IoCompleteRequest(pIrp, IO_NO_INCREMENT); KdPrint(("Leave HelloDDWrite\n")); return status; } NTSTATUS HelloDDKQueryInfomation(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("Enter HelloDDKQueryInfomation\n")); PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; FILE_INFORMATION_CLASS info = stack->Parameters.QueryFile.FileInformationClass; if (info == FileStandardInformation) { KdPrint(("FileStandardInformation\n")); PFILE_STANDARD_INFORMATION file_info = (PFILE_STANDARD_INFORMATION)pIrp->AssociatedIrp.SystemBuffer; file_info->EndOfFile = RtlConvertLongToLargeInteger(pDevExt->file_length); } NTSTATUS status = STATUS_SUCCESS; // 完成IRP pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = stack->Parameters.QueryFile.Length; // bytes xfered IoCompleteRequest(pIrp, IO_NO_INCREMENT); KdPrint(("Leave HelloDDKQueryInfomation\n")); return status; }
//Driver.h
#pragma once #ifdef __cplusplus extern "C" { #endif #include <NTDDK.h> #ifdef __cplusplus } #endif #define PAGEDCODE code_seg("PAGE") #define LOCKEDCODE code_seg() #define INITCODE code_seg("INIT") #define PAGEDDATA data_seg("PAGE") #define LOCKEDDATA data_seg() #define INITDATA data_seg("INIT") #define arraysize(p) (sizeof(p)/sizeof((p)[0])) #define MAX_FILE_LENGTH 1024 typedef struct _DEVICE_EXTENSION { PDEVICE_OBJECT pDevice; UNICODE_STRING ustrDeviceName; //設備名稱 UNICODE_STRING ustrSymLinkName; //符號鏈接名 PUCHAR buffer;//緩沖區 ULONG file_length;//模擬的文件長度,必須小於MAX_FILE_LENGTH } DEVICE_EXTENSION, *PDEVICE_EXTENSION; // 函數聲明 NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject); VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject); NTSTATUS HelloDDKDispatchRoutin(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp); NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp); NTSTATUS HelloDDWrite(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp); NTSTATUS HelloDDKQueryInfomation(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp);
回顧驅動與用戶層通信