首页
社区
课程
招聘
DriverMonitor加载驱动不成功,求解
发表于: 2014-5-5 10:04 11259

DriverMonitor加载驱动不成功,求解

2014-5-5 10:04
11259
我在XP系统的虚拟机上,写好了NT驱动,然后DriverMonitor加载驱动,第一次使用时,能加载成功,看到结果。

然后我再把驱动卸载(点击上面的圆红叉按钮),再重新加载时,就出现下面的提示。
ERROR(2):The ImagePath specified in the driver's service database entry is incorrect, or the file is missing.

怎么也不能再加载上,必须要重启虚拟机才能再加载上。而且也是只有第一次能成功。请问这是什么原因? 难道我每次修改了程序,还得重启一次才能测试? 求各位帮忙。

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 185
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
你驱动有卸载的入口?
2014-5-5 10:24
0
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
有啊,代码都直接抄过来的, 如果没有的话,我第一次卸载不了啊
#pragma INITCODE
extern "C" NTSTATUS DriverEntry (
			IN PDRIVER_OBJECT pDriverObject,
			IN PUNICODE_STRING pRegistryPath	) 
{
	NTSTATUS status;
	KdPrint(("Enter DriverEntry\n"));

	//注册其他驱动调用函数入口
	pDriverObject->DriverUnload = HelloDDKUnload;
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
	
	//创建驱动设备对象
	status = CreateDevice(pDriverObject);

	StringTest();

	KdPrint(("DriverEntry end\n"));
	return status;
}
........
........

#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;

		//删除符号链接
		UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
		IoDeleteSymbolicLink(&pLinkName);
		pNextObj = pNextObj->NextDevice;
		IoDeleteDevice( pDevExt->pDevice );
	}
}
2014-5-5 10:38
0
雪    币: 209
活跃值: (818)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
把完整代码都贴上来
2014-5-5 11:17
0
雪    币: 3
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
把代码放上来分析下
2014-5-5 15:12
0
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
头文件
#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]))

typedef struct _DEVICE_EXTENSION {
	PDEVICE_OBJECT pDevice;
	UNICODE_STRING ustrDeviceName;	//设备名称
	UNICODE_STRING ustrSymLinkName;	//符号链接名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

// 函数声明

NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
								 IN PIRP pIrp);


#include "Driver.h"

#pragma INITCODE
VOID StringInitTest()
{
	ANSI_STRING AnsiString1;
	CHAR *string1 = "hello";
	RtlInitAnsiString(&AnsiString1, string1);
	KdPrint(("Ansistring1:%Z\n", &AnsiString1));

	string1[0] = 'H';
	string1[1] = 'f';
	string1[2] = 'L';
	string1[3] = 'L';
	string1[4] = 'O';

	KdPrint(("AnsiString1:%Z\n", &AnsiString1));

#define BUFFER_SIZE 1024
	UNICODE_STRING UnicodeString1 = {0};
	UnicodeString1.MaximumLength = BUFFER_SIZE;
	UnicodeString1.Buffer = (PWSTR)ExAllocatePool(PagedPool, BUFFER_SIZE);
	WCHAR *wideString = L"hello";

	UnicodeString1.Length = 2 * wcslen(wideString);

	ASSERT(UnicodeString1.MaximumLength >= UnicodeString1.Length);

	RtlCopyMemory(UnicodeString1.Buffer, wideString, UnicodeString1.Length);

	KdPrint(("UnidodeString:%wZ\n", &UnicodeString1));

	ExFreePool(UnicodeString1.Buffer);
	UnicodeString1.Buffer = NULL;
	UnicodeString1.Length = UnicodeString1.MaximumLength = 0;
}

/************************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
      pDriverObject:从I/O管理器中传进来的驱动对象
      pRegistryPath:驱动程序在注册表的中的路径
* 返回 值:返回初始化驱动状态
*************************************************************************/
#pragma INITCODE

