windbg调试基础

说明

(1)每个命令都有各自的使用范围,不支持的指令会显示“No export XXX Found”
(2)调试命令分为三种:基本命令、元命令、扩展命令。基本命令和元命令是调试器自带的。元命令总是以“.”开始,而扩展命令是外部加入的,总是以“!”开头。
(3)基本命令的帮助指令为“?” ,元命令的帮助指令为“.help [/D] ”  ("/D"可以以DML的方式设置链接)
(4)扩展命令从DLL中暴露出来,每个DLL代表一类扩展命令,查看扩展的DLL的命令为“.chain [/D]”。若要列出某个DLL的扩展命令,则使用命令“!模块名.help”。例如:!ext.help
(5)加载DLL的扩展命令的指令为:“.load xxx” 或者 ".unload XXX"
(6)DML使生硬的命令显得友好一些,“dml_start”列出每一类的命令链接。开启DML:".prefer_dml 1" 关闭DML:".prefer_dml 0" 流程图".dml_flow xxxx"
(7)基本信息
version  //查看操作系统和windbg版本
vertarget//单独查看系统版本
||      //列出对象列表
.time  //查看系统时间、进程运行时间


(8)基本设置
.cls :清屏
n [8\10\16] 回车后输入:? 1234  //实现8\10\16进制之间的转换
.effmach [x86\amd64\ia64\ebc]  //设置当前的处理器模式,例如主机为32位的系统,却可以同时调试x86\IA64\x64的目标系统,只要设置主机的处理器模式即可。
.formats 整数 :格式化输出


开始调试

调试已经运行的进程:
.attach 0xPid
windbg -p 0xPid
windbg -pn ProcessName
创建新进程并进行调试
.create 程序启动命令行 例如:
windbg 程序启动命令行 例如:
多个进程挂载调试时:
|  //列出所有被调试的进程
| x s //切换当前调试的进程
进程解除挂载:
.detach //解除windbg和调试进程的调试关系,然后进程可以独立运行。若调试的为dump,则直接结束对dump文件的调试
打开dump文件:
.opendump 文件名
程序崩溃时创建一个dump文件:
.dump 文件名
彻底结束调试:
q|qq|qd   \\q和qq将结束被调试的进程,qd不会关闭被调试的进程。
双机调试时:
.crash  \\引发一个蓝屏,并生产dump文件
.reboot \\系统重启,但不生产dump文件


符号文件

(1)分类:公用符号文件和私有符号文件,公用符号文件包含的信息比较少,私有符号文件含有大量的符号信息。
(2)包含内容:
全局变量,包括类型、名称、地址信息(公用符号)
函数信息,包括名称、原型、地址信息(名称、地址为公用符号,原型为私有符号)
变量、结构体类型定义 (公用符号)
局部变量,包括类型、名称、地址(私有符号)
源文件路径,以及每个符号对应于源文件中的行号,这是进行源码级调试的基础(私有符号)
(3)符号信息隶属于模块,模块加载时才有必要分析其符号信息,模块相关指令:
(a)列举模块列表的命令:lm !dlls .reload/l !imgreloc
lm [选项] [a Address][m Pattern|M Pattern] 或 lmD [选项] [a Address][m Pattern|M Pattern]
选项为/v 可以列出模块的详细信息,包括模块名、模块地址、大小、镜像名、时间戳 以及对应的符号文件信息
参数a 后跟address,只有指定地址所在的模块被列出
参数m 后跟通配符,例如 lm m *o* \\将列出名称中含有o的模块
!dlls [选项][EntryAddress]
-i\-l\-m 排序方式,初始化方式、加载方式、内存起始地址顺序排序
-a 列出镜像文件PE结构的文件头、section头等详细信息
-c 指定函数所在的模块,例如NtCreateFile在哪个模块, 使用命令:!dlls -c ntcreatefile
.reload/l


!imgreloc [模块地址]
主要作用是判断各个模块是否处于preferred地址范围。(preferred是指编译器为其设置的理想地址)


(b)查看模块信息指令
lm v a 模块地址
v选项,以显示详细信息,a参数用来指定模块地址,获取的信息类似于文件属性中获取的信息
!lmi 模块地址
侧重获取对调试器有用的信息
!dh 模块地址
显示非常详细的PE文件头信息


符号路径

(1)调试器寻找符号路径的方向,可以是本地文件夹路径、可访问的UNC路径、符号服务器路径。
(2)设置符号路径(可以在菜单中设置)
.sympath [+] [路径]
.sympath         //查看当前设置的符号路径
.sympath 路径   //将删除原来设置的路径,重新设置新的路径
.sympath+ 路径  //在原来设置的基础上,添加新的符号路径
注:新添加的符号路径,需要使用.reload 指令来更新生效
(3)设置符号服务器和符号缓存
SRV*[符号缓存路径]*服务器地址
设置微软的符号服务器地址:.symfix+ 本地缓存路径


(4)符号选项
.symopt        //查看符号选项
.symopt+ Flags //添加符号选项
.symopt- Flags //删除符号选项


