一、0环通信对象
在3环中通信一般是用消息机制(MSG)来进行相互通信的,而0环有IRP可以用来进行通信,并且可以利用这个来与3环通信
不同的调用方式
二、创建设备对象
首先需要创建设备名称
//创建设备名称 UNICODE_STRING Devicename; RtlInitUnicodeString(&Devicename,L"\Device\MyDevice");
然后创建设备对象
//创建设备 IoCreateDevice( pDriver, //当前设备所属的驱动对象 0, &Devicename, //设备对象的名称 FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObj //设备对象指针 );
三、数据交互方式
有三种方式:缓冲区方式读写、直接方式读写、其他方式读写
缓冲区方式读写(DO_BUFFERED_IO) :操作系统将应用程序提供缓冲区的数据复制到内核模式下的地址中。
直接方式读写(DO_DIRECT_IO) :操作系统会将用户模式下的缓冲区锁住。然后操作系统将这段缓冲区在内核模式地址再次映射一遍。这样,用户模式的缓冲区和内核模式的缓冲区指向的是同一区域的物理内存。缺点就是要单独占用物理页面。
其他方式读写(在调用IoCreateDevice创建设备后对pDevObj->Flags即不设置DO_BUFFERED_IO也不设置DO_DIRECT_IO此时就是其他方式) :
在使用其他方式读写设备时,派遣函数直接读写应用程序提供的缓冲区地址。在驱动程序中,直接操作应用程序的缓冲区地址是很危险的。只有驱动程序与应用程序运行在相同线程上下文的情况下,才能使用这种方式。
其中主要是缓冲区方式读写和直接方式读写,如果需要读写的量不是很多主要是缓冲区方式读写,如果读写的量很多主要是直接方式读写
四、创建符号链接
创建步骤跟创建设备对象差不多
//创建符号链接名称 RtlInitUnicodeString(&SymbolicLinkName,L"\??\MyTestDriver"); //创建符号链接 IoCreateSymbolicLink(&SymbolicLinkName,&Devicename);
1、设备名称的作用是给内核对象用的,如果要在Ring3访问,必须要有符号链接其实就是一个别名,没有这个别名,在Ring3不可见
2、内核模式下,符号链接是以"??"开头的,例如C盘就是"??C:"
3、而在用户模式下,则是以"\."开头的,如C盘就是"\.C:"
五、IRP的类型
当应用层通过CreateFile,ReadFile,WriteFile,CloseHandle等函数打开、从设备读取数据、向设备写入数据、关闭设备的时候,会使操作系统产生出IRP_MJ_CREATE,IRP_MJ_READ,IRP_MJ_WRITE,IRP_MJ_CLOSE等不同的IRP。
其他类型IRP
六、派遣函数
派遣函数就是对IRP的一种响应吧,先来看看它存在哪里
0: kd> dt _DRIVER_OBJECT ntdll!_DRIVER_OBJECT +0x000 Type : Int2B +0x002 Size : Int2B +0x004 DeviceObject : Ptr32 _DEVICE_OBJECT +0x008 Flags : Uint4B +0x00c DriverStart : Ptr32 Void +0x010 DriverSize : Uint4B +0x014 DriverSection : Ptr32 Void +0x018 DriverExtension : Ptr32 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING +0x028 FastIoDispatch : Ptr32 _FAST_IO_DISPATCH +0x02c DriverInit : Ptr32 long +0x030 DriverStartIo : Ptr32 void +0x034 DriverUnload : Ptr32 void //卸载函数 +0x038 MajorFunction : [28] Ptr32 long //派遣函数
注册派遣函数
//设置卸载函数 pDriverObject->DriverUnload = 卸载函数; //设置派遣函数 pDriverObject->MajorFunction[IRP_MJ_CREATE] = 派遣函数1; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = 派遣函数2; pDriverObject->MajorFunction[IRP_MJ_WRITE] = 派遣函数3; pDriverObject->MajorFunction[IRP_MJ_READ] = 派遣函数4; pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = 派遣函数5; pDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = 派遣函数6; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = 派遣函数7; pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = 派遣函数8; pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = 派遣函数9;
IRP_MJ_MAXIMUM_FUNCTION 派遣函数的最大值
派遣函数的格式
NTSTATUS MyDispatchFunction(PDEVICE_OBJECT pDevObj, PIRP pIrp) { //处理自己的业务... //设置返回状态 pIrp->IoStatus.Status = STATUS_SUCCESS; // getlasterror()得到的就是这个值 pIrp->IoStatus.Information = 0; // 返回给3环多少数据 没有填0 IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; }
通过IRP_MJ_DEVICE_CONTROL交互数据,应用层调用DeviceControl函数会产生此IRP
七、基于PspTerminateProcess任意关闭进程
驱动代码
#include<ntifs.h> #include<ntddk.h> #define DEVICE_NAME L"\Device\HbgDev" #define SYMBOLICLINK_NAME L"\??\HbgDevLnk" #define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) #define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS) typedef NTSTATUS(*_PspTerminateProcess)(PEPROCESS pEprocess, NTSTATUS ExitCode); typedef struct { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; UINT32 SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; UINT32 Flags; UINT16 LoadCount; UINT16 TlsIndex; LIST_ENTRY HashLinks; PVOID SectionPointer; UINT32 CheckSum; UINT32 TimeDateStamp; PVOID LoadedImports; PVOID EntryPointActivationContext; PVOID PatchInformation; }LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; _PspTerminateProcess PspTerminateProcess; VOID DriverUnload(PDRIVER_OBJECT pDriver) { DbgPrint("驱动卸载成功 "); } NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp) { DbgPrint("Application connect device"); //返回状态如果不设置,Ring3返回值是失败 pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj ,PIRP pIrp) { DbgPrint("Application disconnection"); pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; PIO_STACK_LOCATION pIrpStack; PVOID pIoBuffer; ULONG uIoControlCode; ULONG uOutLength; ULONG uInLength; ULONG uWrite; ULONG uRead; PEPROCESS pE; //设置临时变量的值 uRead = 0; uWrite = 0x12345678; //获取IRP数据 pIrpStack = IoGetCurrentIrpStackLocation(pIrp); //获取控制码 uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; //获取缓冲区地址(输入输出是同一个) pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; //Ring3 发送数据的长度 uInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; //Ring0 发送数据的长度 uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; DbgPrint("execute "); switch (uIoControlCode) { case OPER1: { DbgPrint("IrpDeviceControlProc -> OPER1... "); pIrp->IoStatus.Information = 0; status = STATUS_SUCCESS; break; } case OPER2: { __asm int 3; DbgPrint("IrpDeviceControlProc -> OPER2 输入字节数: %d ", uInLength); DbgPrint("IrpDeviceControlProc -> OPER2 输出字节数: %d ", uOutLength); memcpy(&uRead, pIoBuffer, 4); DbgPrint("%x", uRead); PsLookupProcessByProcessId((HANDLE)uRead, &pE); status=PspTerminateProcess(pE,0); DbgPrint("%x", status); pIrp->IoStatus.Information = 2; // 返回两字节 status = STATUS_SUCCESS; break; } } return STATUS_SUCCESS; } VOID FindDriver(PDRIVER_OBJECT pDriver, PVOID* KernelBase, PUINT32 uKernelImageSize) { PLDR_DATA_TABLE_ENTRY Head = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection; PLDR_DATA_TABLE_ENTRY Cur = Head; UNICODE_STRING pDriverName; RtlInitUnicodeString(&pDriverName, L"ntoskrnl.exe"); do { if (RtlCompareUnicodeString(&Cur->BaseDllName, &pDriverName, TRUE) == 0) { *KernelBase = Cur->DllBase; *uKernelImageSize = Cur->SizeOfImage; return; } Cur = (PLDR_DATA_TABLE_ENTRY)Cur->InLoadOrderLinks.Flink; } while (Cur != Head); return; } PVOID MemorySearch(PVOID KernelBase,ULONG uKernelImageSize,PVOID ByteCode,UINT32 ByteLength) { PVOID CurKernelBase=KernelBase; while ((ULONG)CurKernelBase != (ULONG)KernelBase + uKernelImageSize) { if (RtlCompareMemory(CurKernelBase, ByteCode, ByteLength) == ByteLength) { return (PVOID)(((UINT32)CurKernelBase) - 0x6); } CurKernelBase = (PVOID)((UINT32)CurKernelBase + 1); } } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path) { NTSTATUS status; PDEVICE_OBJECT pDeviceObj; UNICODE_STRING Devicename; UNICODE_STRING SymbolicLinkName; PVOID KernelBase=NULL; UINT32 uKernelImageSize; UINT32 ByteCode[] = { 0x0124a164, 0x758b0000, 0x44703b08, 0x0db80775, 0xebc00000, 0xbe8d575a, 0x00000248, 0x200147f6, 0x868d1274, 0x00000174 }; //初始化设备名 RtlInitUnicodeString(&Devicename, DEVICE_NAME); //创建设备对象 status=IoCreateDevice(pDriver, 0, &Devicename, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE,&pDeviceObj); pDeviceObj->Flags |= DO_BUFFERED_IO; if (status != STATUS_SUCCESS) { IoDeleteDevice(pDeviceObj); DbgPrint("创建设备失败. "); return status; } //创建符号链接名称 RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINK_NAME); //创建符号链接 IoCreateSymbolicLink(&SymbolicLinkName, &Devicename); //创建分发函数 pDriver->DriverUnload = DriverUnload; pDriver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc; pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc; pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc; //查找PspTerminiateProcess地址 //查找函数地址 FindDriver(pDriver, &KernelBase, &uKernelImageSize); PspTerminateProcess = (_PspTerminateProcess)MemorySearch(KernelBase, uKernelImageSize, ByteCode, sizeof(ByteCode)); return STATUS_SUCCESS; }
3环
// IRPTest_R3.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <winioctl.h> #define DEVICE_NAME L"\Device\HbgDev" #define SYMBOLICLINK_NAME L"\\.\HbgDevLnk" #define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) #define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS) #define IN_BUFFER_MAXLENGTH 4 #define OUT_BUFFER_MAXLENGTH 4 int main(int argc, char* argv[]) { int pid; scanf("%d",&pid); // 获取设备句柄 HANDLE hDevice = CreateFileW(SYMBOLICLINK_NAME,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); DWORD dwError = GetLastError(); if (hDevice == INVALID_HANDLE_VALUE) { printf("获取设备句柄失败 %d. ", dwError); // 如果返回1,请在驱动中指定 IRP_MJ_CREATE 处理函数 getchar(); return 1; } else { printf("获取设备句柄成功. "); } // 测试通信 DWORD dwInBuffer = pid; DWORD dwOutBuffer = 0xFFFFFFFF; DWORD dwOut; DeviceIoControl(hDevice,OPER2,&dwInBuffer,IN_BUFFER_MAXLENGTH,&dwOutBuffer,OUT_BUFFER_MAXLENGTH,&dwOut,NULL); printf("dwOutBuffer: %08X dwOut: %08X ", dwOutBuffer, dwOut); // 关闭设备 CloseHandle(hDevice); getchar(); return 0; }
第一次几乎全自己写完的,但是看了hambaga师傅的博客后,自己注册驱动???看来得学一手