问: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
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课