Windows内核开发-5-(2)-内核模式调试
Windows内核开发-5-(2)-内核模式调试
普通用户模式的调试,采取的是给进程添加一个线程来挂起断点,作为一个调试器的线程在进程中使用。照这样来类推,对操作系统调试相当于添加一个进程来限制操作系统,所以操作系统是会被冻结的。这样的话就不能直接在本机电脑上进行调试了,不然电脑就卡住了。而且还容易出现问题。最好的办法是创建一个虚拟机,用一台主力机给一台专门用来测试的计算机调试。
测试机和主力机必须通过一种方式来连接,选择有很多,最好的选择是通过网络连接,但是网络连接要求target和host至少是Win8以上,Win7就很尴尬了,但是由于这个很多搞安全的要求兼容,就会很麻烦。以至于很多采用串口连接,这里我们将如何建立串口连接。
还有需要注意的就是这个操作系统的版本和位数。你要开发什么样子的就用什么样子的操作系统。比如说:你要开发一个在Win10 64位计算机上用的东西,你就装一个Win10 64位虚拟机。虽然大部分都有兼容的效果,比如在64位上能跑32位的程序,但是还是建议采用对应的操作系统版本。
搭建内核模式调试环境
这里我采用的是Win10 32位虚拟机,和Win10 64位本机,采用串口连接。
下载操作系统
这个在msdn上下载你需要的对应版本的操作系统就好:
https://msdn.itellyou.cn/,安装虚拟机如果不清楚就自行百度一下。
添加启动引导
给测试机添加启动引导,需要使用管理员模式启动命令行:
cmd管理员身份运行bcdedit
bcdedit /copy {current} /d Sna1lGo//这里的Sna1lGo是引导名称,自己随意设置。
bcdedit /displayorder {xxxxx-xxxx-xxx} /addlast //这里的xxx是你在设置了引导名称后的一长条字符串
//这里的addlast是引导的位置,last表示是最后
bcdedit /dbgsettings SERIAL DEBUGPORT:1 BAUDRATE:115200 //设置调试端口波特率
bcdedit /debug {xxxxx-xxxx-xxx} ON//对新加的启动项增加调试功能
bcdedit /timeout 20//选择等待时长
设置完成后,再开机就有系统启动引导了。
虚拟机设置:
添加串行端口:(如果你的虚拟机里面有打印机,打印机默认会占用一个名为//./pipe/com_1的串行端口)
命名随意,只要是//./pipe/xxx就行,这里我采用的是把打印机移除掉,然后命名为//./pipe/com_1。
WinDbg配置
给WinDbg配置当启动的时候自动连接到测试机。首先根据测试机的位数选择同样的WinDbg,这里我选择32位的WinDbg,然后弄了一个快捷方式在桌面。
快捷方式这里有一个目标,在这个目标的后面添加参数:
-k com:port=//./pipe/com_1,baud=115200,pipe
这里的参数是和前面一一对应的,如果有问题就自己找找前面的定义。然后就可以直接运行WinDbg来调试Windows了。
给WinDbg配置符号
符号就是说函数名称的配置,如果不配置函数名称不完整,大概可以先这样理解。
在WinDbg中选择Symbol Search Path(快捷键Ctrl+S):
然后输入:
srv*D:\symbol*;srv*D:\symbol*http://msdl.microsoft.com/download/symbols
这段指令的意思是,会在D:\symbol中存储符号表,如果没有就到后面那个http:地址下载,然后存放到前面那个地址,这个存放的地址可以自己选择。然后就完美了,大功告成。
开始内核调试:
这里采用之前在第四章写的简单完整驱动来调试。
Windows内核驱动--实现修改线程优先级demo - Sna1lGo - 博客园 (cnblogs.com)这里下载例子。
然后将生成的sys和pdb文件一起复制到虚拟机里面,然后安装驱动但是不加载驱动。参考该博客来安装驱动:Windows内核开发-2-开始内核开发-2-内核开发入门 - Sna1lGo - 博客园 (cnblogs.com)
进入WinDbg后,给我们自己写的入口函数打一个断点:
bu prioritybooster!driverentry
这里采用的是bu断点:bu 命令是针对某个符号下断点。 比如 bu MyApp!SomeFunction 。 在代码被修改之后, 该断点可以随着函数地址改变而自动更新到最新位置。 而且bu 断点会保存在WinDbg工作空间中, 下次启动 Windbg 的时候该断点会自动设置上去。另外,在模块没有被加载的时候,bp 断点会失败(因为函数地址不存在),而bu 断点则可以成功。 新版的WinDBG中 bp失败后会自动被转成bu 。
打下断点后,我们在WinDbg命令行中输入g,让系统跑起来,然后再在系统中去加载该驱动。
如果一切顺利的话会出现下面这样:
就可以像一些平常的调试器一样来调试东西了。
输入k指令来查看堆栈:
1: kd> k
# ChildEBP RetAddr
00 8985fad8 81dac709 PriorityBooster!DriverEntry [D:\ProjectSum\Driver\PriorityBooster\PriorityBooster.cpp @ 14]
01 8985fbc8 81e3552c nt!IopLoadDriver+0x443
02 8985fbe8 81aefa6a nt!IopLoadUnloadDriver+0x42
03 8985fc38 81abe0f0 nt!ExpWorkerThread+0xea
04 8985fc70 81b9a18d nt!PspSystemThreadStartup+0x4a
05 8985fc7c 00000000 nt!KiThreadStartup+0x15
如果断点似乎无法设置,则可能是符号问题。 执行 .reload 命令重新加载符号来查看问题是否已解决。 在用户空间设置断点也是可能的,但首先执行 .reload /user 来解决这个问题。
还可以在命令中添加-p来限制给某某进程打断点,总之WinDbg非常强大,好好学习吧。
总结:
WinDbg其实就是一个调试器,只不过可以调试内核。对于调试用户层的代码来说和别的没什么区别只是可能更强大官方一点。而内核模式就最好还是双机调试。搭建内核调试环境是非常重要的,因为调试可以让我们更加深入的,一步一步的看完所有代码非常好用。至于WinDbg的使用方法,大家多尝试,熟练了就好了。可以看看这本书来熟悉WinDbg:http://www.windbg.info/download/doc/pdf/WinDbg_A_to_Z_bw2.pdf
Windows内核开发-5-(2)-内核模式调试的更多相关文章
- Windows内核开发-2-开始内核开发-2-内核开发入门
Windows内核开发-2-开始内核开发-2- 第一个驱动程序: 直接采用vs2019中的Empty WDM Driver 模块创建: 初始的项目文件夹中有一个Driver Files里面会有一个.i ...
- 64位内核开发第二讲.内核编程注意事项,以及UNICODE_STRING
目录 一丶驱动是如何运行的 1.服务注册驱动 二丶Ring3跟Ring0通讯的几种方式 1.IOCTRL_CODE 控制代码的几种IO 2.非控制 缓冲区的三种方式. 三丶Ring3跟Ring0开发区 ...
- 64位内核开发第六讲,Windbg调试ring3跟Ring0.一起调试
目录 驱动第六讲_Windbg连续调试Ring3.与Ring0 一丶Windbg连调试 驱动第六讲_Windbg连续调试Ring3.与Ring0 一丶Windbg连调试 有时候我们调试一个程序.可以使 ...
- Windows内核开发-4-内核编程基础
Windows内核开发-4-内核编程基础 这里会构建一个简单但是完整的驱动程序和一个客户端,部署内核执行一些平时user下无法执行的操作. 将通过以下内容进行讲解: 1 介绍 2 驱动初始化 3 Cr ...
- Bran的内核开发教程(bkerndev)-02 准备工作
准备工作 内核开发是编写代码以及调试各种系统组件的漫长过程.一开始这似乎是一个让人畏惧的任务,但是并不需要大量的工具集来编写自己的内核.这个内核开发教程主要涉及使用GRUB将内核加载到内存中.GR ...
- 内核用户模式调试支持(Dbgk)
简介 将详细分析Windows调试的内核模式接口.希望读者对C和通用NT内核体系结构和语义有一些基本的了解.此外,这并不是介绍什么是调试或如何编写调试器.它可以作为经验丰富的调试器编写人员或好奇的安全 ...
- Windows内核开发-3-内核编程基础
Windows内核开发-3-内核编程基础 这里会深入讲解kernel内核的API.结构体.和一些定义.考察代码在内核驱动中运行的机制.最后把所有知识合在一起写一个有用的驱动. 本章学习要点: 1:通用 ...
- Windows内核开发-6-内核机制 Kernel Mechanisms
Windows内核开发-6-内核机制 Kernel Mechanisms 一部分Windows的内核机制对于驱动开发很有帮助,还有一部分对于内核理解和调试也很有帮助. Interrupt Reques ...
- STM32F103 ucLinux开发之四(内核启动后的调试)
Stm32-uclinux启动后的调试 1. 修改__pfn_to_page使得能够启动 根据STM32F103 ucLinux开发之三(内核启动后不正常)的描述,内核无法启动是选择了平板内存模式后 ...
随机推荐
- 利用 V8 深入理解 JavaScript 设计
JavaScript 代码运行 以大家开发常用的 chrome 浏览器或 Node 举例,我们的 JavaScript 代码是通过 V8 运行的.但 V8 是怎么执行代码的呢?当我们输入 const ...
- excel VBA一个fuction同时执行多个正则表达式,实现方法
代码: Function zhengze3(ze1 As String, ze2 As String, Rng1 As Range, Rng2 As Range) Set regx1 = Cre ...
- Go基础语法0x01-数组
数组 1.Go数组简介 数组是Go语言编程中最常用的数据结构之一.顾名思义,数组就是指一系列同一类型数据的集合.数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数组的 ...
- 详解C++中的多态和虚函数
一.将子类赋值给父类 在C++中经常会出现数据类型的转换,比如 int-float等,这种转换的前提是编译器知道如何对数据进行取舍.类其实也是一种数据类型,也可以发生数据转换,但是这种转换只有在 子类 ...
- 从零玩转人脸识别之RGB人脸活体检测
从零玩转RGB人脸活体检测 前言 本期教程人脸识别第三方平台为虹软科技,本文章讲解的是人脸识别RGB活体追踪技术,免费的功能很多可以自行搭配,希望在你看完本章课程有所收获. ArcFace 离线SDK ...
- Docker:docker部署PXC-5.7.21(mysql5.7.21)集群搭建负载均衡实现双机热部署方案
单节点数据库弊端 大型互联网程序用户群体庞大,所以架构必须要特殊设计 单节点的数据库无法满足性能上的要求 单节点的数据库没有冗余设计,无法满足高可用 推荐Mysql集群部署方案 PXC (Percon ...
- Linux查找占用的端口,并杀死进程
我要使用4040端口,但是被其他的程序占用了 1. 查找占用的程序 netstat -apn | grep 4040 最后一项显示的是pid和对应的名称 2. 杀掉对应的进程,彻底杀死进程 kill ...
- vim下出现^M怎么解决
将window下的文本文件上传到linux上,在读取数据文件时,在每一行数据后会出现^M字符. 为什么会出现这种情况呢: 因为windows.linux.os系统的换行符标准不同: 先了解下概念, ...
- 所有的Java虚拟机必须实现在每个类或接口被Java程序 “ 首次主动使用 ” 时才初始化他们
原文:https://www.cnblogs.com/fanjie/p/6916784.html Java程序对类的使用方式可分为两种– 主动使用– 被动使用 被动使用以后再讲,这里说说什么是主动使用 ...
- 2012年第三届蓝桥杯C/C++程序设计本科B组省赛 取球博弈
2012年第三届蓝桥杯C/C++程序设计本科B组省赛 取球博弈 题目描述 **取球博弈 今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并 ...