版权声明:欢迎转载,注明出处 https://blog.csdn.net/youyou519/article/details/83825334
下面是NT框架
#include <ntddk.h>
#define DEVICE_NAME L"\\device\\ntmodeldrv" //设备名device开头固定,后面随便取,一般和编译出的.sys一致
#define LINK_NAME L"\\dosdevices\\ntmodeldrv"
#define IOCTRL_BASE 0X8000 //定义IoControl起始范围
#define MYIOCTRL_CODE(i) \
CTL_CODE(FILE_DEVICE_UNKNOWN,IOCTRL_BASE+i,METHOD_BUFFERED,FILE_ANY_ACCESS)//这里倒数第二个参数是访问模式
#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)
//定义Ring3的分发函数
//创建分发函数
NTSTATUS DispatchCommon(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;//这个是给ring3的返回值
pIrp->IoStatus.Information = 0;//记录Irp特殊数据,比如读写就是有效字节数
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;//这个是给内核驱动管理框架的
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT pObject, PIRP pIrp)//第一个参数驱动设备对象,在DriverEntry创建
{
pIrp->IoStatus.Status = STATUS_SUCCESS;//这个是给ring3的返回值
pIrp->IoStatus.Information = 0;//记录Irp特殊数据,比如读写就是有效字节数
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;//这个是给内核驱动管理框架的
}
NTSTATUS DispatchRead(PDEVICE_OBJECT pObject,PIRP pIrp)
{
//定义读Buffer指针
PVOID pReadBuffer = NULL;
ULONG uReadLength = 0;
PIO_STACK_LOCATION pStack = NULL;
ULONG uMin = 0;
ULONG uHelloStr = 0;
uHelloStr = (wcslen(L"hello world") + 1)*sizeof(WCHAR);
pReadBuffer = pIrp->AssociatedIrp.SystemBuffer;//地址
pStack = IoGetCurrentIrpStackLocation(pIrp);//获得当前层IRP栈的指针
uReadLength = pStack->Parameters.Read.Length;//从栈的结构体里的联合体获得长度
uMin = uReadLength > uHelloStr ? uHelloStr : uReadLength;
RtlCopyMemory(pReadBuffer, L"hello world", uMin);//这里要用目的和源最小的,以防泄露和溢出
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = uMin;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchWrite(PDEVICE_OBJECT pObject, PIRP pIrp)
{
PVOID pWriteBuffer = NULL;
ULONG uWriteLength = 0;
PIO_STACK_LOCATION pStack = NULL;
PVOID pBuffer = NULL;
pWriteBuffer = pIrp->AssociatedIrp.SystemBuffer;
pStack = IoGetCurrentIrpStackLocation(pIrp);
uWriteLength = pStack->Parameters.Write.Length;
//模拟写,就是分配个内存拷进去数据
pBuffer = ExAllocatePoolWithTag(PagedPool, uWriteLength, 'NQRY');
if (NULL == pBuffer)
{
pIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
//分配成功
//初始化申请的内存
memset(pBuffer, 0, uWriteLength);
RtlCopyMemory(pBuffer, pWriteBuffer, uWriteLength);
//释放buffer
ExFreePool(pBuffer);
pBuffer = NULL;
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = uWriteLength;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DispatchClose(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;//这个是给ring3的返回值
pIrp->IoStatus.Information = 0;//记录Irp特殊数据,比如读写就是有效字节数
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;//这个是给内核驱动管理框架的
}
NTSTATUS DispatchClean(PDEVICE_OBJECT pObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;//这个是给ring3的返回值
pIrp->IoStatus.Information = 0;//记录Irp特殊数据,比如读写就是有效字节数
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;//这个是给内核驱动管理框架的
}
NTSTATUS DispatchIoControl(PDEVICE_OBJECT pObject, PIRP pIrp)
{
ULONG uIoCtrlCode = 0;
PVOID pInputBuffer = NULL;
PVOID pOutputBuffer = NULL;
ULONG uInputLengrh = 0;
ULONG uOutputLength = 0;
PIO_STACK_LOCATION pStack = NULL;
pInputBuffer = pOutputBuffer = pIrp->AssociatedIrp.SystemBuffer;
pStack = IoGetCurrentIrpStackLocation(pIrp);
uInputLengrh = pStack->Parameters.DeviceIoControl.InputBufferLength;
uOutputLength = pStack->Parameters.DeviceIoControl.OutputBufferLength;
uIoCtrlCode = pStack->Parameters.DeviceIoControl.IoControlCode;
//根据不同code处理不同代码
switch (uIoCtrlCode)
{
case CTL_HELLO:
DbgPrint("Hello IoCtrlControl\n");
break;
case CTL_PRINT:
DbgPrint("%ws\n",pInputBuffer);
break;
case CTL_BYE:
DbgPrint("Good Bye\n");
break;
default:
DbgPrint("UnKown IoCtrlControl\n");
break;
}
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING uLinkName = { 0 };
RtlInitUnicodeString(&uLinkName, LINK_NAME);
//删除符号链接
IoDeleteSymbolicLink(&uLinkName);
//释放设备对象
IoDeleteDevice(pDriverObject->DeviceObject);
DbgPrint("Driver UnLoaded\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pRegPath)
{
UNICODE_STRING uDeviceName = { 0 };
UNICODE_STRING uLinkName = { 0 };
NTSTATUS ntStatus = 0;
PDEVICE_OBJECT pDeviceObject = NULL;
ULONG i = 0;
DbgPrint("Driver load begin\n");
//创建设备对象,将之前定义的设备名传入,接收IRP
RtlInitUnicodeString(&uDeviceName, DEVICE_NAME);
RtlInitUnicodeString(&uLinkName, LINK_NAME);
ntStatus = IoCreateDevice(pDriverObject,
0, &uDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("IoCreateDevice Failed:%x\n", ntStatus);
return ntStatus;
}
pDeviceObject->Flags |= DO_BUFFERED_IO;//ring3和ring0通讯协议
//创建符号链接,为了让Ring3看到识别驱动
ntStatus = IoCreateSymbolicLink(&uLinkName, &uDeviceName);
if (!NT_SUCCESS(ntStatus))
{
IoDeleteDevice(pDeviceObject);//失败先删掉
DbgPrint("IoCreateDevice Failed:%x\n", ntStatus);
return ntStatus;
}
//初始和注册化分发函数
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction[i] = DispatchCommon;
}
//初始化特殊分发
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoControl;
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchClean;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
pDriverObject->DriverUnload = DriverUnload;
DbgPrint("Driver load OK!\n");
//
return STATUS_SUCCESS;
}
下面是测试
// R3LoadDrv.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
//这个是R3的安装驱动程序
#include "pch.h"
#include <Windows.h>
#include <winsvc.h>
#include <conio.h>
#include <stdio.h>
#include <winioctl.h>
#define DRIVER_NAME "NTModelDrv"
#define DRIVER_PATH "C:\\DriverTest\\NTModelDrv.sys"
#define IOCTRL_BASE 0x8000
#define MYIOCTRL_CODE(i)\
CTL_CODE(FILE_DEVICE_UNKNOWN,IOCTRL_BASE+i,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define CTL_HELLO MYIOCTRL_CODE(0)
#define CTL_PRINT MYIOCTRL_CODE(1)
#define CTL_BYE MYIOCTRL_CODE(2)
//装载NT驱动框架
BOOL LoadDriver(char* lpszDriverName, char* lpszDriverPath)
{
/************************ 加载NT驱动的代码*******************************
① 调用OpenSCManager,打开SCM管理器.如果返回NULL,则返回失败,否则继续
② 调用CreateService,创建服务,创建成功则转步骤 ⑥
③ 用GetLastError的得到错误返回值
④ 返回值为ERROR_IO_PENDING,说明服务已经创建过,用OpenService打开此服务.
⑤ 返回值为其他值, 创建服务失败,返回失败.
⑥ 调用StartService开启服务
⑦ 成功返回
************************************************************************/
//char szDriverImagePath[256] = "C:\\DriverTest\\ntmodelDrv.sys";
char szDriverImagePath[256] = { 0 };
//得到完整驱动路径
//GetFullPathName(lpszDriverName, 256, szDriverImagePath, NULL);
BOOL bRet = FALSE;
SC_HANDLE hServiceMgr = NULL; //SCM管理器的句柄
SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
//打开服务控制管理器
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == hServiceMgr)
{
//OpenSCManger失败
printf("OpenSCManger() Faild %d !\n", GetLastError());
bRet = FALSE;
goto BeforeLeave;
}
else
{
printf("OpenSCManger() OK!\n");
}
//创建驱动所对应的服务
hServiceDDK=CreateService(
hServiceMgr,
lpszDriverName,//驱动程序在注册表中的名字
lpszDriverName, // 注册表驱动程序的 DisplayName 值
SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限
SERVICE_KERNEL_DRIVER,// 表示加载的服务是驱动程序
SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值
SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值
szDriverImagePath, // 注册表驱动程序的 ImagePath 值
NULL, //GroupOrder HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GroupOrderList
NULL,
NULL,
NULL,
NULL);
DWORD dwRtn;
if (NULL == hServiceDDK)
{
dwRtn = GetLastError();
if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS)
{
//由于其他原因创建服务失败
printf("CreateService() Faild %d !\n", dwRtn);
bRet = FALSE;
goto BeforeLeave;
}
else
{
//服务创建失败,是由于服务已经创立过
printf("CrateService() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS! \n");
}
// 驱动程序已经加载,只需要打开
hServiceDDK = OpenService(hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS);
if (NULL == hServiceDDK)
{
//如果打开服务也失败,则意味错误
dwRtn = GetLastError();
printf("OpenService() Faild %d ! \n", dwRtn);
bRet = FALSE;
goto BeforeLeave;
}
else
{
printf("OpenService() ok ! \n");
}
}
else
{
printf("CrateService() ok ! \n");
}
//开启此项服务
bRet = StartService(hServiceDDK, NULL, NULL);
if (!bRet)
{
DWORD dwRtn = GetLastError();
if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING)
{
printf("StartService() Faild %d ! \n", dwRtn);
bRet = FALSE;
goto BeforeLeave;
}
else
{
if (dwRtn == ERROR_IO_PENDING)
{
//设备被挂住
printf("StartService() Faild ERROR_IO_PENDING ! \n");
bRet = FALSE;
goto BeforeLeave;
}
else
{
//服务已经开启
printf("StartService() Faild ERROR_SERVICE_ALREADY_RUNNING ! \n");
bRet = TRUE;
goto BeforeLeave;
}
}
}
bRet = TRUE;
//离开前关闭句柄
BeforeLeave:
if (hServiceDDK)
{
CloseServiceHandle(hServiceDDK);
}
if (hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
return bRet;
}
//卸载驱动程序
BOOL UnloadDriver(char * szSvrName)
{
/************************* 卸载NT驱动的代码******************************
① 调用OpenSCManager,打开SCM管理器,如果返回NULL,则返回失败,否则继续.
② 调用OpenService.如果返回NULL,则返回失败,否则继续
③ 调用DeleteService卸载此项服务.
④ 成功返回.
************************************************************************/
BOOL bRet = FALSE;
SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDK = NULL;//NT驱动程序的服务句柄
SERVICE_STATUS SvrSta;
//打开SCM管理器
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hServiceMgr == NULL)
{
//带开SCM管理器失败
printf("OpenSCManager() Faild %d ! \n", GetLastError());
bRet = FALSE;
goto BeforeLeave;
}
else
{
//带开SCM管理器失败成功
printf("OpenSCManager() ok ! \n");
}
//打开驱动所对应的服务
hServiceDDK = OpenService(hServiceMgr, szSvrName, SERVICE_ALL_ACCESS);
if (hServiceDDK == NULL)
{
//打开驱动所对应的服务失败
printf("OpenService() Faild %d ! \n", GetLastError());
bRet = FALSE;
goto BeforeLeave;
}
else
{
printf("OpenService() ok ! \n");
}
//停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。
if (!ControlService(hServiceDDK, SERVICE_CONTROL_STOP, &SvrSta))
{
printf("ControlService() Faild %d !\n", GetLastError());
}
else
{
//打开驱动所对应的失败
printf("ControlService() ok !\n");
}
//动态卸载驱动程序。
if (!DeleteService(hServiceDDK))
{
//卸载失败
printf("DeleteSrevice() Faild %d !\n", GetLastError());
}
else
{
//卸载成功
printf("DelServer:eleteSrevice() ok !\n");
}
bRet = TRUE;
BeforeLeave:
//离开前关闭打开的句柄
if (hServiceDDK)
{
CloseServiceHandle(hServiceDDK);
}
if (hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
return bRet;
}
void TestDriver()
{
//测试驱动程序
HANDLE hDevice = CreateFile(
"\\\\.\\NTModelDrv",
GENERIC_WRITE|GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
printf("Create Device ok ! \n");
}
else
{
printf("Create Device faild %d ! \n", GetLastError());
return;
}
CHAR bufRead[1024] = { 0 };
CHAR bufWrite[1024] = "Hello, world";
DWORD dwRead = 0;
DWORD dwWrite = 0;
ReadFile(hDevice, bufRead, 1024, &dwRead, NULL);
CHAR bufInput[1024] = "Hello, world";
CHAR bufOutput[1024] = { 0 };
DWORD dwRet = 0;
DeviceIoControl(hDevice, CTL_HELLO, bufInput, sizeof(bufInput),
bufOutput, sizeof(bufOutput), &dwRet, NULL
);
CloseHandle(hDevice);
}
int main(int argc, char* argv[])
{
//加载驱动
BOOL bRet = LoadDriver((char*)DRIVER_NAME, (char*)DRIVER_PATH);
if (!bRet)
{
printf("LoadNTDriver error\n");
return 0;
}
//加载成功
printf("press any to create device!\n");
getchar();
TestDriver();
//这时候你可以通过注册表,或其他查看符号连接的软件验证。
printf("press any to unload the driver!\n");
getchar();
//卸载驱动
UnloadDriver((char*)DRIVER_NAME);
if (!bRet)
{
printf("UnloadNTDriver error\n");
return 0;
}
return 0;
}
参考