五种常用的IRP类型:
#define IRP_MJ_CREATE 0x00 //CreateFile()
#define IRP_MJ_CLOSE 0x02 //CloseHandle()
#define IRP_MJ_READ 0x03//ReadFile
#define IRP_MJ_WRITE 0x04//WriteFile
#define IRP_MJ_DEVICE_CONTROL 0x0e//DeviceIoControl
入口函数中注册派遣函数
加载中驱动签名:
1.64bit的Windows要求对驱动进行数字签名.
2.引导驱动程序(start为0),由winload.exe的例程进行检查,不通过就不允许启动
3.非引导驱动程序有ntoskrnl.exe使用ci.dll的导出函数进行签名检查
如何对付签名?
1.购买证书并进行合法签名
2.利用第三方签名驱动漏洞
通信方式:
BOOL DeviceIoControl( HANDLE hDevice, DWORD dwIoControlCode,
LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
缓冲模式
用户层:
通过打开符号链接,获取设备访问. 将数据传输到驱动层.
并接受并处理驱动层处理完发送来的数据
// 与驱动通信exe端.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include<Windows.h> #include<winioctl.h> /* CTL_CODE宏,通信结构,参数一是未知设备,第个参数是功能号,800-fff之间,用于区分函数, 第个参数是通信模式,这里是缓冲模式,第个参数是需要哪些访问权限 */ #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED,FILE_ANY_ACCESS) #define sub_code CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED,FILE_ANY_ACCESS) #define SymLinkName L"\\\\.\\freesec_tx" int port[2],bufret; DWORD dwWrite; int add(HANDLE hDevice,int a,int b) { port[0]=a; port[1]=b; //该函数用于与驱动通信参数:设备句柄,CTL宏,函数参数地址,参数大小,驱动处理完返回 //给exe的字符串,返回字符串缓冲大小,实际返回字符串大小.NULL //驱动参数对应关系: //irp_stack->Parameters.DeviceIoControl.InputBufferLength; //irp_stack->Parameters.DeviceIoControl.OutputBufferLength; //irp_stack->Parameters.DeviceIoControl.IoControlCode; DeviceIoControl(hDevice, add_code , &port, 8, &bufret, 4, &dwWrite, NULL); //驱动将函数执行结果存储在bufret中. return bufret; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hDevice = CreateFile(SymLinkName, //\\??\My_DriverLinkName GENERIC_READ | GENERIC_WRITE, 0, // share mode none NULL, // no security OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0 ); // no template printf("start\n"); if (hDevice == INVALID_HANDLE_VALUE) { printf("获取驱动句柄失败: %s with Win32 error code: %d\n","MyDriver", GetLastError() ); getchar(); return -1; } //add_code int a=55; int b=33; int r= add(hDevice,a,b); printf("%d+%d=%d\n",a,b,r); getchar(); return 0; }
驱动:
//_stdcall #include<ntddk.h> #include <ntstrsafe.h> #define INCLUDE code_seg("INIT") #pragma INCLUDE #define symlink_name L"\\??\\freesec_tx" #define device_name L"\\device\\device_tx" #define add_func CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED,FILE_ANY_ACCESS) #define sub_func CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED,FILE_ANY_ACCESS) PDEVICE_OBJECT myDevice; UNICODE_STRING DeviceName; UNICODE_STRING SymLinkName; NTSTATUS MyDisPatcher(PDEVICE_OBJECT dev,PIRP irp) { NTSTATUS status=0; ULONG inputBufferSize; ULONG outputBufferSize; ULONG functionCode; int* inputBuffer; int* outputBuffer; PIO_STACK_LOCATION irp_stack=IoGetCurrentIrpStackLocation(irp);//这个栈主要用于获取非函数参数 DbgPrint("进入派遣函数\n"); if (dev!=myDevice) { status=0; return status; } switch(irp_stack->MajorFunction) { case IRP_MJ_DEVICE_CONTROL: DbgPrint("IRP_MJ_DEVICE_CONTROL!!!!!!!!!!!!!!!!!!!!!!\n"); //得到输入缓冲区大小 inputBufferSize = irp_stack->Parameters.DeviceIoControl.InputBufferLength; //得到输出缓冲区大小 outputBufferSize = irp_stack->Parameters.DeviceIoControl.OutputBufferLength; //得到IOCTL码 functionCode = irp_stack->Parameters.DeviceIoControl.IoControlCode; //获取参数缓冲区,这是输入输出共享的 inputBuffer=(int*)irp->AssociatedIrp.SystemBuffer; outputBuffer=(int*)irp->AssociatedIrp.SystemBuffer; switch(functionCode) { case add_func: DbgPrint("add_func!!!!!!!!!!!!!!!!!\n"); *outputBuffer=inputBuffer[0]+inputBuffer[1]; KdPrint((("计算结果为:%d\n"),*outputBuffer)); break; case sub_func: break; default: break; } break; case IRP_MJ_CREATE: break; case IRP_MJ_CLOSE: break; case IRP_MJ_READ: break; case IRP_MJ_WRITE: break; default: break; } irp->IoStatus.Information=4;//设置操作的字节数为,这里无实际意义 irp->IoStatus.Status=STATUS_SUCCESS;//返回成功 IoCompleteRequest(irp,IO_NO_INCREMENT);//指示完成此IRP KdPrint(("离开派遣函数\n"));//调试信息 return status; } NTSTATUS MyCreateDevice(PDRIVER_OBJECT db) { NTSTATUS status; RtlInitUnicodeString(&DeviceName,device_name); RtlInitUnicodeString(&SymLinkName,symlink_name); status=IoCreateDevice(db,0,&DeviceName,FILE_DEVICE_UNKNOWN,0,1,&myDevice); if (NT_SUCCESS(status)) { db->DeviceObject=myDevice; DbgPrint("设备创建成功!\n"); status=IoCreateSymbolicLink(&SymLinkName,&DeviceName); if(NT_SUCCESS(status)) { DbgPrint("符号链接创建成功!\n"); return status; } } return status; } void unLoadDriver(PDRIVER_OBJECT db) { IoDeleteSymbolicLink(&SymLinkName); DbgPrint("符号链接删除成功!\n"); IoDeleteDevice(db->DeviceObject); DbgPrint("设备删除成功!\n"); } NTSTATUS DriverEntry(PDRIVER_OBJECT db, PUNICODE_STRING us) { NTSTATUS status; db->DriverUnload=unLoadDriver; status=MyCreateDevice(db); db->MajorFunction[IRP_MJ_CREATE]=MyDisPatcher; db->MajorFunction[IRP_MJ_CLOSE]=MyDisPatcher; db->MajorFunction[IRP_MJ_READ]=MyDisPatcher; db->MajorFunction[IRP_MJ_WRITE]=MyDisPatcher; db->MajorFunction[IRP_MJ_DEVICE_CONTROL]=MyDisPatcher; return status; } 需要创建设备,创建符号链接, 添加卸载函数,派遣函数. 在派遣函数中处理用户层数据