前言
这是在四月份写的本系列的第一篇笔记,没有很系统的学习windbg的使用,马上要去四叶草学习,暑假这几天先系统性的学一下windbg的使用,系列笔记会在
配置篇:
- 1)安装WinDbg,如果要进入内核模式调试的话需要进行如下步骤:
- 1)修改虚拟机C盘根目录下配置文件boot.ini
- 2)修改虚拟机设置,添加一个串行串口
- 3)在宿主主机启动winbdg,进入内核调试,配置如下
- PS:如果遇到Fail Open \.\pipe\com_1,只需要在快捷方式后面添加“windbg -b -k com:pipe,port=\.\pipe\com_1,resets=0”即可
进程篇
1.查看进程列表
有多个命令可以显示进程列表,他们主要是:“|”,“.tlist”,“!process”,“!dml_proc”。
- | [进程号]
在用户态下,这个命令显示当前被调试进程的状态信息
被调试进程列表。大多数情况下,调试器中只有一个被调试进程,但可以通过.attach或者.create命令同时挂载或创建多个调试对象。当同时对多个进程调试时,进程号是从0开始的整数。 - tlist [选项] [模块名]
在用户模式下显示系统当前的进程列表,存在两个参数选项:-v:显示进程的详细信息,-c显示当前进程信息。默认是-v
可以通过“.attach”或者“.create”来创建或者附件多个调试对象
- !process:显示调试器当前运行的进程信息
但是这个命令只能在内核调试中使用,如果在用户态中调试,则会出现如下的错误提示。No export prcoess found
- 显示当前进程列表(内核态)
- !process PID:显示PID的详细信息(内核态)
!process 0 0 XXX,exe:查找指定进程(用户态中)
以下是根据上述命令查看到的信息包含的主要内容。Cid : 进程id
- Peb : 进程环境块的地址
- ParentCid : 父进程id
- DirBase : 页目录表 (用于转换虚拟地址和物理地址PDT)
- ObjectTable : 进程的句柄表
2.进程信息
- !peb[address]:查看指定PEB信息,在内核模式下,address可以通过!process 0 0:来查看。如果!peb不带参数,则指的是当前进程的PEB,在用户模式下,只能查看当前进程的PEB,所以不需要带参数。
- dt nt!_PEB[address]:此命令显示系统nt模块中所定义的内核结构体PEB详细内容.
3.切换进程
因为进程的地址空间都是相互独立的,所以我们使用dd 0x400000之类的指令是没有意义的。因为我们不确定当前用户地址空间就是我们的目标进程地址空间。因此我们首先要切换到我们想查看的进程上下文。之后才能查看它私有的地址空间。如果不按这个规定的话,有可能得出的结果是很多?????
- .process [process address]:切换当前的进程空间。
- .context [页目录地址]:如果不使用任何参数,.context命令将显示当前页目录地址。页目录地址就是!process命令中显示的DirBase值。进程切换后,为了检测是否正确切换,可再用!peb命令检查当前进程的环境信息。
4.加载dll
.peb能显示当前进程所加载的dll,但是.dll能显示当前系统所在加载的dll。
线程篇
命令”~”能够进行线程相关的操作。不带任何参数的情况下,它列出当前调试进程的线程。
1.线程冰封
参数f与u分别代表freeze和unfress,前者是指冻住指定线程,后者将被冰冻线程解冻。
- ~2f:暂停该进程的2号线程
- ~2u:启动该进程的2号线程
2.线程切换
- ~线程编号(不是TID):切换线程
- !TEB:查看线程信息块
- ~ 线程号 s:在多线程间作切换,需使用~命令的s参数
- ~~【线程ID】 s: 注意这个命令中的[]并非可选符,而是命令的一部分。例如命令:~~[11a0] s,它将当前线程切换到线程ID为0x11a0的线程。线程ID是系统维护的系统唯一的ID值。
3.遍历线程
- ~*k:显示所有线程的栈信息
- ~*r:显示线程的寄存器信息
- ~e -cmd:对线程执行操作:例如:~e k;r就是对线程执行k和r操作。
查找句柄
利用!handle来查找句柄。
- !handle <句柄索引><标志><进程ID>;句柄索引为0,代表输出所有句柄,为4是输出第一个句柄。
- Object标明的是对象的地址。
- Type标明的是句柄的类型。
- HandleCount标明的是引用次数。
- PointerCount标明的是指针指针引用次数。
异常与事件
- “.lastevent”:显示最近发生的调试事件
- “.exr [mem]”:显示一个异常记录的详细信息
- “.exr -1”:显示最近的一条异常信息,可以使用-1代替记录地址。
- “!anaylze” :用于分析最近的异常事件,并显示分析结果。
- -v:显示详细信息。尤其适用于调试错误
- -f:强制所有事件都当成异常来处理
- -hang:这个选项很有用,对于遇到死锁的情况,它会分析原因。在内核环境中,它分析内核锁和DPC栈;在用户环境中,它分析线程的调用栈。用户环境中,调试器只会对当前线程进行分析,所以一定要将线程环境切换到最可能引起问题的那个线程中去,才有帮助。这个参数非常有用,当真的遇到死锁时,它可以救命(另一个分析死锁的有效命令是!locks)
- -v:显示详细信息。尤其适用于调试错误
- “!error”:此命令和VC里面内置的errlook工具类似。用来根据错误码,查看对应的可读错误信息。微软系统中常用的全局错误码有两套,一套是Win32错误码,通过函数GetLastError()获得的值;另一套是NTSTATUS值。!error命令对这二者都能支持。区别的方法,若错误码后面无参数1,则为Win32错误码;否则就是NTSTATUS错误码。
- “!gle”: 此命令是Get Last Error的缩写。它调用Win32接口函数GetLastError()取得线程的错误值,并打印分析结果。如果带有-all选项,则针对当前进程的所有线程执行GetLastError()操作;否则仅针对当前线程。