windbg学习笔记(2)

第一部分 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 :查看系统当前会话

    1
    2
    3
    4
    kd> !session
    Sessions on machine: 1 //系统中有1个会话
    Valid Sessions: 0 1 3 //有效的会话ID是0
    Current 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 [指定位置符号]:查看指定位置最近的符号