第一部分 windbg命令
windbg命令一共有三大类:标准命令(命令特别短,容易记忆),元命令(也是windbg内置命令,一般用”.”表示,也成点命令),拓展命令(利用windbg目录中的dll文件实现的,使用的时候需要加载需要使用的模块)。
标准命令
一共有大概15中标准命令:
- 控制程序目标执行:
- g:恢复程序运行
- t:跟踪步入(trace into)
- o:跟踪步过(trace over)
- 观察修改寄存器:r命令
- 内存数据:
- d:查看
- e:编辑
- s:搜索
- 观察堆栈:k命令
- kd:显示所有栈情况
- kp:显示调用栈
- kb:显示前三个参数
- kc:只显示调用栈的模块名和地址(不显示调用栈的地址)
- kn:段函数加标号
- Kv:显示FPO和调用约定
- 断点相关:
- BP:设置软件断点
- BA:设置硬件断点
- BL:列举断点
- BC:清除断点
- BD:禁止断点
- BE:重启断点
- 显示控制线程:~命令
- 显示控制进程:|命令
- 显示表达式:?命令,显示C++表达式:??命令
- 用于汇编:a命令,用户反汇编的u命令
- 显示段选择子:dg命令
- 检查符号命令:x命令,搜索符号:ln命令,显示模块命令:lm命令,ld:加载符号表
- 结束调试:q命令
源命令
源命令一般以”.”开头,所以也称之为点命令。
- 控制调试会话和调试目标:
- 重新开始会话:.restart
- 放弃调试目标:.abandon
- 创建新进程进行调试:.create
- 附加进程进行调试:.attach
- 打开转储文件:.opendump
- 分离调试目标:.detach
- 杀死进程:.kill
- 管理拓展命令模块:
- 加载模块:.load
- 卸载模块:.unload和.unloadall
- 显示已经加载的模块:.clain
- 显示转储调试目标:
- 产生转储目标:.dump
- 将原始内存数据写入文件:.writemem
- 显示调试会话时间:.time
- 显示线程时间:.ttime
- 列举任务(进程)列表.tlist
拓展命令
拓展命令保存的windbg安装目录下的dll文件里面,具体使用是”![模块名称].[命令名称] [参数]”。一般使用.load命令需要写入模块的绝对路径,使用.loadby只需要写入模块名称即可!
第二部分 命令提示符
命令提示符号是由一系列文字和大于号组成。他一般标识调试对象的状态或者调试环境的状态。
调试状态
一般存在三个调试状态。繁忙,暂无调试对象和等待。
调试环境状态
当调试器处于等待状态,则windbg显示的是调试环境状态。
如上图:第一个0代表的系统号,如果是0代表的是用户态调试,如果是1代表的是内核态调试
第一个0表示的是进程号,是第0号进程。
第三个数字表示的是线程号。
切换调试对象
- 切换系统号:||
s - 切换进程号:|
s - 切换线程号:~
s
第三部分 创建调试会话
附加已运行进程
- file菜单—>attach to a process
- .attach (多个会话)
创建新进程
- file菜单
- .create xxx.exe
本地内核调试
- file菜单—>kernel Debug
- .attach -k
调试转储文件
- file菜单—>open Crash dump
- .opendump
第四部分 理解上下文
会话上下文
无论用户采用的是本地登录还是远程登录,windows都会为其创建一个会话,这就意味着会话是与windows登录是相关的。会话上下文只有在内核调试才有作用
!session :查看系统当前会话
1234kd> !sessionSessions on machine: 1 //系统中有1个会话Valid Sessions: 0 1 3 //有效的会话ID是0Current Session 1 //当前会话是1!session -s[会话ID]:修改当前会话
改变会话后,默认进程页随之改变成新会话中的进程,因此以前缓存的用户空间不在有效。目前会话上下文只有在内核调试时才有意义。
- !sprocess:查看当前会话内部的所有进程
没有会话都有一个csrss.exe进程(会话管理器进程),但是该进程不属于任何一个会话。
进程上下文
我们都知道一个32位的系统,进程空间为4GB,其中高2GB是系统区域,低2GB是用户区域,但是windows中,系统区域是共享的,但是用户区域是彼此独立的,也就是说,在内核调试的时候,需要切换进程上下文,但是在用户调试的时候,不需要切换进程上下文。
- !process 0 0:列出所有进程的基本信息,主要是EPROCESS信息,这是切换进程上下文的重要信息。
- .process [EPROCESS]:切换进程上下文。
- .context:显示页目录基址
所谓页目录基址,每个进程用户空间都是基于一个页目录基址的,同时也存在一个进程多个页目录基址,此时使用.process会更加有效!
寄存器上下文
寄存器存储的是当前线程的数据值,其他线程都存放在内存中,一般在线程切换(线程上下文)或者产生中断(或异常)(异常上下文)会使用寄存器上下文。
- !process [EPROCESS] :查看进程所有线程信息
- .thread:查看当前线程(我感觉!thread比.thread显示的信息详细很多)
- .thread [THREAD]:修改线程上下文
局部上下文
函数的局部变量关系着函数执行的顺序和位置,在调试时,调试器默认显示的是当前函数所对应的局部上下文。
- .frame:显示局部上下文,如下图:显示当前堆栈对于的函数为RtlpBreakWithStatusInstruction
- kn:显示帧栈函数列表
- .frame [栈函数编号]:切换局部上下文
第五部分 符号与模块
查看模块信息
- lm :显示当前进程的模块信息
- v:显示详细信息
- m:过滤指定模块名:lm m k*
- o: 过滤已经加载过的模块
- !lmi:可以指定进程名,但是只显示一个模块
- 符号类别
查看和分析符号
- x [选项] 模块名!符号名:查看符号信息(支持正则)
- /a /A: 按地址升序或者降序显示
- /n /N:按名称—
- /z /Z: 按大小
- /t:显示数据类型
- /v:显示符号的类型和大小
- /p: 省略函数名和括号之间的空格,意义不是很大
查看符号
- ln [指定位置符号]:查看指定位置最近的符号