Windebug 专题
查找资料的常用网站,分享给大家
http://www.debuginfo.com/articles/easywindbg.html
http://blogs.msdn.com/b/debuggingtoolbox/
http://bbs.cracktool.com/thread-12631-1-2.html
http://analyze-v.com/?p=716
http://msdn.microsoft.com/zh-cn/magazine/hh148143.aspx
---------------------
windbg-windbg环境
安装与配置 windbg 的 symbol (符号)
第一步 下载WinDBG
请通过此链接下载Web安装版的Windows SDK:
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b&displaylang=en
并在安装时清除所有组件的安装复选,并勾选“Debugging Tools for Windows”选项前的复选框进行安装。
另外,也可以通过在以下链接下载以前版本的windbg工具:
http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
http://msdn.microsoft.com/zh-cn/windows/hardware/gg463016中文路径
win8:http://msdn.microsoft.com/zh-cn/windows/hardware/bg127147,再直接选
获取独立的调试工具(通过 Windows 8.1 SDK)
(仅英文)
您将需要检查是否有 WinDBG 更新版本,因为该小组似乎具有相当紧凑的发布日程安排,并且每隔几个月就会发布更新版本。
下载对应的symbol包:
XPSP3的:http://msdl.microsoft.com/download/symbols/packages/windowsxp/WindowsXP-KB936929-SP3-x86-symbols-full-ENU.exe
其它系统:http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx#d(要下载retail版本,不要下checked)
下完了解包到C:\WINDOWS\Symbols里(当然你也可以换任意位置),然后WINDBG里符号路径可以这样设置:C:\WINDOWS\Symbols;
SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols
第二步 双击下载的文件安装 windbg .安装时注意记住安装到那里了.
第三步 windbg 访问符号需要两个文件(SYMSRV.DLL 和 SYMSTORE.EXE)所以添加主 path 环境变量中它们的路径进去,即:你的 windbg 安装目录.
操作方法:在桌面我的电脑点右键--属性--高级--环境变量,在系统变量列表框中找到 path 双击,在变量值最后面加一个分号再把你的安装目录写上.点确定.
这一步是告诉 windbg 那两个文件放在什么地方.
第四步 新建一个环境变量_NT_SYMBOL_PATH 值为: SRV*c:\mysymbol* http://msdl.microsoft.com/download/symbols
操作方法:桌面我的电脑点右键--属性--高级--环境变量 ,点击新建,把上面的变量名和变量值填上.这一步的意思是说告诉 windbg ,我的符号文件存放在c:\mysymbol 中(当然其实里面什么也没有,甚至这个文件夹也不存在,不过没关系,系统找不到的话会给你创建一个,并在上面的网址中去帮你下载符号文件放在里面)
第五步 运行 windbg 打开一个exe文件或者附加到一个进程里去, 你会看到 Symbol search path is: SRV*c:\mysymbol* http://msdl.microsoft.com/download/symbols
打开c盘看到有一个新目录 mysymbol,里面有 windbg 新下载的文件.
这样就差不多了,测试一下。选“内核调试-本地内核调试”,输入dt _EPROCESS,如果能列出EPROCESS结构则说明成功了。
还有一点要说,如果想使用用户态的符号,要再加上一句C:\WINDOWS\Symbols\dll;,如果安装了360,还要关闭360的自我保护(单纯地退出360是不行的),可以在“木马防火墙-设置-保护360产品”下关闭,接着本地内核调试,要先输入.reload(不reload无法使用用户符号),如果出现以下字样就说明成功了(不关闭360自我保护会失败):
lkd> .reload
Connected to Windows XP 2600 x86 compatible target at (Mon Nov 1 09:36:58.439 2010 (GMT+8)), ptr64 FALSE
Loading Kernel Symbols
...............................................................
................................................................
...
Loading User Symbols
......................................
Loading unloaded module list
................
再来测试一下,输入u user32!ValidateHwnd(注:ValidateHwnd是user32.dll里一个未导出的函数),应该可以看到类似下面的输出:
lkd> u user32!ValidateHwnd
USER32!ValidateHwnd:
77d184e0 64a118000000 mov eax,dword ptr fs:[00000018h]
77d184e6 85c9 test ecx,ecx
77d184e8 740c je USER32!ValidateHwnd+0x19 (77d184f6)
77d184ea 3b88f4060000 cmp ecx,dword ptr [eax+6F4h]
77d184f0 0f84c6090100 je USER32!ValidateHwnd+0x12 (77d28ebc)
77d184f6 b201 mov dl,1
77d184f8 eb26 jmp USER32!HMValidateHandle (77d18520)
77d184fa 90 nop
这样内核符号和用户符号就都能用了~
windbg-.symfix、.srcPath、.srcnoisy、log文件(符号文件、源文件、log文件)
symfix
.symfix命令自动将符号路径设置来指向Microsoft 符号存储。
比如,我原来设置的symbol file path为:
那么使用了.symfix之后:
0:000> .symfix
No downstream store given, using C:\Program Files\Debugging Tools for Windows (x86)\sym
这时symbol file path为:
我们发现,系统强制把Microsoft 符号存储的路径覆盖了原有的路径,那么,要使用追加,请使用.symfix+,把原有的路径设回去再保存,再调用.symfix+
0:000> .symfix+
No downstream store given, using C:\Program Files\Debugging Tools for Windows (x86)\sym
这时symbol file path为:
我们注意到,每次都有提示
No downstream store given, using C:\Program Files\Debugging Tools for Windows (x86)\sym
这意思是我们没有指定下载符号的路径,默认使用调试器安装目录下的 sym 子目录,
那么怎么自己加目录呢,比如,我想把符号下载存储到
C:\MyLocalSymbols这个路径,我们可以这样使用它:把原有的路径设回去再保存,再调用.symfix+ C:\MyLocalSymbols
0:000> .symfix+ C:\MyLocalSymbols
后面不再提示什么No downstream....了
这时symbol file path为:
OK,现在这个.symfix应该掌握了,
.srcpath
类似于.sympath,设置源码路径
0:000> .srcpath
Source search path is: <empty>
0:000> .srcpath+ d:\windbg\
Source search path is: d:\windbg\
DBGENG: Scan paths for partial path match:
DBGENG: prefix 'd:\windbg\test1'
DBGENG: suffix 'test1.cpp'
DBGENG: match 'd:\windbg' against 'd:\windbg\test1': 14 (match '')
DBGENG: Scan paths for partial path match:
DBGENG: prefix 'd:\windbg'
DBGENG: suffix 'test1\test1.cpp'
DBGENG: match 'd:\windbg' against 'd:\windbg': -1 (match 'd:\windbg')
DBGENG: check 'd:\windbg\test1\test1.cpp'
DBGENG: found file 'd:\windbg\test1\test1.cpp'
windbg调试器如何知道为某个程序找到符号文件? 调试器需要两部分信息:符号路径的位置,它包括一组路径,以及存储在模块头部分于验证符号文件的信息.符号路径可以是一个本地文件夹、UNC共享连接,或者是在"符号服务器"一节中将要介绍的符号服务器路径。
符号路径的形式很简单,它包括一组由分号(;)分隔的文件夹,符号文件的名字是从映射头部的CV记录中提取出来的,如果没有CV记录,那么也可以根据二进制文件的名字来生成。调试器将通过一种启发式算法在符号路径中搜索符号文件,并将每个找到的符号文件与模块信息进行匹配。如果没有找到匹配的符号文件,调试器将默认使用在模块中导出的符号。
.srcnoisy
.srcnoisy 命令控制源码文件加载的显示级别
0 禁止对额外信息的显示。1 显示源文件加载和卸载的进行情况。2 显示符号文件加载和卸载的进行情况。3 显示选项1和2的所有信息。
0:000> g
Breakpoint 3 hit
eax=00000002 ebx=7efde000 ecx=4f1e7d4c edx=6a521408 esi=001ef98c edi=001efa70
eip=012430ed esp=001ef98c ebp=001efa70 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
test1!wmain+0x5d:
012430ed 8bf4 mov esi,esp
DBGENG: Scan paths for partial path match:
DBGENG: prefix 'd:\windbg\test1'
DBGENG: suffix 'test1.cpp'
DBGENG: Scan paths for partial path match:
DBGENG: prefix 'd:\windbg'
DBGENG: suffix 'test1\test1.cpp'
DBGENG: Scan paths for partial path match:
DBGENG: prefix 'd:'
DBGENG: suffix 'windbg\test1\test1.cpp'
DBGENG: Scan all paths for:
DBGENG: 'd:\windbg\test1\test1.cpp'
DBGENG: Scan all paths for:
DBGENG: 'windbg\test1\test1.cpp'
DBGENG: Scan all paths for:
DBGENG: 'test1\test1.cpp'
DBGENG: Scan all paths for:
DBGENG: 'test1.cpp'
DBGENG: Check plain file:
DBGENG: 'd:\windbg\test1\test1.cpp' - found
最后found!
打开log
在Edit--Open/Close log File:
如果只输入名称,则默认在调试器windbg目录下生成,如果文件已存在,选了Append,则不会覆盖原有内容,否则会覆盖.
再次打开,点击Close Open Log File可以把Log关闭,当前Log只记录从"Opened log file XX"到"Closing open log file"的内容,
当然,Append勾选不会把以前的Log覆盖.
windbg-!logexts(自带的监控API)
Logexts.dll
windbgth自带了跟进API的功能,这样我们可以方便的跟踪整个API的调用
具体的示意图如下:
指令简介
!logexts.logi
将Logger注入目标程序,初始化监控,但是并不开启它。
!logexts.loge
开启监控,如果之前没有调用logexts.logi,这个扩展命令会先初始化监控,然后启动。
!logexts.logd
停止监控。这个命令会摘掉所有的Hook,从而让程序自由运行。不过COM的Hook并不会被摘除。
!logexts.logo
显示或者修改输出选项,这里有三种输出方式:1.在调试器中显示,2.输出到一个文本文件,3.输出到lgv文件。其中lgv文件会包含更多的信息,我们可以使用LogViewer进行查看。
!logexts.logc
显示或者控制监控的API分类。
!logexts.logb
显示或者刷新输出缓存。由于如果在监控过程中发生异常,那么扩展可能无法将记录的日志写入文件中,这个时候我们就需要这个命令,手动的将缓存中的数据写入文件。
!logexts.logm
显示和创建模块的包含/排除列表。这可以帮助我们指定记录那些特定模块中的API调用。
官方介绍
http://msdn.microsoft.com/en-us/library/windows/hardware/ff560170(v=vs.85).aspx
示例
!logexts.loge D:
设置log的保持路径,并且开启监控
!logexts.logc d *
先关闭所有API分类的监控
!logexts.logc
查看API分类id
!logexts.logc e 1
设置想监控API分类
!logexts.logo e *
开启了所有输出方式,注意:如果想要被监控的程序响应的更快,可以去掉Debugger的输出,因为显示花费的时间比较的多。
Logextse有高度可配置性。如果你想监控他描述以外的API,那么你可以自己写这个API的“头文件”。这里用引号是因为,它并不是真正的头文件,只不过他的语法和C的头文件非常的相似。我们可以看一个例子:
创建%windbg_dir%winextmanifestContext.h
并且写入这些内容
category ActivationContext:
module KERNEL32.DLL:
FailOnFalse ActivateActCtx(HANDLE hActCtx, [out] PULONG_PTR lpCookie);
FailOnFalse DeactivateActCtx(DWORD dwFlags, ULONG_PTR upCookie);
在%windbg_dir%winextmanifestmain.h文件的最后加入一行 #include “Context.h”
保存后,重启调试程序,输入!logexts.logc,可以看了多出了ActivationContext这一项。现在就可以选择这一项分类来监控ActivateActCtx和DeactivateActCtx了。
最后自己随便写了个简单的script调用:
.printf /D "<link cmd=\"!logexts.loge c:\\cmdtree\\log\\ \">Enables logging</link>\n"
.printf /D "<link cmd=\"!logexts.logo e *\">sets Logger output</link>\n"
.printf /D "<link cmd=\"!logexts.logc e *\">Displays available API categories</link>\n"
.printf /D "<link cmd=\"!logexts.logb p;!logexts.logb f\">Displays current output buf</link>\n"
.printf /D "<link cmd=\"!logexts.logd\">Disables logging</link>\n"
.printf /D "<link cmd=\"!logexts.loge c:\\cmdtree\\log\\;!logexts.logc e *;!logexts.logo e *;!logexts.logb p;!logexts.logb f\">trace api calls</link>\n"
效果如下: