首页
社区
课程
招聘
[求助]VS2015编写WDM NT式驱动,成功编译,成功在WIN10x64上加载,但是下的断点有时候不会命中
发表于: 2016-12-12 16:04 6927

[求助]VS2015编写WDM NT式驱动,成功编译,成功在WIN10x64上加载,但是下的断点有时候不会命中

2016-12-12 16:04
6927
问:VS2015调试驱动,下的断点有时候会一个都不断下,有时候只断下几个,请懂得朋友回帖讲解原因
PS:在次先非常感谢朋友们花时间看我的问题,如果我提供得信息不够您判断的话,请回帖告知,我会立马向您提供相关信息

VS2015编写WDM NT式驱动,成功编译,成功在WIN10x64上加载;

我的具体调试步骤是:
1.将编译好的.sys .car .pbd文件拷贝到目标机
(用KmdManager工具加载驱动,服务安装卸载,启动停止,都是成功的)
2.首先安装服务
4.然后到VS中暂停虚拟机,这时候虚拟机鼠标等等不可以使用,属于调试状态
5.然后在VS的源文件中下断点
6.然后在继续运行虚拟机
7.在虚拟机中点运行驱动,这时候VS中已经有断点断下,但是断点命中层次不齐,很多都没有断到
8.然后继续运行虚拟机
9.在虚拟机中点卸载驱动
10.VS中再次断下,但是只有部分断断点命中
11.调试结束

但是下的断点有时候不会命中,或者下5个断点,前几个或者后几个不会命中,只会命中其中几个。


驱动卸载的时候只会命中箭头指的这里,前面两个不会命中,如果只下前面两个任意一个断点或者两个断点都下,也同样不会命中


驱动加载的时候,只会命中箭头所指代码,前面的都不会命中,调试了很久,命中结果有时会参差不齐,但都不会完全命中

/*
WIN64驱动开发模板
作者:Tesla.Angela
*/

//【0】包含的头文件,可以加入系统或自己定义的头文件
#include <ntddk.h>
#include <windef.h>
#include <stdlib.h>

//【1】定义符号链接,一般来说修改为驱动的名字即可
#define	DEVICE_NAME			L"\\Device\\KrnlHW64"
#define LINK_NAME			L"\\DosDevices\\KrnlHW64"
#define LINK_GLOBAL_NAME	L"\\DosDevices\\Global\\KrnlHW64"

//【2】定义驱动功能号和名字,提供接口给应用程序调用
#define IOCTL_IO_TEST		CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SAY_HELLO		CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

//【3】驱动卸载的处理例程
VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
	UNICODE_STRING strLink;
	DbgPrint("[KrnlHW64]DriverUnload\n");
	//删除符号连接和设备
	RtlInitUnicodeString(&strLink, LINK_NAME);
	IoDeleteSymbolicLink(&strLink);
	IoDeleteDevice(pDriverObj->DeviceObject);
}

//【4】IRP_MJ_CREATE对应的处理例程,一般不用管它
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDevObj);
	DbgPrint("[KrnlHW64]DispatchCreate\n");
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

//【5】IRP_MJ_CLOSE对应的处理例程,一般不用管它
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDevObj);
	DbgPrint("[KrnlHW64]DispatchClose\n");
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

