HelloWorld驱动的准备、运行和调试
0x00 目的
在虚拟机内部编写驱动并加载驱动,简单的helloworld打印。基于Win11 64位主机,Win 7 X86虚拟机双机调试环境对驱动程序进行调试,对驱动下断点进行控制。
环境主机为win11 x64,虚拟机win7 x86
使用windbg进行双击调试,使用vs2010和ddk7.1。
环境请搜索自行搭建,并不是很难\~
今天要做的事,应该是通往驱动大门的第一步。过程可能会出现奇奇怪怪的问题,一定要多耐心尝试!这个东西折磨了我三天。所以非常有幸能把我的经验分享给大家,让大家少走弯路。
0x01 必备软件
DDK7.1、vs2010、DebugView、DriverMonitor或者KMDmanager需要被安装。
0x02 编写helloworld驱动
1.示例代码
#include <ntddk.h>
// 退出driver
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint(" the driver unloaded successfully! \n");
}
// driver的入口
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING reg_path)
{
DbgPrint("ok, congratulation ,the driver has loaded successfully!\n");
if(NULL != pDriverObject){
pDriverObject->DriverUnload = DriverUnload;
}
return STATUS_SUCCESS;
}
我们要将上面这个代码保存为helloworld.c
文件。
!INCLUDE $(NTMAKEENV)\makefile.def
将上面这个文件保存makefile
文件。注意不要有前导空格,只要一行,也不要进行任何修改。
#下面这行的意思是指定生成驱动名为HelloWorld.sys
TARGETNAME=HelloWorld
#下面这行的意思是指定生成文件的类型DRIVER,也就是驱动
TARGETTYPE=DRIVER
#下面这行指定生成驱动所在的路径\SYS\HelloWorld.sys
TARGETPATH=SYS
#下面这行指定相关头文件所在目录路径
INCLUDES=$(BASEDIR)\inc;\
$(BASEDIR)\inc\wxp;\
##上边必空一行H:\WINDDK3790(DDK目录) 等价$(BASEDIR)
#下面这行指定驱动源代码*.cpp或者*.c
SOURCES=HelloWorld.c\
将上面这些代码保存为Sources
文件,同样不要进行修改。
文件准备好之后是如下的样子。
2.Build it!
如图,在开始菜单中,找到WDK的文件夹,然后Build Environment,接着Windows 7,如果是64位选择x64的,32位选择x86的。注意要右键用管理员权限运行。
小tips:x86
是32位是因为像8086的86之类的,86代表初代
所以x86
代表32位而不是x32代表32位,hhhh
接着我们使用cd
命令,将目标目录调整到我们刚才存放三个文件夹的路径下面。我这里存放的路径是C:\demo
。然后输入build
命令,就开始build了。<i>这里可能会遇到一些报错,需要自己排查代码有没有在复制粘贴的过程中有一些符号出问题。</i>
完成之后的效果是这样的:
3.给我们的驱动签名
现在我们在开始的菜单栏里搜索Visual Studio Command Prompt
,然后使用管理员权限打开,效果如下。
接下来我们要给我们的驱动进行签名,如果没有签名,系统是不认你的驱动的喔。
接着我们使用cd
命令,首先到达你存放代码的目录。我这边还是C:\demo
。不过在build之后,真正的驱动在C:\demo\sys\i386
,如果是64位就可能是...\sys\amd64
了。
对于我的情况,就是cd
到C:\demo\sys\i386
。
首先输入命令,生成cer证书文件:
makecert -r -pe -ss Ctcloud -n CN=Ctcloud.com(Test) xxx.cer
然后输入命令,对sys文件进行签名:
Signtool sign /a /v /s Ctcloud /n Ctcloud.com(Test) /t http://timestamp.verisign.com/scripts/timestamp.dll xxx.sys
Ctcloud
、Ctcloud.com(Test)
以后我们可以自己修改。
xxx.cer
中的xxx
是我们自己可以修改的,是证书名称。
——————————————————————————
xxx.sys
的xxx
也是可以自己修改的,是我们要签名的文件名,注意签名的时候要像刚才一样,
用命令cd
到文件的目录下。
(如果是cat文件,则把后缀改为cat其他命令一样。)
0x03 运行HelloWorld
1.注册并启动
我们使用KMDManger,注意用管理员权限打开,因为我注册过了我就直接点Run了。没注册过的时候,按照Register -> Run -> Stop -> Unregister
的操作顺序试试,如果没有报错都是Success那就可以继续往下了。
//如果用的是DriverMonitor,在file中导入之后点击`start …`和`stop …`效果是一样的
2.观察
打开debugview,注意用管理员权限打开。然后再次run和stop,就可以看到输出。
这个过程可能会busy一会,耐心等待,如果等太久还不正常,那就重启吧。
0x04 调试HelloWorld
首先我们stop我们的驱动HelloWorld,然后在windbg 上方栏目点击debug然后选中break进行点击,进而输入命令 bp HelloWorld
,将HelloWorld作为断点。这个时候可能会提示失败,但是不要灰心,我们直接在Manger或者Monitor启动我们的驱动HelloWorld,这个时候就会进入单步调试了。
以下是一些单步调试中常用的命令及其作用:
p:单步执行。p加变量的话则是打印变量内容。
d:查看指定地址范围的内存内容。例如:d 0x1000 0x2000,查看从地址0x1000到0x2000的内存内容。
u:以汇编指令的形式查看指定地址处的代码。例如:u 0x401000,以汇编指令的形式查看地址0x401000处的代码。
t:查看当前线程的调用栈信息。
k:查看当前进程的调用栈信息。
r:查看或修改寄存器的值。例如:r eax,查看eax寄存器的值;r eax=0,将eax寄存器的值设置为0。
g:运行程序,直到遇到下一个断点或异常。
poi:以指定类型的形式查看指定地址处的内存内容。例如:poi 0x1000 l4,以32位整数的形式查看地址0x1000处的内存内容。
ln:查找指定地址所在的源代码行号。例如:ln 0x401000,查找地址0x401000所在的源代码行号。
dv 或 du 命令:查看局部变量或者内存地址中的数据。
r 命令:显示所有寄存器的值。
bp 命令:设置断点,可以通过地址、符号名、函数名等方式设置。
bl 命令:列出当前所有的断点信息。
ba 命令:列出所有类型的断点信息。
tcf 命令:终止程序执行。
!analyze 命令:分析程序崩溃的原因。
lm 命令:列出当前加载的所有模块信息。
!dbgprint:可以查看dbgprint的内容
要以汇编指令的形式查看代码,可以使用u命令。
如果要在u命令中指定汇编指令的数量,可以在命令后面添加一个数字。
例如,要以汇编指令的形式查看地址0x401000处的后10条指令,
可以使用命令u 0x401000 L10。
0x05 尾声
这篇文章的分享就到这里,有什么问题和不对的地方欢迎指出和一起讨论!谢谢\~