1) 基础篇是讲理论的,先跳过去,看不到代码运行的效果要去记代码是一个痛苦的事情。这里先跳入探索篇。其实今天的确也很痛苦,这作者对驱动开发的编译与调试环境介绍得太模糊了,我是各种尝试,对这个环境的搭建还是不够理想,这里稍微做下笔记。
2)概念:普通运用程序开发在R3,而内核开发在R0,R0是最高特权等级。内核空间不同于普通的程序代码空间,独享4GB寻址过程,内核空间被所有的运用程序共享,一旦内存程序崩溃,系统将崩溃,导致蓝屏或者重启。
3) 开发与调试方案:基于上述的概念,调试内核程序是一个很要小心的事情。为了避免造成不必要的麻烦,采用的是虚拟机调试。搭建一个虚拟机,将虚拟机系统作为一个客户端运行程序,利用管道技术,使用windbg来调试整个系统。下面主要记录下搭建这么一个调试环境的过程,在摸索期间,也看到有的教程在本物理机安装驱动并且用DebugView查看内核级程序的输出信息,初步了解这只是一个输出功能,而不能算一个调试手段,暂时无视之。
4) 下载WDK内核开发开发包,我下载的是7600版本(已经集成了windbg,安装的时候选择完全安装)。下载VMware,我的是9.02。然后再下载一个xp镜像,你要用win7就下载win7。
5)安装虚拟机,安装WDK。接下来是创建管道,以及把虚拟机设置成调试模式启动:
a)打开WMware,不启动虚拟机电源开关,打开虚拟机设置,选择“添加”按钮,在出现的“添加硬件”向导中选择“串行端口”,点击“继续”,选择“输出到命名管道”,点击“完成”。此时在虚拟机设置选项卡可以看到添加了一个串行端口。
b)观察添加的串行端口是“串行端口2”还是“串行端口1”,一般网上都没提这点,而我虚拟机有点怪,是“串行端口2”,这里要注意,需要修改右侧“使用命名管道”项:把名称改为对于数值,串口2就改成“\\.\pipe\com_2”,第二项不动,第三项改为“另一端为运行程序”,再把下面的I/O模式给勾上。
c) 启动虚拟机,进入系统盘,找到boot.ini,去掉只读属性,打开,添加调试启动模式:
“multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect /debug /debugport=com2 /baudrate=115200”
d) 右键“我的电脑”,进入设备管理器,选择COM端口:
要注意:这里的COM与刚刚虚拟机上建立的串行端口要对应,我是串行端口2,则这里选择COM2。
双击它,在“端口设置”选项卡中,将“每秒位数”设置为“115200”。
e)重启虚拟机,可以看到调戏启动项出来了,选择它进入系统:
f)回到物理机,建立任意目录,我是“C:\symbols”,开打windbg,打开“文件”->“符号文件路径”,输入如下串:“SRV*你设置的符号路径*http://msdl.microsoft.com/download/symbols”
g)关闭windbg,找到windbg路径,建立一个快捷方式,剪切到桌面,修改它的属性,在原来的目标串后面添加如下命令行参数:
“-b -k com:port=\\.\pipe\com_2,baud=115200,pipe”
注意:“\\.\pipe\com_2”为管道名称,自行对应修改
6)到这,虚拟机和windbg的配置就完成了,接下来build一个驱动来调试一下:
a)建立任意目录作为工程目录,我的是“D:\mydriver”
b)新建一个记事本为你,输入如下C代码:
1 #include <ntddk.h>
2
3 //提供一个Unload函数值是为了让这个程序能动态卸载,方便调试
4 VOID DriverUnload(PDRIVER_OBJECT driver)
5 {
6 //打印一句话
7 DbgPrint("first: Our driver is unloading...\r\n");
8 }
9
10 //DriverEntry,入口函数。相当于main
11 NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
12 {
13 __asm int 3;
14 //这里只输出一句话
15 DbgPrint("first: Hello,my salary!");
16 //设置一个卸载函数,便于这个函数的退出
17 driver->DriverUnload = DriverUnload;
18 return STATUS_SUCCESS;
19 }
20
修改此文件名为first.c,具体意义不必理会,值注意一句话,这里的“__asm int 3”为中断指令,为了调试时用。
c)新建记事本文件,输入如下语句:
1 #下边这行指定生成驱动名字DDK_HelloWorld.sys
2 TARGETNAME=first
3
4 #下边这行指定生成文件的类型DRIVER指驱动
5 TARGETTYPE=DRIVER
6
7 #下边这行指定生成驱动所在的路径\SYS\DDK_HelloWorld.sys
8 TARGETPATH=SYS
9
10 #下边这行指定相关头文件所在目录路径
11 INCLUDES=$(BASEDIR)\inc;\
12 $(BASEDIR)\inc\wxp;\
13
14 ##上边必空一行D:\WINDDK\3790.1830 等价$(BASEDIR)
15 #下边这行指定驱动源代码*.cpp或者*.c
16 SOURCES=first.c
修改此文件名为Sources(没有文件后缀名)。上面的赋值注意变通,主要有驱动名字,以及源代码文件的指定
d)新建记事本文件,输入如下语句:
1 # 此文件 一般情况下只有一行 并且不需要修改 不能有前导空格
2 !INCLUDE $(NTMAKEENV)\makefile.def
修改此文件名为makefile(没有文件后缀名)。这个文件估计也是给nmake使用的
e)准备工作完成,从开始菜单进入WDK的“Build Environment”->“windows xp”,这里将看到两个选项,一个是“x86 Checked Build Environment”,另一个是“x86 Free Build Environment”,前者相当于VC的debug,后者相当于release。选择前者。进入命令行模式
f)使用cd命令进入工程目录,开始build驱动项目,我的是“D:\mydriver”
1 d:
2 cd mydriver
3 build
g)build完成后将看到输出:
这里看到了一个错误,提示在21行。其实这个不是错误,只是一个警告,可以看到提示:编译了3个文件,生成了一个可执行文件。可以在右下角查看View Warnings,因为这个不是马上就会弹出警告信息的,如果看到是灰色的,可以先点击上面那一个选项:Check New
可以看到下图:
可见,这里的确是Warning(两个Warning = 一个error?我汗颜),既然是这样,那么就先不管它,要我现在看也不知道是什么警告。
到工程目录的sys\i386下,可以看到生成了2个文件,first.sys就是生成的驱动文件
7) 编译结束了,剩下的就是试着调试,打开虚拟机,选择调试启动项启动它(这里会卡一会,因为等待调试程序连接,不用管,直接切到物理机上来)。
8)使用桌面的快捷方式打开windbg,打开以后将看到:
命名管道已经打开,正在等待连接。
9)当连接上以后将看到:
这个窗口,最上面的是代码区,左下角是命令行输入已经对应输出窗口,右边是虚拟机目前的寄存器状态,这些窗口可以在view菜单项设置是否开启,我已经对他们排过版了。
10)现在可以看到,输出了一条自动中断指令int 3,回到虚拟机会发现整个系统已经被中断,鼠标按键完全没有反应。在命令行输入指令“g”让虚拟机继续跑动,在物理机将刚刚编译完成的first.sys驱动文件,以及驱动安装软件InstDrv.exe(这个软件之前没提,网上应该有很多资源下载)复制到虚拟机桌面,打开InstDrv.exe安装驱动并运行:
运行以后发现虚拟机再次假死,这是因为驱动文件代码中的int 3中断起了作用,回到物理机,发现:
输出了一个中断指令,这时可以在view选项卡选择Dissassemby开启反汇编窗口查看一下情况:
一切,之前熟悉的身影都冒出来了。
11)现在可以一路按F10单步运行下去,这里和C类似,F8和F11是步入,F11步出,F7运行到游标处。到这里初步的调试环境搭建,以及调试效果就出来了,以下是单步到驱动程序退出,然后回到虚拟机中卸载驱动后的输出状况:
以及: