windbg加载符号为什么找不到符号文件

Windbg 标签_51CTO技术博客
搜索推荐文章
搜索原创文章
搜索近期文章
&&&&【问题现象】explorer.exe应用程序报错。如图【原因说明】遇到explorer.exe应用程序报错,正常来讲explorer.exe不会无缘无故的报错,一般都是第三方DLL异常导致报错,然而如何快速的定位是哪个dll程序是一个问题。首先经常用到的定位报错DLL的方法就是使用进程工具PCHunter查看exp..
&&&&!wow64exts.sw..
&&&&Windbg相信windows开发的人都知道,有些人用的溜儿溜儿的,有个crash,直接拿这个工具一分析,就定位出来了。非常好用。以前有个同事,做sdk开发的,会各种命令。来北京后,还去过微软面试(不过当时是做外包,挣得也不少),问的问题就包括会不会用windbg定位问题。当时就会几个..
&&&&以我在notepad.exe中设置CreateFileW特定文件名断点为例。bpkernel32!CreateFileW"r$t1=poi(esp+4);as/mu$FileName$t1;.block{.if($sicmp(\"${$FileName}\",\"C:\\abc.txt\")!=0){.echoc:\\abc.txt}.else{.gc}}"bpkernel32!CreateFileW"r$t1=poi(esp+4);as/mu$FileName..
&&&&ctrl+breakbreaktheexcutingprogram1+tsourcemode1-tclosesourcemodebreakpointbpmodule_name(dll_name)!function_name(without())blshowthebreakpointsbcnumberdeletebreakpointe.g.bc1datadtstruct_nameaddress(Hex)-rxshowthecontentofaftertheaddressdependonthestructdefinit..
&&&&命令==========kk命令显示的是一定数量的栈帧,其中帧的数量是由.kframes命令来控制的,默认值是256。kp5显示调用栈中前5个函数以及他们的参数.kb5显示调用栈中前五个函数以及他们的前三个参数.kf5显示在调用栈中五个函数所使用的栈的大小.每个栈帧所占的空间使用量的计算方法是:将..
&&&&ProcDump与Procexp一样是Windows平台上的内部调试工具,Procexp采用图形界面体现系统整体及个别进程的性能信息,而ProcDump则与我们在Unix平台上使用的性能分析工具类似使用CLI命令行界面。
Procdump目前的版本号为3.04,可以从其Homepage上下载到该工具,该监控软件由MarkRussin..
加载模块映像信息:
lm[-v|-l|-k|-u|-f][-m模块名称]列出模块,详细|带加载符号|仅内核符号信息|仅用户符号信息|映像路径;模块名称匹配。
lmDDML模式:输出包含lmv的链接
!dlls按照加载序数列出所有加载的模块
-i按照初始化顺序
-l按照加载顺序
-m按照内存顺序
&&&&WinDBG命令输入ddNt!NtOpenProcess正常显示了,但有的执行不了,
一,WinDBG命令输入!process00提示错误
lkd&!process00
****NTACTIVEPROCESSDUMP****
NTsymbolsareincorrect,pleasefixsymbols
二,WinDBG命令输入dt_eprocess提示错误
lkd&dt_eprocess
&&&&好久没写博文了,呵呵。下边对昨晚的IE9故障做一个记录。
昨晚用IE9上cnbeta,只要一打开首页面IE就崩溃,打开文章页面没事。打开163和优酷任何页面也崩溃,其他网站倒是没事,本来不想修了,因为还装了Chrome、火狐等浏览器,但电脑里有个故障程序心里不爽,哈哈。
&&&&在蓝屏瞬间,系统会形成一个存储器转储文件&&死机瞬间的内存映像,通常是C:\WINDOWS\Minidmp目录下的DMP文件,它就是我们要找的救星,分析它就能查找到问题所在。
DMP文件需要使用MS提供的WinDbg工具来分析:第一步:安装winDbg,下载winsdk_web安装其中的Debugging..
&&&&本文详细的介绍了标准的Windows蓝屏故障的分析、处理流程。介绍了如何使用WinDbg工具来分析内核转储文件(Crashdump)以确定问题。在文末附带的记录了VMware服务错误的处理记录。
操作系统:Windows7EnterpriseX64SP1[Version6.1.7601]。
系统用途:这个机器安装的软件较多,一般..
&&页数 ( 1/3 )
Copyright&
版权所有 未经许可 请勿转载使用Windbg分析Windows蓝屏具体原因
用windows最郁闷的莫过于蓝屏了(BSOD,Blue Screen of Death)
对于那种在添加新硬件或安装新软件、新驱动后出现的蓝屏,只需把你之前的所作所为还原掉一般就能解决问题。但是对于那种找不到原因而且经常出现的莫名蓝屏(比如我所遇到的每天一蓝)就没办法了。
好在每次windows在临死之前都会留下些线索。如上图,最后5行就是将当前的内存状态转存(dump)到文件。
前提是你开启了内核转储(minidump):
右键 计算机 -& 属性 -& 高级系统设置
-& 高级选项卡 -& 启动和恢复 -&
小内核转储
根据默认设置,文件会保存到相关的设置路径。
虽然网上有些轻量级的dump分析工具,但分析结果非常不准。所以还是使用微软自家的权威分析。
[网上有相关快速教程,但用的是老版本的软件,新版本变化较大]
现在windows debugging tools SDK(又叫windows debugger)
&(由于无法保证连接长期有效,若失效,建议搜索
“Debugging Tools for Windows”)
PS,你可能还需要在这个页面下载符号库(不用急着下载),Windows Symbol
运行安装程序(这是一个微软的在线安装程序,所以请准备好网络)
根据以下说明:
The Debugging Tools are listed in two places on the Installation
Options screen in the Windows SDK Setup Wizard:
Select the&Debugging
Tools&option under
the&Common Utilities&if
you want the x86 version of Debugging Tools and you are installing
on an x86 computer. This option automatically detects the CPU
architecture of the computer on which you are installing the tools
and it is the fastest method of installing the tools.
Select the&Debugging
Tools&option under
the&Redistributable
Packages&to download all three versions of
Debugging Tools (x86, x64, Itanium).
选择相关选项
[更新] 安装软件界面发生变化了,不过变得更简单了,这里就不贴新图了
运行WinDbg,
首先需要载入符号库(symbol package):
File -& Symbol File Path...
可以使用你刚才下载过的符号库安装路径
也可以直接联网,用到什么再下什么,然后保存到本地:
SRV*d:\DebugSymbols*/download/symbols
我比较懒,直接用了联网方法(而且有些符号在下载包里没有,只有联网才会有)
最后就是打开dump文件了开始分析了
File -& Open Crash Dump
很容易就能发现是哪里出了问题以及是谁调用的
(本例中是一个网速检测软件和底层驱动冲突导致IRQ异常,BSOD)
我的更多文章:
( 09:03:05)
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。问问用WinDbg打开蓝屏产生的DMP文件显示的信息问题 - 看雪安全论坛
悬赏金: 10 &nbsp 状态:
注册日期: Oct 2012
现金: 41 Kx
获感谢文章数:0获会员感谢数:0
结帖率:100%
, 10:40:21
问问用WinDbg打开蓝屏产生的DMP文件显示的信息问题
首先是一个用VS写的能导致蓝屏的一个项目(此项目应该是在VS2010上写的),我是在WIN7&64位系统上用的VS2013+WDK把其编译出来sys文件。
然后打开虚拟机里调试模式下的XP系统,把SYS文件放进XP系统,用DriverMonitor加载并运行驱动,
然后蓝屏,产生DMP文件,把这DMP文件拿回到&这个64位系统,
之后我根据项目代码中,可能存在错误的地方修改了一下(在DriverEntry中)。然后再编译一次。
================================================
编译完我就用WinDbg打开DMP文件,(这时是第一次打开,符号包跟BSODCheck.pdb的路径也是设置好了的)&输入!analyze&-v&就出现&一段信息,但当时只留意到开始的几句。
Probably&caused&by&:&BSODCheck.sys&(&BSODCheck!DriverEntry+XXX&)大概这样的提示,
提示了是在DriverEntry中。
然后继续弹出其它信息,但我没有看到有CONTEXT等详细内容,于是就把DriverEntry中的代码,改回原来的样子(没修改前的样子)再编译一次,
然后再用WinDbg打开DMP文件,输入指令,就出现了如下信息(这次没有打开虚拟机里面的系统)
Use&!analyze&-v&to&get&detailed&debugging&information.
BugCheck&19,&{20,&937db8,&a050001}
***&ERROR:&Module&load&completed&but&symbols&could&not&be&loaded&for&BSODCheck.sys
Probably&caused&by&:&BSODCheck.sys&(&BSODCheck+1179&)
Followup:&MachineOwner
BSODCheck.sys&(&BSODCheck+1179&)&括号里显示的函数名不见了,上面好像也比之前多了句ERROR提示
之后我怎么&弄,都提示这个,当然输入了!analyze&-v都是得到不完整信息
STACK_COMMAND:&&kb
FOLLOWUP_IP:&
BSODCheck+1179
babc080&&&&&&push&&&&h
SYMBOL_STACK_INDEX:&&2
SYMBOL_NAME:&&BSODCheck+1179
FOLLOWUP_NAME:&&MachineOwner
MODULE_NAME:&BSODCheck
IMAGE_NAME:&&BSODCheck.sys
DEBUG_FLR_IMAGE_TIMESTAMP:&&538c46a1
FAILURE_BUCKET_ID:&&0x19_20_BSODCheck+1179
BUCKET_ID:&&0x19_20_BSODCheck+1179
Followup:&MachineOwner
而这段就是最后一段信息,没有出现详细的信息。而pdb文件的路径我一直都没有改变过的,每次用WinDbg打开DMP文件前,我都检查下,符号包路径好了没,PDB路径好了没。
然后想是不是符号包下载不全,就回到WinDbg打开Attach&to&a&Process随便附加到一个进程,然后在下面输入命令&.reload&/f&进行下载,从原来55M,
下到现在128M左右,再试,依旧是这些不完整信息。这样就没法根据详细信息处理蓝屏问题啊。
求教到底是哪里出错了?
注册日期: May 2014
现金: 127 Kx
获感谢文章数:0获会员感谢数:0
, 19:00:46
你需要的不是微软的pdb,而是你自己的BSODCheck.pdb。
注册日期: Oct 2011
现金: 40 Kx
获感谢文章数:1获会员感谢数:2
, 19:07:54
LZ先是产生了一个dmp文件,然后修改、编译后再去看原来的dmp,此时的pdb已经是新文件的pdb了,和老的dmp已经对不上了。
注册日期: Dec 2013
现金: 159 Kx
获感谢文章数:0获会员感谢数:0
, 22:44:58
你每一次编译一次pdb文件都会重新生成。你用最新的符号去调试之前的DMP文件,自然符号找不到。每次编译完应该对.sys文件和.pdb文件进行保存,这是一个习惯。
注册日期: Oct 2012
现金: 41 Kx
获感谢文章数:0获会员感谢数:0
, 07:31:09
最初由 ghostway发布
你每一次编译一次pdb文件都会重新生成。你用最新的符号去调试之前的DMP文件,自然符号找不到。每次编译完应该对.sys文件和.pdb文件进行保存,这是一个习惯。
这次我重新把项目重新编译,得出SYS文件,然后直接拿到虚拟机,运行SYS,蓝屏,然后生成DMP文件,生成后重启了虚拟机,进入系统把DMP文件取出来到我的64位系统中,然后用WinDbg-Open&Crash&Dump打开DMP文件分析,但这次出现的信息依然是没有CONTEXT
蓝屏时候的现场环境,这是为什么呢?CONTEXT不是一定会出来的吗?
还有一个问题就是,我运行SYS蓝屏后,虚拟机系统自动启动,但到了那个XP标题的读取界面,就一直卡住在那里,一动不动,必须要我再手动,RESTART&后才能进入系统,这又是为什么呢?
注册日期: Oct 2012
现金: 41 Kx
获感谢文章数:0获会员感谢数:0
, 07:44:34
*******************************************************************************
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*&&&&&&&&&&&&&&&&&&&&&&&&Bugcheck&Analysis&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*******************************************************************************
Use&!analyze&-v&to&get&detailed&debugging&information.
BugCheck&19,&{20,&,&,&a050007}
Probably&caused&by&:&BSODCheck.sys&(&BSODCheck!DriverEntry+59&)
Followup:&MachineOwner
kd&&!analyze&-v
*******************************************************************************
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*&&&&&&&&&&&&&&&&&&&&&&&&Bugcheck&Analysis&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*******************************************************************************
BAD_POOL_HEADER&(19)
The&pool&is&already&corrupt&at&the&time&of&the&current&request.
This&may&or&may&not&be&due&to&the&caller.
The&internal&pool&links&must&be&walked&to&figure&out&a&possible&cause&of
the&problem,&and&then&special&pool&applied&to&the&suspect&tags&or&the&driver
verifier&to&a&suspect&driver.
Arguments:
Arg1:&,&a&pool&block&header&size&is&corrupt.
Arg2:&,&The&pool&entry&we&were&looking&for&within&the&page.
Arg3:&,&The&next&pool&entry.
Arg4:&0a050007,&(reserved)
Debugging&Details:
------------------
BUGCHECK_STR:&&0x19_20
POOL_ADDRESS:&&&Nonpaged&pool
DEFAULT_BUCKET_ID:&&DRIVER_FAULT
PROCESS_NAME:&&System
LAST_CONTROL_TRANSFER:&&from&80545a86&to&804f9cb5
STACK_TEXT:&&
bacfbc10&20&&nt!KeBugCheckEx+0x1b
bacfbc60&bacf7b8&00004&nt!ExFreePoolWithTag+0x2a0
bacfbc7c&5acb10&00000&BSODCheck!DriverEntry+0x59&[e:\agptemp\temp\bsodcheck\bsodcheck.c&@&61]
bacfbd4c&00&nt!IopLoadDriver+0x66d
bacfbd74&00&89a328b8&nt!IopLoadUnloadDriver+0x45
bacfbdac&805cdcf4&00000&nt!ExpWorkerThread+0x100
bacfbddc&835b02&00000&nt!PspSystemThreadStartup+0x34
00&00000&nt!KiThreadStartup+0x16
STACK_COMMAND:&&kb
FOLLOWUP_IP:&
BSODCheck!DriverEntry+59&[e:\agptemp\temp\bsodcheck\bsodcheck.c&@&61]
bac0080&&&&&&push&&&&h
FAULTING_SOURCE_CODE:&&
&&&&57:&&&{
&&&&58:&&&&&memcpy(pwz_buf,theRegistryPath-&Buffer,theRegistryPath-&Length);
&&&&59:&&&&&ExFreePool(pwz_buf);
&&&&60:&&&}
&&&&61:&&&IsExitProcess(0x);
&&&&63:&&&return&STATUS_SUCCESS;
SYMBOL_STACK_INDEX:&&2
SYMBOL_NAME:&&BSODCheck!DriverEntry+59
FOLLOWUP_NAME:&&MachineOwner
MODULE_NAME:&BSODCheck
IMAGE_NAME:&&BSODCheck.sys
DEBUG_FLR_IMAGE_TIMESTAMP:&&
FAILURE_BUCKET_ID:&&0x19_20_BSODCheck!DriverEntry+59
BUCKET_ID:&&0x19_20_BSODCheck!DriverEntry+59
Followup:&MachineOwner
这是这次出来的提示,这应该是不完整的吧?
注册日期: May 2014
现金: 127 Kx
获感谢文章数:0获会员感谢数:0
, 12:37:53
这次是有正确pdb的,检查一下你的pwz_buf从哪里来的,free掉它把内存池给破坏掉了。
注册日期: Jan 2014
现金: 34 Kx
获感谢文章数:0获会员感谢数:0
, 15:20:11
Loading&Dump&File&[D:\Mini.dmp]
Mini&Kernel&Dump&File:&Only&registers&and&stack&trace&are&available
Symbol&search&path&is:&srv*F:\WorkingProject\kbinject\objchk_win7_x86\i386*/download/.sympath&srv*D:\WinDDK\.1\Debuggers\Symbols*/download/symbols
Executable&search&path&is:&
Windows&XP&Kernel&Version&2600&(Service&Pack&3)&MP&(2&procs)&Free&x86&compatible
Product:&WinNt,&suite:&TerminalServer&SingleUserTS
Built&by:&2600.xpsp.1
Machine&Name:
Kernel&base&=&0x804d8000&PsLoadedModuleList&=&0x
Debug&session&time:&Tue&Jun&10&17:00:57.203&2014&(UTC&+&8:00)
System&Uptime:&0&days&0:04:46.868
Loading&Kernel&Symbols
...............................................................
.............................................
Loading&User&Symbols
Loading&unloaded&module&list
*******************************************************************************
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*&&&&&&&&&&&&&&&&&&&&&&&&Bugcheck&Analysis&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*******************************************************************************
Use&!analyze&-v&to&get&detailed&debugging&information.
BugCheck&,&{69002e,&2,&1,&8054c10d}
Unable&to&load&image&genfs.sys,&Win32&error&0n2
***&WARNING:&Unable&to&verify&timestamp&for&genfs.sys
***&ERROR:&Module&load&completed&but&symbols&could&not&be&loaded&for&genfs.sys
Probably&caused&by&:&Pool_Corruption&(&nt!ExDeferredFreePool+107&)
Followup:&Pool_corruption
0:&kd&&!analyze&-v
*******************************************************************************
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*&&&&&&&&&&&&&&&&&&&&&&&&Bugcheck&Analysis&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*
*******************************************************************************
DRIVER_CORRUPTED_EXPOOL&(c5)
An&attempt&was&made&to&access&a&pageable&(or&completely&invalid)&address&at&an
interrupt&request&level&(IRQL)&that&is&too&high.&&This&is
caused&by&drivers&that&have&corrupted&the&system&pool.&&Run&the&driver
verifier&against&any&new&(or&suspect)&drivers,&and&if&that&doesn't&turn&up
the&culprit,&then&use&gflags&to&enable&special&pool.
Arguments:
Arg1:&0069002e,&memory&referenced
Arg2:&,&IRQL
Arg3:&,&value&0&=&read&operation,&1&=&write&operation
Arg4:&8054c10d,&address&which&referenced&memory
Debugging&Details:
------------------
BUGCHECK_STR:&&0xC5_2
CURRENT_IRQL:&&2
FAULTING_IP:&
nt!ExDeferredFreePool+107
3b&&&&&&&&&&&&mov&&&&&dword&ptr&[ebx],edi
CUSTOMER_CRASH_COUNT:&&21
DEFAULT_BUCKET_ID:&&COMMON_SYSTEM_FAULT
PROCESS_NAME:&&AlipaySecSvc.ex
LAST_CONTROL_TRANSFER:&&from&8054c75f&to&8054c10d
STACK_TEXT:&&
f4c75f&91d64&84f44008&nt!ExDeferredFreePool+0x107
f2e465&84f00&00ebf3c4&nt!ExFreePoolWithTag+0x47f
WARNING:&Stack&unwind&information&not&available.&Following&frames&may&be&wrong.
f20&00001&genfs+0x3465
fc92e4f4&01&nt!KiFastCallEntry+0xfc
00ebf4d4&00&x7c92e4f4
STACK_COMMAND:&&kb
FOLLOWUP_IP:&
nt!ExDeferredFreePool+107
3b&&&&&&&&&&&&mov&&&&&dword&ptr&[ebx],edi
SYMBOL_STACK_INDEX:&&0
SYMBOL_NAME:&&nt!ExDeferredFreePool+107
FOLLOWUP_NAME:&&Pool_corruption
IMAGE_NAME:&&Pool_Corruption
DEBUG_FLR_IMAGE_TIMESTAMP:&&0
MODULE_NAME:&Pool_Corruption
FAILURE_BUCKET_ID:&&0xC5_2_nt!ExDeferredFreePool+107
BUCKET_ID:&&0xC5_2_nt!ExDeferredFreePool+107
Followup:&Pool_corruption
0:&kd&&lmvm&Pool_Corruption
start&&&&end&&&&&&&&module&name
我用windbg分析dump文件,结果如上,哪位大神分析下
注册日期: Oct 2012
现金: 41 Kx
获感谢文章数:0获会员感谢数:0
, 23:11:56
最初由 cvrock发布
这次是有正确pdb的,检查一下你的pwz_buf从哪里来的,free掉它把内存池给破坏掉了。
就是说,出现这些信息就是正常了吗?&那为什么没出来CONTEXT&的信息?
注册日期: May 2014
现金: 127 Kx
获感谢文章数:0获会员感谢数:0
, 07:18:44
最初由 黑子控发布
就是说,出现这些信息就是正常了吗?&那为什么没出来CONTEXT&的信息?
都指向这么清晰了还想要多么详细?另外下面那个genfs又找不到pdb了。
您不可以发表主题
您不可以回复帖子
您不可以上传附件
您不可以编辑自己的帖子
论坛论坛启用
用户控制面板
会员在线状态
『看雪众测/众包』
『Android 安全』
『Android 开发』
『iOS安全』
『求助问答』
『经典问答』
『资料导航』
『软件调试逆向』
『密码学』
『编程技术』
『C32Asm』
『MDebug』
『安全工具开发』
『加壳与脱壳』
『CrackMe&ReverseMe』
『资源下载』
『WEB安全』
『漏洞分析』
『外文翻译』
『招聘专区』
『职业生涯』
『15PB培训』
『麦洛克菲培训』
『茶余饭后』
『安全资讯』
『论坛活动』
6)PEDIY Crackme竞赛2009
7)看雪十周年专版
8)腾讯公司2010软件安全竞赛
9)2011 Exploit Me竞赛
『图书项目版』
《加密与解密(第三版)》
《C++反汇编与逆向分析技术揭秘》
《Android软件安全与逆向分析》
『论坛版务』
所有时间均为北京时间, 现在的时间是 .
&&& 看雪学院()
| 提供带宽资源
|&微信公众帐号:如何配置windbg的symbol文件调试程序
[问题点数:20分,结帖人wxf54318]
如何配置windbg的symbol文件调试程序
[问题点数:20分,结帖人wxf54318]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2011年9月 C/C++大版内专家分月排行榜第二2011年4月 C/C++大版内专家分月排行榜第二2010年11月 C/C++大版内专家分月排行榜第二
2011年6月 C/C++大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。【转帖】使用WinDbg和虚拟机调试Windows驱动程序(很详细)
使用WinDbg和虚拟机调试Windows驱动程序
09:40本文来自:/zhg_tao
/suiyingjie/
/zhg_tao/blog/static//
/suiyingjie/archive//1053391.html
http://silverstr.ufies.org/lotr0/windbg-vmware.html
/support/ws3/doc/ws32_devices3.html
驱动调试攻略(WinDbg)
驱动调试是一个系统级调试方式,所以调试工具用WinDbg是最佳选择。驱动调试一般情况下,需要两台电脑进行。一台作为主机进行驱动调试,另一台作为目标机进行驱动安装。当然如果没有多余的电脑,我们可以安装VMware模拟系统调试(虚拟机)。只是对电脑的配置要求比较高。本文介绍使用WinDbg及WMware进行调试的具体设置及方法。这些资料在网络很难找到,笔者也是吸取了他人很多宝贵意见才完成的,供大家学习讨论。
VMware Support 中说,自 4.0.18.0 版本之后的 WinDbg 都支持了通过 pipe
来进行调试,不过微软对此并没有任何说明。所以,在VMware中虚拟被调试的系统,然后通过VMware虚拟一个com端口。使用这个虚拟的端口,就可以用
WinDbg 进行调试了。
具体步骤如下:
1. 安装和设置WinDbg,WMware
首先,请到微软官方网站
/whdc/devtools/debugging/default.mspx,下载最新版本的WinDbg工具,建议使用6.0以上版本的WinDbg做为调试工具。WMware也可以在网站上找到,当然使用高版本比较好。
安装过程比较简单,就不在此多做介绍。唯一要注意的是,安装完虚拟机后,请在VMware主菜单“VM”中选择“Install VM
Tools…”,完成系统驱动文件的安装。
安装完这两个软件后,请在VMware中安装跟你的电脑版本相同的操作系统。例如:你的电脑安装的是WindowsXP
Professional,那么最好在Vmware中安装相同版本。至少是相同的系统,Windows XP&& Windows
XP、Windows 2000&& Windows
2000。这样会在驱动调试过程中避免不必要的麻烦。笔者使用的操作系统为Windows XP Professional。
我们将使用电脑的COM1口最为调试口。
1.1设置 VMware 的虚拟com
1. 运行 VMware ,点击 "Edit virtual machine settings"
2. 点击 "Add..." 来运行 VMware 的 Hardware Wizard
3. 选择 "Serial Port",点 "下一步"
4. 选择 "Output to named pipe",点 "下一步"
5. 第一框里保持默认的 "//./pipe/com_1"
第二框里选"This end is the server."
第三框里选"The other end is an application."
选中 "Connect at power on"
然后点击 "Advanced&&"
6. 选中 "Yield CPU on poll"(VMware Support 中提到了这一点),然后点完成。
7. 这样就完成了虚拟com的设置。
8. 重新启动一下。
1.2设置 VMware 虚拟出来的 guest os
9. 编辑虚拟机中C盘根目录下的boot.ini文件。
在c:/下,可以找到boot.ini,可以用记事本打开它,或者命令行方式
C:/&attrib -s -h -r boot.ini
C:/&notepad boot.ini
我们需要在 guest os
的启动项上加些参数,才能够使用WinDbg调试它。我们可以在现有的行后面直接加参数,不过强烈推荐复制一个新行,在新行的后面加参数。这样在调试启动有问题的时候,我们可以方便的换回原来的启动方式。下面就是我改好的boot.ini。
在boot.ini文件中添加以下代码:
multi(0) disk(0) rdisk(0) partition(1) /WINDOWS="Microsoft Windows
XP Professional-Debug" /fastdetect /debugport=COM1
/baudrate=115200
10. 在 guest os 的设备管理器中把com1端口的速度也就是"每秒位数"项,设为和上面一样的115200。
打开vmware中winxp的设备管理器,选择端口(com1), 双击这个"com1",在弹出的对话框中。
1.3设置真实系统(主机)com
11. 回到我们的真实系统(主机)中,重复第10步。
1.4设置真实系统(主机)WinDbg
12. 设置WinDbg的快捷方式,及其运行参数:
我们需要告诉WinDbg通过pipe进行连接和连接的速度。
可以在命令提示符(cmd.exe)下加参数 -k com:port=//./pipe/com_1,baud=11520,pipe
运行WinDbg(VMware Support 中没有提到 baud=11520 这个参数,其实这是个比较重要的参数)。
更方便的方法是在桌面建立一个WinDbg的快捷方式,在该快捷方式的属性,"目标"框中,加上参数 -k
com:port=//./pipe/com_1,baud=11520,pipe
。这样运行这个快捷方式启动的WinDbg就完成了设置。参数的具体作用,可以参考 WinDbg 的帮助文件。
在快捷方式的属性中,将目标(Target)改为:
"C:/Program Files/Debugging Tools for Windows/windbg.exe" -b -k
com:pipe,port=//./pipe/com_1,resets=0
命令参数的意义:
-b:一旦主机目标机之间建立起连接,立刻中断目标机
-k:内核调试
Com:设置连接目标机的通信端口(此处为命名管道)和波特率(此处为115200)
-y:设置符号文件路径
13. 设置WinDbg参数
现在我们假设你的驱动代码放在D:/mydriver目录中;系统级Symbol文件存放在C:/WINDOWS/Symbols目录中,这些Symbol文件是从微软的网站上/download/symbols下载而来,这个网址是不可以用IE直接打开的,WinDbg&
File& Symbol File
Path...界面中选择Reload,WinDbg会自动帮你下载;驱动生成的Symbol文件存放在D:/mydriver/objchk_wxp_x86/i386目录中。
a) 设置驱动Symbol路径,WinDbg-&File-& Symbol
File Path...为
SRV*C:/WINDOWS/Symbols*/download/
D:/mydriver/objchk_wxp_x86/i386
b) 设置驱动源文件路径,WinDbg-&File-& Source
File Path…为D:/mydriver
c) 为了保险起见,我们同时设置系统变量。
My Computer -& Properties-& Advanced
Tab-& Enviroment Variables-&
Add._NT_DEBUG_BAUD_RATE=115200
_NT_SYMBOL_PATH=SRV*C:/WINDOWS/Symbols*/download/symbols
_NT_ALT_SYMBOL_PATH = D:/mydriver/objchk_wxp_x86/i386
_NT_SOURCE_PATH = D:/mydriver
启动VMware,将主机目录C:/WINDOWS/Symbols下的拷贝到虚拟机的相同位置。同时请把驱动编译后生成在D:/mydriver/objchk_wxp_x86/i386目录下的*.pdb、*.sys、*.map、*.exp、*.lib文件一并拷贝到两个系统的C:/WINDOWS/Symbols目录中。
15. 重新启动VMware,并选择如图所示。这个时候先不敲回车键。
16. 在主机中运行之前设置好的WinDbg快捷方式。直到在WinDbg命令窗口中出现“Waiting to
reconnect...”,此时打开VMware,敲回车键进入虚拟机。到这里所有的设置工作就全部完成了。
2.驱动安装及调试
这里其大家注意,由于我们目前用的是虚拟机,所以安装驱动程序的时候一定要把VMware设置到全屏状态。
编辑你要调试的源代码,在你需要调试的代码中添加硬断点。如果不添加硬断点,将没有办法进入所调试的程序中。具体方法如下:
在你需要调试的程序中加入以下代码:
extern "C" {
#include &wdm.h&
//或者是#include &winddk.h&
}//放在文件开头
DbgBreakPoint();//放在需要调试的地方
重新编译驱动程序,记住一定要更新把重新生成的*.pdb、*.sys、*.map、*.exp、*.lib文件一并拷贝到两个系统的C:/WINDOWS/Symbols目录中。
打开VMware,Ctrl+Alt+Enter进入虚拟机全屏模式。插入需要调试设备的硬件,笔者调试的目标设备为USB。当USB插入主机后,直接由VMware识别到这个USB设备,指定驱动位置,系统将会在你设置硬断点的地方停下来。这个时候你就可以回到WinDbg,进行单步调试了。你还可以在程序中添加软断点,“F9”或者“bp
MyApp!MyFunction”。
3.两台电脑调试说明
两台电脑调试跟借助VMware调试有所不同,不同之处有以下几个方面。
(1) 需要自己制作一条Null Modem Cable. 请参考以下电路。将两台电脑连接起来。
管脚信息说明:
9-Pin NULL Modem Cabling
3 2 Transmit Data
2 3 Receive Data
7 8 Request to Send
8 7 Clear to Send
6,1 4 Data Set Ready and Carrier Detect
5 5 Signal Ground
4 6,1 Data Terminal Ready
25-Pin NULL Modem Cabling
2 3 Transmit Data
3 2 Receive Data
4 5 Request to Send
5 4 Clear to Send
6 20 Data Set Ready and Carrier Detect
7 7 Signal Ground
20 6 Data Terminal Ready
(2)WinDbg快捷方式参数设置
"C:/Program Files/Debugging Tools for Windows/windbg.exe" -b -k
com:port=//./ com1,resets=0
//////////////////////////////////////////////////////////////////////////////////////
Windbg简明教程
09:10Windbg是Microsoft公司免费调试器调试集合中的GUI的调试器,支持Source和Assembly两种模
式的调试。Windbg不仅可以调试应用程序,还可以进行Kernel Debug(新版本对于XP+操作系统支持Live kernel
debug),同时结合Microsoft的Symbol
Server调试应用程序和Kernel非常得利。Windbg支持x86,IA64,AMD64。
Windbg下载地址:/whdc/devtools/debugging/default.mspx
下面我来说一下Windbg的基本用法:
由于Windbg是GUI调试器,所以在设置方面可以通过菜单,也可以通过命令。我只说明最方便的办法:),那请先打开Windbg吧
号路径设置,Ctrl+S在弹出的窗口中输入你的符号路径,路径的格式只要符合Windows操作系统路径格式即可,路径可以多个,中间以分号间隔,如:
d:/symbols/win2k3_en;个人感觉Windbg的强大功能之一在于Windbg会自动到Microsoft的服务器上下载符号表文件
(.dbg或.pdb,有时DLL和EXE也会下载),只要在符合表路径里做如下设置:srv*d:/symbolslocal*http:
///download/symbols,这样如果相关符号表在d:/symbolslocal目录没有找到的话,
Windbg会自动在Microsoft的Symbol
Servers上下载。如果你是调试自己的应用程序的话,建议你将自己应用程序的*.pdb文件的路径放在前面这样对Windbg来说查找起来比较快。
源文件路径设置:Ctrl+P在弹出的窗口里指定你的源代码文件的路径,路径格式只要符合Windows操作系统的格式即可,可以指定多个,中间以分号间隔。
可以将你的设置进行保存,File-&Save Workspace。
可以创建一个子进程进行调试,也可以对正在运行的程序进行调试,方法如下:Ctrl+E打开一个应用程序并可指定运行参数进行调试;F6从对话框中选择当前正在运行的进程调试。
对于调试子进程,通常Windbg会在应用程序运行之前中断,此时你可下一些想要的断点:
以Notepad.exe 为例,如果你还没有符号表文件的而又设置了MicrosoftSymbol
Servers的话,你得先等一下,因为Windbg会自己自动到Microsoft上下载相关的符号表,在命令提示符的位置如果没有出现0:
000&这个标记表示Windbg正在忙。
表达式格式:
无论在那条指定里都会涉及这个问题:数制,语法。Windbg支持C++和
MASM两个表达式格式,@@用于即时改变语法格式,即在MASM下使用@@指令来使用C++的语法解释器,反之亦然。Windbg数制的表示0x表示
16进制,0n表示10进制,0t表示8进制,0y表示2进制;Windbg默认数制为16进制,n指认用于设置数制;默认表达式语法是MASM,.
指令用于设置表达式语法解释器。本文均使用MASM为默认语法解释器。大小问题,通常如果不特别说明,Windbg对指令不区分大小
断点指令:BP,BM,BA,BL,BC,BD,BE
BP 在指定的地址设置断点
bp notepad!WinMain,在Notepad的WinMain函数处下断点。
点的位置可以用符号表示,也以直接使用地址及Windbg的Pseudo-Register(虚拟寄存器),如$exentry表示进程的入口点,可以使
用bp @$exentry在进程的入口点设置断点,对于Notepad当前入口点为,也可以直接 bp
,等效于bp notepad!WinMainCRTStartup.
BM 使用模式匹配设置断点,需要符号表支持
bm 值一提,在符号表合法的情况下(符号表中包含私有符号的时候),bm可能通过模式一次下多个断点,bm
mydriver!FastIo*指定可以将所有与FastIo*模式相匹配的函数下断点,如FastIoRead,FastIoWrite等。但是bm
需要full or export
symbols支持,Microsoft的提供的符号表不是都支持的,通常我们自己编译的程序的符号表(Windbg显示为private
pdb symbols)默认是支持的。
BA (Break on Access)
顾名思义,对内存访问下断点。对于在多核或多处理器调试的时候
很有用,对于调试多线程也很有用,应该说用处很多,比如对一个全局变量设置断点,ba
mydriver!gMonitoredDevices,如果如果你认为这个变量的值被莫名的修改了,相信通过BA设置的断点,你很快就能找到是谁修改
BL(List),BC(Clear),BE(Enable),BD(Disable)
这四个指令是分别用于列表,清除,开启和禁用断点,也是使用非常频繁的指令。
以上所提到的断点指令通过与J指令很容易形成条件断点。比如:
bp USER32!GetMessageW "r $t1=poi(esp+4);r $t2=poi(@$t1+4); j(@$t2 =
0x102 ) 'du @$t1+8 L2;gc';'gc'"
这个条件断点,截取WM_CHAR消息,并将字符(包括中文)显示出来。
条件断点的最简形式:bp Address "j (Condition) 'OptionalCommands'; 'gc'
Address是指令的地址,Condition是一个条件表达式,如果@eax=1,'OptionalCommands'是在断点被击中并且表达式成立时要执行的指令;gc指定是从一个条件断点返回,是不可少的一部分。
数据查看指令 d{a|b|c|d|D|f|p|q|u|w|W}
d{b|c|d|D|f|p|q}分别是显示:
byte&ASCII,
double-word&ASCII,double-word,double-precision,float,pointer-sized,quad-word数据;
DA用于显示ASCII,DU用于显示UNICODE;
BYB,BYD,显示binary和Byte及binary和DWORD
补充一个DV,用于查看本地变量用的
这些指令区分大小。
栈指令k[b|p|P|v]
这 四条指令显示的内容类似,但是每个指令都有特色,KB显示三个参数,Kp显示所有的参数,但需要Full Symbols或Private
PDBSymbols支持。KP与Kp相似,只是KP将参数换行显示了。Kv用于显示FPO和调用约定,KD,用于显示Stack的Dump,在跟踪栈时
比较有用。
这些指令区分大小。
KD显示的内容:
0012fbd0 0012fbf0
0012fbd4 77e2158f USER32!UserCallWinProc+0x18
0012fbd8 0016011e
0012fbe0 750a0c3f
0012fbec dcbaabcd
0012fbf0 0012fc2c
0012fbf4 77e1279c USER32!DefDlgProcWorker+0xbf
DGGuarder!MainDLGproc
[j:/mydriver/dgguarder2/dgguarder.c @ 350]
0012fbfc 0016011e
e0f626 USER32!__ClientLoadMenu+0x38
e0f635 USER32!__ClientLoadMenu+0x47
KP显示的内容:
ChildEBP RetAddr
0012fbd0 77e2158f DGGuarder!MainDLGproc(
struct HWND__ * hwnd = 0x0016011e,
unsigned int message = 0x30,
unsigned int wParam = 0x750a0c3f,
long lParam = 0)+0x227 [j:/mydriver/dgguarder2/dgguarder.c @
0012fbf0 77e1279c USER32!UserCallWinProc+0x18
e0b981 USER32!DefDlgProcWorker+0xbf
e140bb USER32!InternalCreateDialog+0x695
e1410f USER32!InternalDialogBox+0xaa
df41ec USER32!DialogBoxIndirectParamAorW+0x34
01cdc USER32!DialogBoxParamA+0x4a
08684 DGGuarder!WinMain(
struct HINSTANCE__ * hInstance = 0x,
struct HINSTANCE__ * hPrevInstance = 0x,
char * lpCmdLine = 0x "",
int nCmdShow = 10)+0x5c [j:/mydriver/dgguarder2/dgguarder.c @
0012ffc0 77e88989 DGGuarder!WinMainCRTStartup(void)+0x194
[f:/vs70builds/3077/vc/crtbld/crt/src/crt0.c @ 251]
KERNEL32!BaseProcessStart+0x3d
数据修改指令e{b|d|D|f|p|q|w}
请参见文档吧:)
反汇编指令u,uf
u @$exentry L10
0:001& u @$exentry L10
notepad!WinMainCRTStartup:
bec mov ebp,esp
aff push 0xff
8180001 push 0x1001888
d0650001 push 0x10065d0
a mov eax,fs:[]
mov fs:[],esp
c498 add esp,0xffffff98
5e8 mov [ebp-0x18],esp
5fc mov dword ptr [ebp-0x4],0x0
a02 push 0x2
0100644f ff call dword ptr [notepad!_imp____set_app_type
uf (Unassemble Function)指令对整个函数进行反汇编
uf GetLanguageCount
0:000& uf GetLanguageCount
DGGuarder!GetLanguageCount [j:/mydriver/dgguarder2/language.c @
54 bec mov ebp,esp
54 ecc0000000 sub esp,0xc0
54 dbd40ffffff lea edi,[ebp-0xc0]
54 0000000 mov ecx,0x30
54 cccccccc mov eax,0xcccccccc
54 00403c1c f3ab rep stosd
56 a00 push 0x0
56 8b44100 push 0x41b428
56 0b44100 push 0x41b420
56 00403c2a e8b1edffff call DGGuarder!ReadInt ()
56 c40c add esp,0xc
58 f pop edi
58 e pop esi
58 b pop ebx
58 c4c0000000 add esp,0xc0
58 bec cmp ebp,esp
58 00403c3d e85e0f0000 call DGGuarder!_RTC_CheckEsp
(00404ba0)
58 be5 mov esp,ebp
58 d pop ebp
跟踪指令T,TA,TB,TC,WT,P,PA,PC
T指令单步执行,在源码调试状态下,可指源码的一行,根据不同的选项也可以为一行ASM指令;
TA单步跟踪到指定地址,如果没有参数将运行到断点处。
TB执行到分支指令,分支指令包括calls, returns, jumps, counted loops, and while
TC执行到Call指令
WT Trace and Watch Data,一条强大指令,对执行流程做Profile,执行一下看看结果吧
P,PA,PC相信不用多做解释,大家也都明白了
源代码操作指令 .,lsf,lsc,ls,l,lsp
.指令打一个源文件,可以打开一个全路径的文件,也可以通过函数地址来打开并定位到源文件中函数的位置,如. &a myapp!main,.
j:/mydriver/mydriver.c
lsf指定一个源文件为当前源文件,使用lsc可显示当前指定的源文件ls可显示源文件的代码。Lsf可以使用全路径,如果源路径已经设置,也可以直接指定源文件名称。如lsf
mydriver.c,lsf j:/mydriver/mydriver.c
lsc显示当前源文件
ls显示当前源文件的代码,如ls 200显示第200行
l 用于设置源文件选项
lsp 设置源文件行在调试时显示范围比如,显示当前行的前50,后50,lsp 100
但通常使用Windbg时,可以直接用Ctrl+O来打开并查看源文件
寄存器指令 r
信大家对这个指令都很熟悉,在Windbg中r指令除了可以显示修改CPU寄存器之外,Pseudo-Register可使用这个命令来修改。对eax
操作,r eax 显示其值,r eax=2,修改其值;r $t2=10,修改Pseudo-Register的值,r
@$t2显示其值。
Search 指令 s,#
S 指令对内存区别进行查找,可用于查找数字,字符串,但不支持模式查找。s -d @esp L100
8187bc40,从esp指向的内存地址0x100个字节内查找 DWORD 8187bc40。查找字符串 s -a 0012ff40
L20 "Hello" 。s -sa 和 s -su 显示内存可打印的ASCII和Unicode字符串。
#指令可以查询汇编指令模式, # "call[ ]+esp" kernel32 L1000查找call esp 指令。
其他常用指令 lm,!peb,x,dt
lm 查看当前载入的模块
!peb 查看当前进程环境块(PEB)
x 查看模块的符号,如x mydriver!*FastIo*,显示所有与*FastIo*匹配的符号列表
dt 查看类型数据,还可用于查看模块类型的符号列表,如 dt dgguarder!_IMAGE_DOS_HEADER
从处查看_IMAGE_DOS_HEADER类型的数据
上下文的概念
Windbg下上下文的概念很重要,根据文档中说明有多种上下文概念,
Session Context,
Process Context
Register Context(其实也就是线程上下文)
Local Context(这个关系的本地如果解析本地变量的问题)
调 试Win32应用程序,Session Context和Process Context是确定的,主要是Register
Context,也即Thread Context,可以使用~指令来查看,改变当前的Thread Context
。~*显示所有线程列表,~xs用于切换上下文(x是数字),如:~1s,将上下文切换到1号线程。
.frame用来设置Local Context。
好了,基本的指令都已经列出了来了,Kernel
Debug现在先不写了,其实跟Win32也差不多。如果再有时间再写吧。本文对指令没有说的太细,详细说明见Windbg文档,希望见谅。
//////////////////////////////////////////////////////////////
WINDBG Script简易教程
08:56【文章标题】: WINDBG Script简易教程
【文章作者】: 笨笨雄
【【工具名称】: WINDBG
【下载地址】:
/whdc/devtools/debugging/installx86.mspx
【作者声明】: 希望更多人使用WINDBG,然后大概就能看到debugging tools for
windows的帮助文件的中文翻译了吧。花了 几天时间才在翻译软件的帮助下看完debugger
commands部分,痛苦死了。也找不到WINDBG的插件,还是WINDBG没插件功能?为了简
化调试过程,只有学习使用SCRIPT了,现在把这几天的经验跟大家分享。附件中所有代码经NOTEPAD,REGEDIT等调试,花了几小时,基本通
废话多了,现在是正文。WINDBG的指令比较多,还是英文的,所以我只挑了一部分经常会用到的,并通过实例去告诉大家那些指令的作用和格式。正如大多数高级语言教程一样,我们先来看看如何写一个HELLO
WORLD的程序。
如果使用.echo "HELLO WORLD"作为例程就太简单了,我希望介绍更多的指令。所以我在OD直接用汇编写了个程序:
;TITLE跟显示内容都在这个跟下一个PUSH
;我比较懒。。。就用一样的字符了
MOV EAX,OFFSET MESSAGEBOXW
先用EAX保存MESSAGEBOXW的指针,然后再CALL。这是为了你在任何一个程序下都能用使用这个SCRIPT。如果直接 CALL
MESSAGBOXW的指针,翻译成机器码是相对于当前位置的偏移,这样写出来的SCRIPT文件在这个程序能用,别的程序就不能用了。
机器码 6A 00 68 78 56 34 12 68 78 56 34 12 6A 00 b8 68 3d e2 77 ff
我虚拟机使用的是WIN 2000
连SP1都不是。。所以我不保证你的机器仍然能正常运行这个程序。为了能正常使用,你可以随便找一个程序,然后 BP
MESSAGEBOXW,中断之后当前的EIP就是了,把ff d0前面的68 3d e2
77换掉了就可以了。我的目的并不是介绍如何写一个兼 容性差的程序,重点是学会如何写SCRIPT。
准备工作做好了,在看代码之前,先解释一些指令:
$exentry伪寄存器,数值上等于EP
$t0-$t19,WINDBG为我们提供了20个自定义的伪寄存器
R指令能改变几乎所有寄存器的值,包括EAX等
.dvalloc [/b] size 申请内存空间,带/b
地址,可在指定地址申请空间,不带则自动分配,指定地址时不一定成功,暂时的经验指定地址越大越容易成功。
e* 地址 在指定内存中写入数据,EW 写入WORD,EB写入BYTE,ED写入DWORD
注意: EW 45会产生溢出错误,同理EB
123也是错的,正确的例子可见后面的代码
f 地址 L长度 BYTE
在长度的地址写入数据,你可以在示例中看到效果。同样BYTE的位置只能是BYTE,多于8位的数据都会造成溢出错误。
m 源地址 L源地址长度 目的地址 复制内存区域
d* 地址 显示地址中的数据,其中db的效果可在示例中看到。
.dvfree /d 地址 size 释放指定地址的内存,这里指定地址用的是/d要与 .dvalloc的/b相区别。
附件中helloworld.txt的代码:
---------------------------------------helloworld.txt--------------------------------
g $exentry
r $t0=00ff0000; $$ $t0:源内存基址
r $t2=@$ $$ $t2:目的内存基址
r $t1=@$t0; $$ $t1:当前指针
.dvalloc /b $t0 1000; $$在00b90000申请1000BYTE的内存空间
ew $t1 006A 0068
.echo "ew指令的效果"
r $t3 = @$t1 + 3; $$PUSH DWORD的机器码=68 DWORD
$$这里应该输入字符串的首址
r $t1 = @$t1 + 7; $$懒得计算,所以用$t3存起DWORD的指针
$$输入字符串的时候一起搞定
eb $t1 68 12 34
.echo "eb指令的效果"
r $t4 = @$t1 + 1; $$同上
r $t1 = @$t1 + 5
f $t1 l20 6A 00 b8 68 3d e2 77 ff d0
.echo "f指令的效果"
r $t1 = @$t1 + 9
r $t5 =$t1 - $t0 + $t2
ed $t3 $t5; $$ 添加字符串的指针回去
ed $t4 $t5
f $t1 l20 'h' 'e' 'l' 'l' 'o' ' ' 'w' 'o' 'r' 'l' 'd' '!' 00
$$ 把字符串写进内存中
m $t0 l30 $t2
r $ip=$t2; $$ 修改EIP
.dvfree /d $t0 1000; $$ 释放内存
---------------------------------------helloworld.txt完结的分割线--------------------------------
为了你的速度,请保证symbol
path为空,只有在你有源代码或者系统核心的时候它的存在才有意义,否则你会发现它会非常费时且毫无意义,尤其是你得连上网络下载symbol资源的时候。
使用SCRIPT文件的命令有4个"$&","$$&","$&&","$$&&",他们的区别就是有没有空格或者
换行符的限制。使用$$&&没有任何限制,这样可使代码更具可读性。要使用附件中的SCRIPT请使用$$&&指令。
例如你可以用下面指令访问在D盘下的helloworld.txt。
$$&&d:/helloworld.txt
如果你把helloworld.txt放在WINDBG的安装目录,那么你可以使用下面指令:
$$&&helloworld.txt
运行完helloworld.txt后你会发现报错了,因为我的代码覆盖了EP。通过上面的例子,我们能用SCRIPT做什么呢?在合适的时机,把没加密的IAT或者其他什么的,暂存到内存中,在脱壳完毕的时候再自动用正确的部分把加密部分覆盖掉。
也许在未来,也会遇到这样的需要,程序运行到某部分的时候,中断,然后运行我们自己的代码,运行完毕之后,我们需要返回到程序原来的流程。为此我把上面的SCRIPT修改了一下,写成BACKTOCODE.TXT。
--------------------------------------------backtocode.txt--------------------------------------
r $t0=00ff0000
r $t1=@$t0
r $t18=$$$ 用$t18暂存当前EIP,显然$ip=EIP
.dvalloc /b $t0 1000
ew $t1 006A 0068
r $t3 = @$t1 + 3
r $t1 = @$t1 + 7
eb $t1 68 12 34
r $t4 = @$t1 + 1
r $t1 = @$t1 + 5
f $t1 l20 6A 00 b8 68 3d e2 77 ff d0
r $t1 = @$t1 + 9
ed $t3 $t1
ed $t4 $t1
ba e1 $t1 ;$$ 内存运行断点,E代表运行1是长度,在E后面通常是1,断在最后一个指令后的第一个地址
f $t1 l20 'h' 'e' 'l' 'l' 'o' ' ' 'w' 'o' 'r' 'l' 'd' '!' 00
r $ip=$t0 ;$$ 在分配的内存中直接运行我们自己的代码
.dvfree /d $t0 1000
r $ip=$t18 ;$$ 把EIP设置为原来的
.$$ 当前命令行窗口清屏
$$ 单步步过
-------------------------------------------backtocode.txt结束-----------------------------------
为了anti anti
debug我们需要隐藏标题,虽然WINDBG本身有.wtitle指令,可是那个指令会把它后面的所有内容当作字符串输入,而且windbg+版本号是无论怎么改都会被默认添加到最后的。这样上面那个SCRIPT就有用了,就差CODE了。
为了anti anti
debug,每次DEBUG的时候,我们都要做一些准备工作,用SCRIPT文件,我们可以自动完成这些操作,下面是我DEBUG之前都会用到的SCRIPT文件
-----------------------------------------------start.txt----------------------------------------
r $t0 = 00
eb 7FFDF002 $t0 ;$$去除DEBUG标志
.pcmd -s ".if(eax& and
eax&){du eax};
.if(edx& and edx&){da
g $$$入口点
-------------------------------------------start.txt结束----------------------------------------
如你所见的,这有点少。没办法水平有限,而且写这篇文章的时候我才勉强说是学会用,还是那句重点是教会大家用WINDBG。WINDBG的初始断点并不是
入口点所以得自己用指令让它自动停在入口点,有的程序是有TLS表的,对着PE格式的介绍文章,写一个SCRIPT在有TLSCALLBACK的情况下自
动停在TLSCALLBACK入口是有可能的,你会在文章的最后部分得到相关指令的介绍。现在来说说START.TXT中没有注释的指令。
; 分号,多条命令的分隔符。从左到右运行。
下面例子中,对MESSAGEBOXW下断后运行,中断之后便会运行r $t0=esp+8指令
g;r $t0=esp+8
注意:如果你使用CRTL+BREAK快捷键在中断之前暂停调试也会导致r $t0=esp+8的运行。
.if(条件表达式){命令} 跟C语言中的用法一样。
.pcmd 不带参数则显示每条指令之后自动使用的指令。-s "命令" 设置命令。-c 清除命令。
da 以ASCII显示内存地址,du以UNICODE显示内存地址
在示例中,整条指令的效果表现为,每单步一个指令,便会当EAX,EDX指向的是一个合法地址的时候,便以ASCII和UNICODE的方式分别显示它的值,就象OD那样。如果熟悉ASCII和UNICODE字符集的范围还能设置仅当有效字符时才显示结果。
上传的附件 11.rar
在调试的过程中,有时我们希望自动化解决一些问题。例如调试使用了UnhandledExceptionFilter的SEH,我们需要自动修改
ZwQueryInformationProcess的返回值。或者对于某些API的ANTI
DEBUG,如果我们修改了输入参数,同样不能返回应该返
回的值。学破解不久,一下子要找用了UnhandledExceptionFilter的软件还真不容易,用别的API代替了。我用OD把NOTEPAD
修改一下,改名为TEST放在附件中。
流程MESSAGEBOXW,GETCOMMANDLINEW,MESSAGEBOXW输出COMMANDLINE,最后EXITPROCESS。
现在我要做的是改变GETCOMMANDLINEW的输出,和第二个MESSAGEBOXW的输入。现在让我们看看test2.txt
-------------------------------------------test2.txt-----------------------------------------------
g $exentry
bp messageboxw "r $t0=$t0+1;j($t0=2)'r $t1=poi(esp+8);f $t1 l4
bp getcommandlinew "g poi(esp);r $t1=eax+5;f $t1 l4 55;g"
------------------------------------------test2.txt完结---------------------------------------------
首先对相关指令作一些介绍
BP 地址或者函数名 "命令" 命令参数是可选的,存在的情况下,中断的同时会先运行那些命令。
J(条件表达式)'命令1';命令2 相当于.if但是又有点不同命令2只能是1个,后面所有命令会被忽略。
POI() 返回指针的指向位置的内容。
这里用了条件中断的方法实现,第一个条件中断指令用$t0作为计数器,第二次中断的时候变修改堆栈中指针指向位置的内存区域。注意到调用API的返回地址在ESP中,直接跳出去,然后修改EAX就可以达到修改函数输出参数的效果了。
这里提供第二种可行的方法,并且更有可扩展性,现在看看test.txt中的代码。
-------------------------------------------test.txt------------------------------------------------
g $exentry
bp messageboxw
bp getcommandlinew
bp exitprocess
.while (eip!=77e7b0bb){
.if($ip=77e116cc){
r $t0=$t0+1
.if($t0=2){
r $t1=poi(esp+8)
f $t1 l4 45
.if($ip=77e7c693){
g poi(esp)
r $t1=eax+5
f $t1 l4 55
.elsif($ip=77e7b0bb){
------------------------------------------test.txt完结----------------------------------------------
仍然先介绍一些指令:
.while(条件表达式){} 跟C语言中的一样,循环结构,直到条件表示式为真
.elsif(){} 跟前面的.if用法一样,它的作用如字面上意思,只是小心别拼错为ELSEIF
.break 跟C语言中的一样,跳出循环。
如果在条件为真的时候不用.break跳出循环就会出错,这点要注意。
这里构造了一个循环结构,并且通过对比EIP的方法来识别函数,同样地因为我的虚拟机是WIN 2000
连SP1都不是,所以我不肯定该地址在你的机器
中仍然可用。不过这里提供了一个思路,你可以用这个方法构造一个SCRIPT来加强WINDBG的功能,例如象OD一样中断的时候自动显示所有参数,并且
带上英文提示那是什么参数。同样地,我们可以做一个自动化分析SCRIPT,分析每个CALL中包含了什么API,并且列出输入和输出参数,CALL的深
度还指令数,并且自动生成报告文件,假如有人开发出这样一个SCRIPT,调试分析将会变得容易。WINDBG里面有个相似功能的指令。
自动跟踪并生成报告,几乎跟我上面说的一样。带/l参数的时候可以设置深度,不过很多时候,我们看到一个CALL并不知道里面究竟有多深,但是我们希望得到一些关于那个CALL的详细信息来判断是否值得跟进。这里有两个问题:
1 递归,那这个指令不知道运行多久。
2 大量NATIVE API调用,显然大多数情况下,我们并不关心。
比起1,2更加常见,/i参数是用来避开指定模块的,不会用,帮助文件里也没提。。。。希望有大大能答我这个问题
WINDBG提供了下面3个指令用于保存分析过程进文件,通过适当的开关可以过滤一些无意义的信息,使分析过程易于观看。
.logopen 文件路径
带/U参数则以UNICODE方式输入文本。重写整个文件,并记录当前命令窗口在使用该指令之后的所有内容。
.logclose 文件路径 停止记录并关闭文件。
.logappend 文件路径
带/U参数则以UNICODE方式写文件。记录当前命令窗口在使用该指令之后的所有内容,并添加进文件。
提到了功能强化,大家都知道OD里面有个命令是运行到RET处吧,在WINDBG中似乎没有这样的指令,类似的有PC,即运行到CALL。我写了一个SCRIPT来模拟OD中的那个指令。现在我们来看看goret.txt
-------------------------------------------goret.txt------------------------------------------------
.while(@$t0!=c3){
r $t0=by(eip)
.if(@$t0=c3){
-----------------------------------------goret.txt完结----------------------------------------------
这里是最后一个示例分析,所以除了解释上面的指令之外也给出一些有价值的指令
not 非 and或者& 与
hi() 取高16位 or或者^ 或
low() 取低16位 xor或者| 异或
by() 取低8位 gu 步出,不知道具体原理,有时会出错
wo() 取低16位 t 步入
mod或者% 模运算
这个SCRIPT使用了一个循环,通过EIP取得当前指令的机器码,低8位既为指令,然后把指令存进$t0作比较。C3是RET的机器码,等于则跳出循环,否则一直步过。
这个示例表明,我们可以在SCRIPT里分析每一条指令。我们可以在WINDBG中进行2次开发,动态将那些简单使用JMP+内存指针或者寄存器作为跳转
的乱序的程序重新排序,使花指令失效,并且实现自动清除垃圾指令,最后生成优化后的汇编代码文件。本论坛翻译区里的变形多态中的关于收缩器的理论已经为我
们奠定了理论基础。
你可能会需要用到反汇编指令
u 起始地址 l长度 L代表的不是地址长度而是指令的个数
---------------------------------后续讨论,用SCRIPT把WINDBG变成脱壳机------------------------------
在准备写这篇文章的时候,我又把DEBUGGER COMMANDS看了一次,发现了这个指令
.writemen filename range 将目标内存区域写进文件。RANGE的格式为 地址 l长度
我没试过L后面是否接受寄存器作为参数。也没实际测试过这个指令的具体操作是怎么样的,无论如何,有这个可能存在。当然我们也可以申请内存区域以程序的方式来完成这个工作,不过我希望它仅用SCRIPT完成。
假如这的确可行,可以通过下面指令组合来自动寻找文件头,当然也能确定文件大小。
$p 伪寄存器,它将返回前一次用d*指令所显示的内存的内容。
假设 02 03 04 05 06 07 08
我使用dd ,那么$p =
显然我们可以通过这个方法来访问内存。
dw 取一个WORD; dd取DWORD; dw取qword
能访问内存也代表说我们在调试程序中插入的代码也能跟SCRIPT通信,并且把一些SCRIPT无法完成的工作交给程序执行,然后把结果返回给SCRIPT。
假如l的参数无法通过寄存器来传递,只能依靠用户按照提示进行操作,那么我们有更简单的方法
.imgscan 它将返回所有模块MZ的地址和它的SIZE
----------------------------------这里给出一些可能的疑问和解答--------------------------------------
Q:在调试SCRIPT文件的时候,我该如何知道寄存器跟内存的变化?
A:我们可以用下面的指令来观察寄存器跟内存的变化
d* 用于显示内存,之前已经提到就不详细说明了
? 寄存器 显示寄存器的值,例如
? poi(esp); ? $t0
这将先显示ESP指向的值,然后显示$t0的值
除了可以使用.echo命令对显示参数作说明之前,也可以使用.printf作格式化输出,它的用法跟C语言中的printf是一样的
Q:我写的SCRIPT文件出错了,语法跟参数都没错,为什么我找不到出错原因?
A:有的指令要注意的,BA只能在进入程序区域之后才能用。.dvalloc申请过的内存,即使用.dvfree释放了,也无法在同样的位置再申请,可能是BUG。
*是一个注释命令,它后面所有的内容都会被当作字符
$$则是以分号为结束
.restart指令跟.wtitle指令,不知道为什么不能放在SCRIPT中使用。
还有就是@这个标记,这个标记是告诉WINDBG后面的是一个伪寄存器而不是程序里的某一个变量的符号。有的指令在没有@标记的时候会报错,例如.
while括号里的条件表达式,如果你用了伪寄存器,一定要在前面加上@否则一定报错。此外用帮助文件里的话来说,使用@,可以让SCRIPT文件运行得
更快,因为在解读这个代码的时候不需要先搜索一次SYMBOL记录。
Q:我能把功能模块化然后在其他SCRIPT文件中使用吗?
A:我已经测试过$$&&指令也能在SCRIPT里面使用
Q:我写的SCRIPT FILE能在64位系统中用吗?
A:如果你仅使用SCRIPT来实现功能,那么很可能与64位兼容。尽量使用伪寄存器。
$ip,$retreg,$csp在32位系统中分别表示EIP,EAX,ESP,而在64位系统中则表示RIP,RAX,RSP也分别对应Itanuim处理器中的相关寄存器。
通过函数名获取不同版本下的地址,可以通过下面代码:
$$第一个断点,断点ID为0
$$第二个断点,断点ID为1
r $t10 = $bp0; $$将第一个断点的地址转存$t10
r $t11 = $bp1; $$将第二个断点的地址转存$t11
bc *; $$清除所有断点。
这段代码运行之后MESSAGEBOXW的地址便存于$t10中,而$t11里面的则是getcommandlinew的地址。这里要说明,断点用完要释放,否则不好估计断点的ID,此外在内核模式中,最多只允许32个断点。
$peb和$teb返回当前进程的PEB和TEB地址,这里的翻译区有介绍如何仅通过PEB或者TEB判断当前操作系统类型
为不同系统准备不同代码
总算写完了。。。。再废话几句
WINDBG看起来很难用,是因为用的人不多。
即使没有插件功能,WINDBG SCRIPT的功能也已经很强大了。
如果大家都来做SCRIPT,调试分析难度会降低很多,新手也可以通过阅读SCRIPT
FILE来学习。搜索引擎使用得好的确可以学到很多,可惜这跟作
者的表达和使用引擎者的表达有关,很可能相同的内容,因为表达方式不同就查不到了。就象我学校的图书馆,在电脑搜索逆向工程是什么都找不到的,但是搜索加
密解密,却看到好几本书。
OD虽然好,始终是RING3的,SOFTICE似乎也已经停止开发了。希望大家都能加入WINDBG的行列
///////////////////////////////////////////////////////
WinDbg入门教程(1)-调试器的基础知识
09:22WinDbg 入门教程
在我的职业生涯中,我看到我们大多数都是使用Visual
Studio来进行调试,而不是用其它许多免费的调试器。你可能有许多理由来使用这样的调试器,比如,在你家里的机器上没装开发环境,但是一个程序一次次的崩溃。其实根据堆栈的dump就可以判断出IE的崩溃是否是由于一个第三方的插件。
对于WinDbg,我目前为止还没有发现很好的快速入门的教程。这篇文章结合实例讨论了WinDbg的使用。我首先假设你熟悉调试的基本概念:stepping
in, stepping out,断点以及远程调试的基本概念。
注意,这本来是座位一个入门的文档,你可以阅读并且开始使用WinDbg.
如果对于特定的命令有疑问,请查阅WinDbg的文档。你可以在任何微软提供的调试器中使用这篇文章中提到的命令,比如在VS的命令行窗口中。
这篇文章是基于WinDbg 6.3.
这仅仅是一系列关于调试技术的文章中的第一篇。在下一篇文章中,我会解释如何针对调试器编写扩展DLL.
调试器一览
下面大概介绍了你可以从微软网站上下载到的调试器:
· KD-内核调试器。你可以用它来调试蓝屏一类的系统问题。如果是开发设备驱动程序是少不了它的。
· CDB-命令行调试器。这是一个命令行程序
· NTSD-NT调试器。这是一个用户模式调试器,可以用来调试用户模式应用程序。它实际上是一个CDB的windows
· WinDbg-用一个漂亮的UI包装了KD和NTSD。WinDbg即可以调试内核模式,也可以调试用户模式程序。
VS.net-使用同KD和NTSD相同的调试引擎,并且相比于同样用于调试目的的WinDbg,提供了功能更丰富的界面。
调试器之间的比较
Visual Studio .NET
内核模式调试
用户模式调试
非托管调试
附加到进程
从进程分离
WinDbg实际上包装了NTSD和KD并且提供了一个更好用的用户界面。它也提供了命令行开关,比如最小化启动(-m),附加到一PID指定的进程(-p)以及自动打开崩溃文件(-z)。它支持三种类型的命令。
· Regular commands(比如: k) 用来调试进程
· Dot commands(比如:.sympath)用来控制调试器
· Extension commands(比如:
!handle)-这些命令属于可以用来添加到WinDbg的自定义命令;它们用扩展DLL的输出函数来实现。
PDB文件指的是链接器生成程序数据库文件(Program database
files)。私有的PDB文件包括私有以及公有符号,源代码行号,类型,局部以及全局变量。公有的PDB文件不包含类型,局部变量以及源代码行号信息。
WinDbg入门教程(2)-各种调试场景介绍
09:26调试场景
使用WinDbg进行远程调试是很容易的,而且有很多种可行的方法。在下文中,’调试服务器’指的是运行在你所要调试的远程机器上的调试器。’调试客户端’指的是控制当前会话的调试器。
· 使用调试器:你需要CDB, NTSD或者WinDbg已经安装在远程机器上。WinDbg客户端可以连接到CDB,
NTSD或者WinDbg中的任何一个作为服务器,反之亦然。在客户端和服务器直接可以选择TCP或者命名管道作为通讯协议。
o 在服务器端的启动过程:
& WinDbg &server npipe:pipe=pipename(注:可以允许多个客户端连或
& 从WinDbg内部: .server npipe:pipe=pipename(注,连接单个客户端)
你可以用多种协议开启不同的服务会话。并且可用密码来保护一个会话。
o 从客户端连接:
& WinDbg -remote npipe:server=Server,
pipe=PipeName[,password=Password]
& 从WinDbg内部: File-&Connect to Remote Session: for
connection string, enter npipe:server=Server, pipe=PipeName
[,password=Password]
· 使用Remote.exe:
Remote.exe使用命名管道作为通讯的方式。如果你使用的是一个命令行接口的程序,比如KD,CDB或者NTSD。你可以使用remote.exe来远程调试。注意:使用@q(不是q)来退出客户端,不用关掉服务端。
o 要启动一个服务端:
& Remote.exe /s “cdp &p &pid&”
o 从客户端连接:
& Remote.exe /c &machinename&
上面的test1是我们所选择的命名管道的名字。
服务端会显示那个客户端从那个服务器连接以及执行过的命令。你可以使用‘qq’命令来退出服务端;或者使用File-&Exit来退出客户端。另外,如果要进行远程调试,你必须属于远程机器的”Debugger
User”组并且服务器必须允许远程连接。
在WinDbg的文档的”Enabling Postmorten
Debugging”部分对此有很详细的讨论。简而言之,你可以把WinDbg设置成默认的即时调试器,命令就是:Windbg
&I。这个命令实际上是把注册表中 HKLM/Software/Microsoft/Windows
NT/CurrentVersion/AeDebug的键值设置成WinDbg。如果要把WinDbg设置成为默认的托管调试器,你需要显示设置如下的注册表键值:
HKLM/Software/Microsoft/.NETFramework/DbgJITDebugLaunchSetting 设置成
HKLM/Software/Microsoft/.NETFramework/DbgManagedDebugger
设置成Windbg.(注意其中的启动参数设置)
通过JIT的设置,当一个应用程序在不是调试的状态下抛出了未处理的异常之时,WinDbg就会被启动。
所有这些调试器均支持在AMD64和IA64上的64位调试环境。
托管应用程序的调试
WinDbg 6.3以后的版本支持在Widbey(VS2005和.net 2.0的内部开发代号) .net
CLR托管调试。在文档中针对托管调试有很好的讨论。需要注意的是,对于托管程序来说,没有刚才所说的PDB(译注:托管代码实际上也是有PDB的,但是这个PDB实际上记录了C#代码和IL代码的对应关系以及相关的一些信息)的概念,因为所有的程序都是编译成为ILASM。调试器通过CLR来查询所需的附加信息。
有几点需要注意:
你只能在托段函数的代码被执行过至少一次之后才能设置断点。只有这样它才能被编译成汇编代码。记住以下的几点:
· 关于函数的地址的复杂化以及对应的断点设置:
o CLR有可能丢弃已经编译好的代码,所以函数的入口地址有可能改变。
同样的代码有可能被多次编译,如果多个应用程序域没有共享这段代码的话。如果你设置了一个断点,它就会被设置在当前线程(译注:CLR的逻辑线程)所在的应用程序域内。
o 泛型的特殊实例可能导致同一个函数有不同的地址。.
· 数据存储布局的复杂化以及对应的数据检查:
CLR可能会在运行的时候任意改变数据的存储布局,所以一个结构体成员的偏移量可能会被改变掉.
(译注:实际上是在一个类型被加载的时候决定的数据布局,之后是不会改变的。)
一个类型的信息是在第一次使用的时候被加载,所以你可能不能够查看一个数据成员如果它还没有被使用过.
· 调试器命令的复杂化
当跟踪托管代码的时候,你会需要穿越大段的CLR自己的代码比如JIT编译器的代码,原因可能是你第一次进入一个函数,或者是你在托管和非托管代码之间进行切换。
调试Windows服务
使用WinDbg,你可以像调试其它应用程序那样调试Windows服务程序。即可以通过附加进程的方法启动Windows服务,也可以把WinDbg当作一个即时调试器,并且在代码中调用DbgBreakPoint
或者 DebugBreak,或者在x86机器上加入一条int 3汇编指令。
一个调试器会得到两次的异常通知-第一次在应用程序有机会处理异常之前(‘first chance
exception’);如果应用程序没有处理这个异常,这时候调试器就会有机会来处理异常(‘second-chance
exception’)。如果调试器没有处理二次机会的异常,应用程序就会退出。
.lastevent或者,!analyze &v命令会给你显示异常的记录以及异常抛出所在函数的堆栈跟踪信息。
你也可以使用 .exr, .cxr以及
.ecxr命令来显示异常和上下文记录。同时需要注意的是,你也可以改变first-chance的处理选项。对应的命令就是: sxe,
sxd, sxn和sxi。
能否请教一个问题:
我的Windbg不能设置断点,重新加载Symbols文件的时候也总是有几个加载失败,Symbols file
path的设置是:
SRV*c:/symbols*/download/symbols。
类似的环境变量也设置了,可是怎么弄都不行,又没有什么好的建议?
用;将Symbols file path分开,例如:
d:/dev/SRV*c:/symbols*/download/symbols
WinDbg 入门指导(3)-WinDbg中常用的功能以及设置
09:34WinDbg的功能
调试器扩展DLL
所谓的扩展指的是一些DLL,你可以用在调试器内调用并且执行一些自定义的命令。这些DLL必须实现一些特定的函数,并且要满足一些需求,这样才能被认为是一个扩展DLL。在下一篇文章内,我们将会了解到怎样写出一个扩展DLL。所谓的bang(!)命令就是从你的扩展DLL内执行的命令。注意这些DLL是被加载到调试器的进程空间内。
内存转储文件
你可以使用转储功能来取得一个进程的快照信息。一个mini-dump通常比较小,除非你使用了全内存的minidump(.dump
/mf)。通常能够转储句柄信息也是很有用的,命令是
.dump/mfh。一个小型转储通常包含了所有的线程的堆栈以及一个已被加载的模块的列表。一个全转储包含了更多的信息,比如进程的堆。
崩溃转储分析
如果你的windows系统当机,那么它就会在一个文件中转储物理内存中的数据,以及所有的进程信息。可以通过Control Panel
-&System-&Advanced-&’Startup
Recovery’来配置。你也可以首先把WinDbg配置成为一个即时调试器,然后就可以取得任意一个非正常终止的进程的转储(.dump)。注意,从转储文件中分析出代码中的bug往往是一个复杂费力的过程。
使用以下的步骤来分析一个转储文件:
1) 在WinDbg内,通过 File-&’Open Crash Dump’,
指向转储文件。
2) WinDgb会给你显示应用程序崩溃之时所执行的指令。
正确设置你的符号文件目录和源代码目录。如果你不能够匹配正确的符号文件,想要弄清楚程序的逻辑是非常困难的。如果你能够把符号文件匹配到正确版本的源代码,这是就应该很容易分析出Bug原因。注意,私有符号文件含有行号信息并且会盲目的显示你源代码中的对应行而不进行任何的检查;如果你的源码版本不对,那么你就不能够看到匹配汇编代码的正确源码。如果你仅仅有公有的符号文件,你会看到最后一个被调用的函数(栈上的)。
注意调试驱动或者托管代码是与此有很大不同的。参考《The Windows 2000 Device Driver
Book》来获得调试设备驱动的技术。
WinDbg的常用设置
符号文件与文件夹
如果想更有效的调试,你需要符号文件。符号文件可以是老式的COFF格式或者就是PDB格式。PDB就是程序数据库文件并且包含了公有符号。这些调试器内,你可以使用一系列的地址来让调试器寻找已经加载的二进制文件的符号。
操作系统的符号文件一般存储在%SYSTEMDIR%Symbols目录。驱动程序的符号文件(.DBG或.PDB)一般存储在和驱动文件(.sys
文件)相同的目录下。私有符号文件包含的信息包括:函数,局部以及全局变量,以及用来把汇编代码和源代码关联起来的行号信息;对于客户来说,符号文件一半是公有的-这些文件仅仅包括公有成员。
你可以通过File-Symbol File Path来设置符号文件目录,或者使用
.sympath命令。如果想要添加到网络上符号文件的引用,添加以下的内容到你的 .sympath
SRV*downstream_store*/download/symbols
使用的命令就是:
SRV*c:/tmp*/download/symbols
C:/tmp就是download_store,所需要的符号文件会被下载存储至此。注意这个符号服务器仅仅开放了公有的符号文件。
当调试器把一个二进制文件(DLL或exe)的时候,他会检查比如文件名,时间戳以及校验值。如果你有符号信息,你就可以在调用栈上看到函数名和他们的参数。如果二进制文件和PDB文件都来自于你自己的应用程序,你就可以看到比如私有函数,局部变量以及类型这类额外的信息。
源代码路径
你可以通过File-&Source File
Path来设置源码路径,或者使用.srcpath命令。如果你设置了代码的路径,当你调试的时候,调试器会通过PDB文件的行号信息来显示相匹配的源代码。
断点,跟踪
· 通过bp命令或者工具栏上的断点图片来设置软断点。
· 通过代码比如DbgBreakPoint() 或者 KdBreakPoint()来设置硬断点。
· 在扩展DLL中使用跟踪函数DbgPrint, KdPrint, OutputDebugString
来把输出显示在WinDbg的输出窗口中。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 windbg符号路径设置 的文章

 

随机推荐