//【6】IRP_MJ_DEVICE_CONTROL对应的处理例程,驱动最重要的函数之一,一般走正常途径调用驱动功能的程序,都会经过这个函数
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDevObj);
	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
	PIO_STACK_LOCATION pIrpStack;
	ULONG uIoControlCode;
	PVOID pIoBuffer;
	ULONG uInSize;
	ULONG uOutSize;
	DbgPrint("[KrnlHW64]DispatchIoctl\n");
	//获得IRP里的关键数据
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
	//这个就是传说中的控制码
	uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
	//输入和输出的缓冲区(DeviceIoControl的InBuffer和OutBuffer都是它)
	pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
	//EXE发送传入数据的BUFFER长度(DeviceIoControl的nInBufferSize)
	uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
	//EXE接收传出数据的BUFFER长度(DeviceIoControl的nOutBufferSize)
	uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	switch (uIoControlCode)
	{
		//在这里加入接口
	case IOCTL_IO_TEST:
	{
		DWORD dw = 0;
		//输入
		memcpy(&dw, pIoBuffer, sizeof(DWORD));
		//使用
		dw++;
		//输出
		memcpy(pIoBuffer, &dw, sizeof(DWORD));
		//返回通信状态
		status = STATUS_SUCCESS;
		break;
	}
	case IOCTL_SAY_HELLO:
	{
		DbgPrint("[KrnlHW64]IOCTL_SAY_HELLO\n");
		status = STATUS_SUCCESS;
		break;
	}
	}
	//这里设定DeviceIoControl的*lpBytesReturned的值(如果通信失败则返回0长度)
	if (status == STATUS_SUCCESS)
		pIrp->IoStatus.Information = uOutSize;
	else
		pIrp->IoStatus.Information = 0;
	//这里设定DeviceIoControl的返回值是成功还是失败
	pIrp->IoStatus.Status = status;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return status;
}

//【7】驱动加载的处理例程,里面进行了驱动的初始化工作
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
	UNREFERENCED_PARAMETER(pDriverObj);
	UNREFERENCED_PARAMETER(pRegistryString);
	NTSTATUS status = STATUS_SUCCESS;
	UNICODE_STRING ustrLinkName;
	UNICODE_STRING ustrDevName;
	PDEVICE_OBJECT pDevObj;
	//设置分发函数和卸载例程
	pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
	pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
	pDriverObj->DriverUnload = DriverUnload;
	//创建一个设备
	RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
	status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
	if (!NT_SUCCESS(status))	return status;
	//判断支持的WDM版本,其实这个已经不需要了,纯属WIN9X和WINNT并存时代的残留物
	if (IoIsWdmVersionAvailable(1, 0x10))
		RtlInitUnicodeString(&ustrLinkName, LINK_GLOBAL_NAME);
	else
		RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
	//创建符号连接
	status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);
	if (!NT_SUCCESS(status))
	{
		IoDeleteDevice(pDevObj);
		return status;
	}
	DbgPrint("[KrnlHW64]DriverEntry\n");
	//返回加载驱动的状态(如果返回失败,驱动讲被清除出内核空间)
	return STATUS_SUCCESS;
}

代码是Tesla.Angela大神教程中的,我只是加了几行关于取消变量未使用的警告的代码


这是目标机配置,Win10 10586[2016年2月最新镜像] 64位 虚拟机 (主机可以Ping通虚拟机,且虚拟机可以上网,是新系统,官方镜像安装的)


这是项目文件,只有一个Driver.c源码,源码在上方已给出。



这是驱动项目的设置信息

本人初学驱动,加过很多驱动开发的群,也逛过很多驱动开发的论坛,各种资料不全,很多简单的问题也没有人去帮忙解决,群内技术交流环境也十分的差。
为此,我准备为驱动开发的入门这一块尽我自己的能力去弥补弥补,我会看很多书籍,看很多帖子,把我的经验理解贴出来,也同时去帮助其他菜鸟入门学习,不要让这么多的有志青年在弯路中一直迷失方向。

目前只创建一个QQ交流群,群内会共享一些比较系统的教程,和我个人学习的一些笔记。
后续我会想其他办法继续完善
同时欢迎各路大神入驻本群 在闲暇之余来帮助帮助菜鸟  且当是复习基础吧

群号:43934862
QQ: 1269766498

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 20
活跃值: (250)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
之前也是和你一样,反来每次调试时都把驱动生成最新的拷进去,然后断点都能正常断下了。
2016-12-12 17:20
0
雪    币: 284
活跃值: (250)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
直接在代码里面写__debugbreak()
2016-12-12 19:01
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
好像只有这种方法了
2016-12-20 20:12
0
雪    币: 6
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
试过,有时候还是不管事
2016-12-20 20:13
0
雪    币: 145
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
一直在用windbg..
2016-12-20 21:52
0
游客
登录 | 注册 方可回帖
返回
//