(5)符号加载
(a)立刻加载
ld xxx /f xxx //前面xxx为xxx.exe,后者为xxx.pdb
(b)重新加载
.reload /f /v [模块名] //没模块名时,将重新加载当前使用的所有模块的pdb
/f    //迫使调试器立刻搜素并重新加载 
/v    //搜索过程中的详细信息显示出来
/i    //不检查pdb文件的版本
/l    //只显示模块信息,在内核模式下和"lm n t"命令类似,但显示的内容更多,因为包含了用户模块信息
/n    //仅仅重加载内核符号,不加载用户符号
/o    //即使版本相同,也强制覆盖符号库中的符号文件
/d    //用户模式下的默认选项,重新加载模块列表中的所有模块
/s    //内核模式下默认选项,重新加载系统模块列表中的所有模块,若用户模式下加载内核模块时则也要使用此选项
/u    //卸载指定模块。若发现当前版本不对,使用"\u"先卸载再重新加载


(c)符号验证
!chksym <模块名> [符号名]


(d)加载选项
!sym    //默认设置为Quit\prompts on的状态
两类:Quit\noisy    搜索或加载pdb时,是否显示详细信息
 prompts on \ prompts off 网络下载符号遇到安全认证时,是否弹出确认对话框,不弹出的情况下不会下载符号链接。


(6)符号搜索
(a)全局搜索
x [参数] [模块!符号]
不加参数时,将列出当前调试环境下的所有的句柄变量。例如显示kernel32模块中所有以a开头的符号:x kernel32!a*
支持DML格式,即\D 例如:x \D kernel32!a*
若不知道NtCreateFile函数在哪个模块,则: x *!*NtCreateFile*
x的参数
/t  /v  //建议带上,显示更多的符号、类型信息
/f // 只显示函数符号,并且会显示函数的详细定义
(b)就近搜索
ln 内存地址  //列出地址附近一定范围内的所有符号


源码命令

(1)源码路径
.srcpath //查看当前源码路径
.srcpath+ 路径 //添加路径
.srcpath 路径 //删除原来的路径设置,重新添加路径
(2)源码选项
.srcnoisy    //查询当前状态
.srcnoisy 1  //开启状态,在源码加载、卸载、单步调试时会显示丰富的源码信息
.srcnoisy 0  //关闭装填


.lines [-d|-e|-t] //在符号文件加载过程中,是否将行号一并加载进来。


代码行选项,包括行号和内容,建议 l+* 设置
开打:l+[选项]
关闭:l-[选项]
进入源码模式和汇编模式的命令:
l+t \\源码模式
l-t \\汇编模式


进程命令

(1)进程列表
显示进程命令:|  .tlist  !process !dml_proc
|:命令显示当前被调试进程的列表信息,在多个进程间切换使用参数“s"
.tlist[选项][模块名] :显示当前系统的进程列表 -v选项显示进程详细的信息,-c显示当前的进程信息,没有模块名时将显示当前系统下所有的进程的信息
!process 用在内核模式下,显示进程列表和指定进程的详细信息,可以显示进程中的线程和调用栈内容。
!dml_proc[进程号|进程地址] :相当于"|" "!process"的DML合并版本


(2)进程信息
进程环境块(process Environment Block)是内核结构体,主要是查看进程的此结构。
!peb [地址]
若没设置地址,则显示当前进程。在内核模式下要使用!process获取地址,在用户模式只能显示当前进程的PEB,故一般不带参数。
dt nt!_peb 地址 : 显示系统nt模块中所定义的内核结构体PEB的详细内容。
(3)进程切换
进程的切换,将伴随着相关的寄存器和堆栈的切换。
在用户模式下:
| [进程号] s
在内核模式下:
.process [进程地址] //所谓进程地址,即RPPROCESS结构体地址。
.context [页目录地址] //页目录地址就是!process中的DirBase,若没添加地址,则显示当前页目录地址


线程命令

使用命令"~"能够进程与线程的相关操作,在不带任何参数的情况下,列出了当前调试进程的线程信息。
(1)冻结线程
~2f :表示把2号线程冻住,在解冻之前不再给它分发CPU时间
~2u :2号线程解冻重新运行。
(2)线程挂起
~2n :表示increase,增加一个线程的挂起计数
~2m :表示resume,减少一个线程的挂起计数
注:挂起计数为0时,才可继续运行
(3)线程切换
~2 :查看指定的线程信息
!teb [teb地址] :线程中包含有线程环境块
~ 线程号 s  :线程间切换
~~ 线程ID s :使用线程ID在线程间切换


(4)线程遍历
~*k      :显示所有线程栈信息(此命令:对所有线程执行k命令)
~*r      :显示线程寄存器信息
~*e k;r  : e为execute的缩写,后面跟一个或多个windbg命令,它遍历线程并对每个线程执行指定指令。此处表示:对所有线程执行k、r指令。
(5)线程时间
.ttime :显示当前线程的时间信息
!runaway 7 :显示当前进程的所有线程的时间信息
异常与事件
(1)windbg调试器是事件驱动的。Windows操作系统的调试子系统,是"事件"的发生源。调试器的所有操作都是因事件而驱动,因事件处理而被中继。异常只是事件中的一类。
(2)sx : 列出针对当前调试目标的异常或非异常的处理
(3)在菜单debug中event filters菜单中查看全部调试事件。Execution表示中断属性,Continue表示中继熟悉,Argument设置调试事件执行参数,Commands设置事件两轮机会发生时的执行命令。
(4)sxr :将当前对调试事件的设置,恢复为默认设置。
(5).lastevent : 显示最近发生的一个调试事件,往往是导致发生中断的事件。
(6).exr -l :仅仅显示最近一条的异常记录
(7).bugcheck :显示bug check 的详细信息
(8).analyze 
-v :显示异常的详细信息
-f : force,强制将任何事件都当做异常来分析,即使是普通的断点事件
-hang : 遇到死锁时可以分析原因,在内核模式下分析内核锁和DPC栈,在用户模式下分析线程的调用栈,在用户模式下一定要切换到最可能引起问题的线程中才有帮助。另一个分析死锁的命令:!looks
-show bug-check-代码[参数]:在内核环境下,显示指定的bug check的详细信息。
(9)!error [][]: 
!error 2 : 错误码为2的win32错误信息
!error 2  1: 错误码为2的NTSTATUS错误信息
(10)!gle [-all] :调用win32的GetLastError函数分析
(11)gh (go with exception handled):把异常标记为已处理,并继续执行
(12)gn (go with exception not handled):对异常不进行处理,而继续执行


局部变量

(1)x和dv两个命令可以打印当前的局部变量列表。dv功能强大。
(2)dv的参数
/v : 显示虚拟地址
/i : 显示变量详细信息,局部变量、全局变量、形参、函数变量
/t : 变量类型
/f : 可指定进行分析的函数,需要指定函数名
例如 dv /v /i/ /t /f wmain  //表示对wmain函数分析局部变量
显示类型
(1)dt命令可以查看结构体的类型定义。例如:dt nt!*


内存命令

查看内存

(1)d[类型] [地址范围]  //类型为:
d,da,db,dc,dd,dD,df,dp,dq,du,dw,dW,dyb,dyd,ds,dS
(2)以数组的形式查看内存
dda\dpa\dpp\dpu\dps\dqa\dqp\squ\dqs
(3)以链表形式查看内存
dl 开始地址 \\默认从头到尾遍历链表,b参数可设置反向遍历。

内存信息

(1)!address [地址]  //显示进程和系统的内存状态、信息。例如:
    BaseAddr EndAddr+1 RgnSize     Type       State                 Protect                   Usage
|-  401000   529000   128000    MEM_IMAGE   MEM_COMMIT      PAGE_EXECUTE_READ             Image "testDeviceIoCtrl.exe"

(a)内存类型
未被使用    
MEM_IMAGE   映射在一个可执行的文件片段,例如dll
MEM_MAPPED  映射在一个不可执行的文件片段,例如页文件
MEM_PRIVATE 私有内存针对进程而言,无法在多进程间共享
(b)保护模式
NOACCESS(不做任何访问)
READWRITE(可读写)
PAGE_NOACCESS(不可访问)
PAGE_READONLY(只读)
PAGE_READWRITE(可读写)
PAGE_EXECUTE_READWRITE(可执行可读写)
PAGE_WRITECOPY(写时拷贝)
PAGE_EXECUTE_WRITECOPY(可执行并写时拷贝)
PAGE_GUARD(保护)


(c)内存状态
MEM_FREE(空闲内存)
MEM_RESERVED(保留内存,不能被实际使用)
MEM_COMMIT(内存已经提交,正在使用)
(d)内存用途
用户内存:
RegionUsageIname(二进制文件镜像)
RegionUsageStack(线程栈)
RegionUsageTeb(线程的TEB结构)
RegionUsageHeap(堆内存)
RegionUsagePeb(目标进程的Peb)
RegionUsageProcessParameters(目标进程的启动参数)
RegionUsageEnvironmentBlock(目标进程的环境块)
内核模式:
KernelSpaceUsageImage(内核文件的镜像)
KernelSpaceUsagePFNDatabase(页表信息)
KernelSpaceUsageNonPagePool(非分页内存池)
KernelSpaceUsageSpecialPool(特殊池内存)
KernelSpaceUsageKernelStack(内核栈



(2)在用户模式下,使用以下命令可以查看内存统计信息
!address -summary  //侧重内存用途、内存类型、内存状态等
!vprot [地址]     //侧重内存保护信息
!vadump [-v]      //显示整个内存空间, -v将详细显示
(3)在内核模式环境下,查看内存统计信息
!memusage  //从物理内存角度显示内存统计信息。无数个页表将被打印。
!vm        //从虚拟内存的角度显示统计信息
(4)其他
!filecache  //在内核模式下,显示文件缓存和页表状态。
!heap       //在用户模式下,查看堆信息。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值