extern "C" NTSTATUS DriverEntry(
			IN PDRIVER_OBJECT pDriverObject,
			IN PUNICODE_STRING pRegistryPath)
{
	NTSTATUS status;
	KdPrint(("Enter driverEntry\n"));

	pDriverObject->DriverUnload = HelloDDKUnload;
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;

	status = CreateDevice(pDriverObject);

	StringInitTest();

	KdPrint(("driverEntry end\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),
				&(UNICODE_STRING)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;

	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)
	{
		PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;

		UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
		IoDeleteSymbolicLink(&pLinkName);
		pNextObj = pNextObj->NextDevice;
		IoDeleteDevice(pDevExt->pDevice);
	}
}
/************************************************************************
* 函数名称:HelloDDKDispatchRoutine
* 功能描述:对读IRP进行处理
* 参数列表:
      pDevObj:功能设备对象
      pIrp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
{
	KdPrint(("Enter HelloDDKDispatchRoutine\n"));
	NTSTATUS status = STATUS_SUCCESS;

	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	KdPrint(("leave HelloDDKDispatchRoutine\n"));
	return status;
}


全部的了
2014-5-6 07:33
0
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7

#include "Driver.h"

#pragma INITCODE
VOID StringInitTest() 
{
	//(1)用RtlInitAnsiString初始化字符串
	ANSI_STRING  AnsiString1;
	CHAR * string1= "hello";
	//初始化ANSI_STRING字符串
	RtlInitAnsiString(&AnsiString1,string1);
	KdPrint(("AnsiString1:%Z\n",&AnsiString1));//打印hello

	string1[0]='H';
	string1[1]='E';
	string1[2]='L';
	string1[3]='L';
	string1[4]='O';
	//改变string1,AnsiString1同样会导致变化
	KdPrint(("AnsiString1:%Z\n",&AnsiString1));//打印HELLO

	//(2)程序员自己初始化字符串
#define BUFFER_SIZE 1024
	UNICODE_STRING UnicodeString1 = {0};
	//设置缓冲区大小
	UnicodeString1.MaximumLength = BUFFER_SIZE;
	//分配内存  // 参一:Specifies the type of pool memory to allocate.
	UnicodeString1.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
	WCHAR* wideString = L"hello";

	//设置字符长度,因为是宽字符,所以是字符长度的2倍
	UnicodeString1.Length = 2*wcslen(wideString);

	//保证缓冲区足够大,否则程序终止
	ASSERT(UnicodeString1.MaximumLength>=UnicodeString1.Length);
	//内存拷贝,
	RtlCopyMemory(UnicodeString1.Buffer,wideString,UnicodeString1.Length);
	//设置字符长度
	UnicodeString1.Length = 2*wcslen(wideString);

	KdPrint(("UnicodeString:%wZ\n",&UnicodeString1));

	//清理内存
	ExFreePool(UnicodeString1.Buffer);
	UnicodeString1.Buffer = NULL;
	UnicodeString1.Length = UnicodeString1.MaximumLength = 0;
}



/************************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
      pDriverObject:从I/O管理器中传进来的驱动对象
      pRegistryPath:驱动程序在注册表的中的路径
* 返回 值:返回初始化驱动状态
*************************************************************************/
#pragma INITCODE// 放在INIT段,加载结束可从内存中卸载
extern "C" NTSTATUS DriverEntry (
			IN PDRIVER_OBJECT pDriverObject, // IN-代表参数纯粹用于输入目的,OUT-代表这参数仅用于函数的输出参数,INOUT-既可以输入又可以输出的参数
			IN PUNICODE_STRING pRegistryPath	) 
{
	NTSTATUS status;
	KdPrint(("Enter DriverEntry\n"));

	//注册其他驱动调用函数入口
	// 向Windows的I/O管理器注册一些回调函数
	pDriverObject->DriverUnload = HelloDDKUnload;
	pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
	pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
	
	//创建驱动设备对象
	status = CreateDevice(pDriverObject);

	StringInitTest();

	KdPrint(("DriverEntry end\n"));
	return status;
}

/************************************************************************
* 函数名称:CreateDevice
* 功能描述:初始化设备对象  (此函数能将多个设备对象链接在一起)
* 参数列表:
      pDriverObject:从I/O管理器中传进来的驱动对象
* 返回 值:返回初始化状态
*************************************************************************/
#pragma INITCODE // 指明此函数加载到INIT内存区域,成功卸载后可退出内存
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),
						&(UNICODE_STRING)devName,
						FILE_DEVICE_UNKNOWN,// 此设备为独占设备,只能被一个应用程序使用 一般虚拟设备常使用这个作为设备类型
						0,// 指定一个或多个系统定义的常量,连接在一起,提供有关驱动程序的设备其他信息.
						TRUE,// 如果是独占的话设置为TRUE,非独占设置为FALSE.
						&pDevObj );// 指向的指针用来接收DEVICE_OBJECT结构体.
	if (!NT_SUCCESS(status))
		return status;

	pDevObj->Flags |= DO_BUFFERED_IO;// 表明此种设备为BUFFERED_IO设备  读写操作使用缓冲方式 书P114  将设备设置成缓冲区设备
	// 填写设备的扩展结构体,在其它驱动程序的函数中可很方便得到这个结构体,进而得到该设备的自定义信息
	pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;// 得到设备对象扩展数据结构
	// 设置设备扩展的设备对象
	pDevExt->pDevice = pDevObj;
	// 设置设备扩展中的设备名称
	pDevExt->ustrDeviceName = devName;
	//创建符号链接
	UNICODE_STRING symLinkName;
	RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");  // 符号链接以 \??\ 开头, 如C盘是 \??\C
	pDevExt->ustrSymLinkName = symLinkName;
	status = IoCreateSymbolicLink( &symLinkName,&devName );
	if (!NT_SUCCESS(status)) 
	{
		IoDeleteDevice( pDevObj ); // 删除设备对象
		return status;
	}
	return STATUS_SUCCESS;
}

