今天拿到《天书夜读 从汇编到Windows内核编程》
顺便就配一下windbg + Vmware 双机调试的环境,下面是从网上找到的一篇文章,拿来主义了,呵呵:)
最后配置完后,小试了一把,感觉就是不一样啊,呵呵,可以直接调试Windows,你不输g命令,它就死在那里,动都不动,感觉真是爽!!!!
R0代码逆向学习向导------开发调试环境
一边逆向一边提高开发水平,两者就都上去了
这个环境的搭建网上的教程泛滥了,不过很多应付,这里我来个全面的。这里主要侧重于通过Vmware和Windbg双机调试的。
准备工具:
• WindowsDDK7600.16385.1
• DbgView
• Winobj
• MSDN
• InstDrv
VC++或者masm32
•
开发环境配置:
(1) VC++
但凡写过点C程序的都知道这是什么,我也不说什么了。用这个编译器写驱动程序,实际上好多人现在都是把他作为一个编辑工具(我也是^-^)。网上有配置VC来开发调试驱动的教程,我就不说了,我还是习惯用WDK来编译。
下面简单说下开发过程:
下载好WDK,安装之
装好VC(废话)
建工程写代码
选择WDK编译环境,build之
上面的过程简略下,具体的看后面的教程。
(2) masm
有的人习惯用asm来写驱动,那么这个环境其实也很简单。
我按我习惯说下:
下载masmplus,安装之(其他 的比如Radasm、BTasm都可以的)
下载KmdKit18(MASM32开发内核驱动绝佳搭档)(俄罗斯大牛搞的)
写代码直接编译链接之
调试环境搭建:
(一)windbg
Windbg本身可以直接从微软的网站上下载
下载地址:http://www.microsoft.com/whdc/devtools/debugging/default.mspx
Windbg的设置其实主要是关于调试符号的设置,没有符号你会很不爽,会忽视掉许多细节,因此调试符号之于Windbg是非常重要的.
1.系统调试符号的设置
首先找个空间足够的位置,XP sp2的调试符号完整一点大概需要1G的空间~~
比如我是在D盘,建立一个MyLocalSymbols文件夹,用来存放系统的符号文件.
然后你可以从微软的网站上下载相应的调试符号包(大要180M~200M大小),要根据你虚拟机中的相应系统版本来下载,安装到MyLocalSymbols文件夹下.
当然,不安装符号包的话也可以设置成调试时自动从网上下载(即使你安装了符号包,有部分内容还是要到网上下载),具体怎么设置稍后讲.
不过我比较喜欢一次搞完,免得每次用的时候都要等它到网上下载比较慢~~
2.自己的调试符号的设置
再建一个文件夹,用于存放我们自己编译出来的驱动的符号文件.单独存放,不要跟系统的混到一起.
我这里就仍在D盘建立一个MySysSymbols文件夹,用于存放自己的符号文件.
然后给这个文件夹创建一个快捷方式,把它放到C:/Documents and Settings/你的用户名/SendTo文件夹下.
这样,以后编译完驱动以后,直接在符号文件上右击->发送到"MySysSymbols"就可以了,很方便~~
3.环境变量的设置
如果你想Windbg启动时自动识别符号路径的设置的话,我们就来建立一个环境变量
在"我的电脑"上右击,"属性"->"高级"->"环境变量",然后我们给当前用记新建一个名为_NT_SYMBOL_PATH的环境变量
值为 :
D:/MyLocalSymbols;D:/MySysSymbols;SRV*D:/MyLocalSymbols*http://msdl.microsoft.com/download/symbols
这样设置以后,系统的调试符号就在D:/MyLocalSymbols下,而我们自己驱动的调试符号就在D:/MySysSymbols下
当符号文件不匹配时,Windbg会自动连网从http://msdl.microsoft.com/download/symbols下载符号文件到D:/MyLocalSymbols,下次再用到时就不用下载了
设置好保存就可以了,修改环境变量需要重新启动系统才能生效~
到这里我再说一点,当你用了一段时间之后,常用的符号文件基本上就全有了,不想等,也可以用一些方法让Windbg马上下载符号文件
直接打一些正确的但是当前符号包中不正确或不匹配的符号名称可以"刺激"Windbg马上到网上下载,我为了节约时间就是这么干的.比如打dt nt!_KPCR,如果你的内核文件TimeDataStamp不匹配(内核等几个核心文件由于更新经常会这样)使得Windbg无法正确显示此符号,它就会马上乖乖地到网上把整个符号文件下载回来~~
在调试符号基本全了以后(调试时基本不再出现Windbg再连网下载符号文件的情况),建议把环境变量中联网的部分去掉。以我的为例,就是设置成 D:/MyLocalSymbols;D:/MySysSymbols
这样就断了它连网下载的念想,否则你一旦打错个符号,它还是会很负责地上网查找、下载,结果还是找不到,浪费很多时间~~
如果确实某个符号找不到需要临时上网找,那么执行下面命令就可以了
.sympath+ SRV*D:/MyLocalSymbols*http://msdl.microsoft.com/download/symbols
这样就重新恢复了Windbg上网下载符号的能力
(二)Vmware
Vmware的相关设置
1.编辑Vmware设置,添加一个串口设备.
首先我们要添加一个串口设备.打开你的虚拟机,选择“编辑虚拟机设置”
然后"Add...(添加)"->"Serial Port(串口)"->"Output to named pipe(输出到命名管道)"一路Next
名称就用默认的"//./pipe/com_1",这个其实对应于你的串口名称com1,用别的名字当然也可以,不过后面要对应
第二行选择"This end is the server"
第三行选择"The other end is an application"
同时把下面的"Connect at power on(打开电源时连接)"
请见下图:
好了,这回串口设备有了.下面进行相关设置
2.设置串口波特率
启动虚拟机中的OS,进入系统,打开设备管理器选项,这时就看到刚才添加的串口com1了
双击com1设备进入属性设置,在"端口设置"选项卡中选择"每秒位数"也就是波特率为115200
(据说Windbg可以自动适应波特率,没尝试过,因此还是设置一下吧)
3.修改boot.ini(如果是Vista以上就不是修改boot.ini了,需要别的修改方式)
这一步准确讲是添加DEBUG启动模式,对于Win2003及以前的系统,可以通过修改boot.ini来实现
对于Vista,Server2008,Win7等就得用bcdedit来编辑启动设置了
有需要的可以搜索"Windbg内核调试之一 Vista Boot Config设置"来查找那篇文章
我的GuestOS是WinXP Sp2,所以采用boot.ini的方法
打开C盘,把隐藏文件显示出来,去掉boot.ini的只读属性,双击打开来
通常你只会看到一个启动选项,我们复制一个,在后面加上 /debug /debugport=com1 /baudrate=115200
注意修改时间timeout,不要为0或太短,否则你连选择的机会都没有~~
贴个图,不会就照图中来,红线框住的部分是新加的
如果你不愿新增加,直接编辑原来那个也可以,不过还是推荐新加一个好~
然后你可以往虚拟机中放一些测试驱动常用的工具,比如DebugView,InstDrv等等
这时关于虚拟机部分就设置完成了,可以把当前状态保存一个快照,以后如果哪个驱动把系统搞崩溃再也起不来了,恢复一下就OK了
4.建立双机调试快捷方式
在桌面建立一个Windbg的快捷方式命名为“双机调试”,然后编辑其属性,把“目标”后面加上
-k com:port=//./pipe/com_1,baud=115200,pipe
比如我的电脑上,完整的应该是这个样子:
"C:/Program Files/Debugging Tools for Windows (x86)/windbg.exe" -b -k com:port=//./pipe/com_1,baud=115200,pipe
好了,一切设置就绪,来体验一下~~
重新启动虚拟机中的系统,在启动菜单时选择有“启用调试程序”的那一项,回车确认
然后把虚拟机最小化,回到桌面双击刚才建好的“双机调试”快捷方式,如果没有什么意外的话,稍等一下就会看到:
Connected to Windows XP 2600 x86 compatible target,ptr64 FALSE
Kernel Debugger connection established.
这就表示已经连接成功了,接下来会显示一下符号路径,内核基址等信息。
此时按下Ctrl+Break,就会中断下来,命令输入窗口变为可用状态,可以输入各种命令了~~
如果需要进入系统之后才加载驱动的话,可以等系统启动完毕后再中断,输入断点命令.这取决于你驱动的加载时机
(三)调试
先说点命令:
1.基本调试控制
运行程序(Run): 快捷键:F5 命令:g
单步步入(Step In): 快捷键:F8 命令:p
单步步过(Step Over): 快捷键:F10
运行到光标所在行: 快捷键:F7
执行到返回:gu
执行到指定地址:g [Address]
重新运行调试程序: 快捷键:Ctrl+Shift+F5(这个对驱动一般用不到)
2.断点
断点之于调试当然是非常重要的
常用命令:
bp [Address]or[Symbol] 在指定地址下断
可以使用地址或符号,如
bp 80561259(Windbg默认使用16进制)
bp MyDriver!GetKernelPath
bp MyDriver!GetKernelPath+0x12
bp [Address] /p eprocess 仅当当前进程为eprocess时才中断
这个很常用,比如你bp nt!NtTerminateProcess,但是只想在某一进程触发此断点时才断下来,那就加上这个参数吧,因为内核中的代码是各个进程共用的,所以此命令很实用
bp [Address] /t ethread 仅当当前线程为ethread时才中断,用法跟/p参数类似
bu [Address]or[Symbol] 下一个未解析的断点(就是说这个断点需要延迟解析)
这个也很常用,比如我们的驱动名为MyDriver.sys,那么在驱动加载之前下断bu MyDriver!DriverEntry,
然后加载这个驱动时就可以断在驱动入口,并且这个是不需要调试符号支持的
bl 列出所有断点,L=List
bc[id] 清除断点,c=Clear,id是bl查看时的断点编号
bd[id] 禁用断点,d=Disable,id即断点编号
be[id] 启用断点,e=Enable,id为断点编号
3.查看和修改数据
调试中不可避免的要查看和修改数据
查看内存:
db/dw/dd/dq [Address] 字节/字/双字/四字方式查看数据
da/du [Address] ASCII字符串/Unicode字符串方式查看指定地址
其它常用的如查看结构
dt nt!_EPROCESS
dt nt!_EPROCESS 89330da0 (把0x89330da0作为对象指针)
修改内存:
eb/ew/ed/eq/ef/ep Address [Values]
字节/字/双字/四字/浮点数/指针/
ea/eu/eza/ezu Address [Values]
ASCII字符串/Unicode字符串/以NULL结尾的ASCII字符串/以NULL结尾的Unicode字符串
搜索内存:
s -[b/w/d/q/a/u] Range Target
搜索字节/字/双字/四字/ASCII字符串/Unicode字符串
4.寄存器
在用Windbg调试时可以Alt+4直接调出寄存器窗口,然后拖放到合适的位置就可以。
要修改呢就直接双击相应的项就可以了。
把命令的方式也说一下,比较简单:
r 显示所有寄存器的值
r eax 显示eax的值
r eax=1 修改eax的值为1
5.辅助命令
!process 显示当前进程信息
!process 0 0 显示当前所有进程(会有僵尸进程)
!process 1f4 显示pid为1f4的进程信息,后面也可以跟eprocess的值
!thread 显示当前线程信息
!thread
!process 1f4 显示tid为768的线程信息,后面也可以跟ethread的值
栈相关:
k 显示调用栈
kb 显示ebp和前3个参数
kp 以函数调用形式显示栈
以上就是常用的命令了~~~
来个简单的实践过程,步骤如下:
1.编译好你的驱动,假设名为ShowSSDT.sys,并把驱动符号文件ShowSSDT.pdb发送到MySysSymbols文件夹下(之前设定的自己的调试符号文件夹)
2.启动虚拟机,选择调试方式进入系统
3.迅速打开“双机调试”,建立调试连接,详细过程第二节讲过了
4.等待虚拟机中系统启动完毕(不等也行,反正下断要在驱动加载之前就行了)
5.在Windbg中按下Ctrl+Break,输入bu My.sys!DriverEntry,回车确认,然后输入g命令继续执行
6.把My.sys拖到虚拟机中,在虚拟机系统中启动InstDrv,加载此驱动
7.回到Windbg窗口,如果一切正常的话,你会看到已经中断在My.sys的入口代码处了
接下来,要单步还是要下断点、要继续执行什么的,就全由你来作主了~~