/************************************************************************
* 函数名称:HelloDDKUnload
* 功能描述:负责驱动程序的卸载操作
* 参数列表:
      pDriverObject:驱动对象
* 返回 值:返回状态
*************************************************************************/
// 由I/O管理器负责调用此回调函数
// 卸载驱动例程主要目的是遍历系统中所有此类设备对象,然后删除设备对象及符号链接
#pragma PAGEDCODE
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject) 
{
	PDEVICE_OBJECT	pNextObj;
	KdPrint(("Enter DriverUnload\n"));
	pNextObj = pDriverObject->DeviceObject;// 第一个设备对象的地址存在于驱动对象的DeviceObject域
	while (pNextObj != NULL) 
	{
		PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
			pNextObj->DeviceExtension; // 得到设备扩展  设备的扩展结构体

		//删除符号链接
		UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
		IoDeleteSymbolicLink(&pLinkName);
		pNextObj = pNextObj->NextDevice;  // 每个设备对象的NextDevice域记录着下一个设备对象的地址
		// 删除设备
		IoDeleteDevice( pDevExt->pDevice );// 参数就是要被删除的设备对象指针
	}
}

/************************************************************************
* 函数名称:HelloDDKDispatchRoutine
* 功能描述:对读IRP进行处理
* 参数列表:
      pDevObj:功能设备对象
      pIrp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
// 对设备对象的创建,关闭和读写操作都被指定到这个默认的派遣例程中
#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
								 IN PIRP pIrp) 
{
	KdPrint(("Enter HelloDDKDispatchRoutine\n"));
	NTSTATUS status = STATUS_SUCCESS;
	// 完成IRP
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = 0;	// bytes xfered
	// This value is IO_NO_INCREMENT if the original thread requested an operation
	// the driver could complete quickly (so the requesting thread is not compensated for its assumed wait for I/O to be completed)
	// or if the IRP is completed with an error.
	// 如果要求操作的原始线程需要驱动程序快速的完成处理,
	// 或者IRP填充完成时有错误发生,那么这个值就应该设为 IO_NO_INCREMENT。
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	KdPrint(("Leave HelloDDKDispatchRoutine\n"));
	return status;
}


我6楼的代码就是按照上面的代码抄来的,但这段代码生成的SYS文件,就能不停地加载,不会出现1楼所说的提示,但我用6楼的代码就会有这提示,请问是怎么回事啊?

我已经把while(!pNextObj) 改回 while(pNextObj != NULL) 还是这样。 求教啊
2014-5-6 07:51
0
雪    币: 46
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
应该不是while(!pNextObj) 改回 while(pNextObj != NULL)的问题。

你说你加载/卸载原来的驱动程序没问题,是不是原来的驱动程序没有删除干净?注意你的代码和原来的是一样的,创建的设备对象名字也是一样的。
如果你原来的驱动程序和现在的驱动程序二进制名字不一样就可能产生名字冲突。
2014-5-7 14:28
0
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
确实 是因为之前代码写错,没有把设备删除干净,所以后来代码改回while(pNextObj != NULL)
也不能解决问题,之后重启了系统,再运行就没有问题了。
2014-6-4 10:16
0
游客
登录 | 注册 方可回帖
返回
//