Loading... > windbg手册 --- # 查看变量 `dv` Display Variable的缩写, 查看局部变量. `dv /i` 查看局部变量, 并显示符号的类型和参数类型. `dv /V` 查看局部变量, 并显示变量的存储位置. `dv /V VariableName` 指定需要查看的变量的名字 `dv 02sample!gGlo*` `dv`命令可以带有通配符, 来查看具有某命名模式的变量. `dt` Display Type的缩写. 当变量的类型为复合类型, 比如说结构体或者类, 那么dv命令只会显示变量的地址. dt命令可以将一块内存按照某个数据类型来解析, 其中的数据类型需要作为参数被传递给dt命令. `dt KBTest 0x000cff0c` 将某内存地址按照某类型来解释并显示. `dt 02sample!gGlobal` dt命令在显示内存块时, 解析对象的类型. # 断点 WinDBG 提供了多种设断点的命令:bp, bu, bm, ba. `bp` 命令是在某个地址下断点, 可以 `bp 0x7783FEB`也可以 `bp MyApp!SomeFunction` 。 对于后者,WinDBG 会自动找到MyApp!SomeFunction 对应的地址并设置断点。 但是使用bp的问题在于:1)当代码修改之后,函数地址改变,该断点仍然保持在相同位置,不一定继续有效; 2)WinDBG 不会把bp断点保存工作空间中 。所以,我比较喜欢用bu 命令。 `bu`命令是针对某个符号下断点。 比如 `bu MyApp!SomeFunction` 。 在代码被修改之后, 该断点可以随着函数地址改变而自动更新到最新位置。 而且bu 断点会保存在WinDbg工作空间中, 下次启动 Windbg 的时候该断点会自动设置上去。另外,在模块没有被加载的时候,bp 断点会失败(因为函数地址不存在),而bu 断点则可以成功。 新版的WinDBG中 bp失败后会自动被转成bu 。 `bm` 命令也是针对符号下断点。 但是它支持匹配表达式。 很多时候你下好几个断点。 比如,把MyClass 所有的成员函数都下断点: `bu MyApp!MyClass::*`, 或者把所有以CreateWindow开头的函数都下断点:`bu user32!CreateWindow*` 。 以上三个命令是对代码下断点, 我们还可以对数据下断点。 `ba`命令就是针对数据下断点的命令, 该断点在指定内存被访问时触发。 命令格式为 `ba Access Size [地址]` Access 是访问的方式, 比如 e (执行), r (读/写), w (写) Size 是监控访问的位置的大小,以字节为单位。 值为 1、2或4,还可以是 8(64位机)。 比如要对内存0x0483DFE进行写操作的时候下断点,可以用命令 `ba w4 0x0483DFE` 其他断点命令: `bl` 列出所有断点 `bc` 清除断点 `bd` 禁用断点 `be` 启动被bd 命令经用的断点 # 符号 ld ModuleName 加载指定模块的符号 ld * 加载所有模块的符号 !sym 获取符号加载状态 !sym noisy 让调试器显示符号搜索详细信息 !sym quiet 默认项,不显示符号搜索信息 .sympath 显示和设置符号搜索路径 .sympath+ 增加符号搜索路径 .sympath+ C:\Symbols .symopt 显示当前符号可选项 .symopt+ Flags 添加符号可选项 .symopt- Flags 移除符号可选项 .symfix 设置符号库路径 .sym+ DownstreamStore 添加符号库路径 x [Options] Module!Symbol 模式匹配符号信息 x /t .. 根据数据类型匹配 x /v .. 显示详细信息 x /a .. 按照地址排序 x /n .. 按照名称排序 x /z .. 按照大小排序 x *! 列出所有模块 x ntdll!* 列出 ntdll 模块 x /t /v ntdll!* 列出 ntdll 模块数据类型和符号类型 .reload 重新加载符号信息 .reload [/f | /v] /f 强制立即加载符号 /v 显示详细信息 .reload [/f | /v] _Module_ Module 为指定模块加载符号信息 .reload /f @"ntdll.dll" .reload /f @"C:\WINNT\System32\verifier.dll" # 模块 lm[ v | l | k | u | f ] [m Pattern] 显示已加载的模块 lm 显示所有加载和未加载的模块信息 lmv 显示已加载模块的详细信息 lml 同时显示加载的符号信息 lmk 显示内核模块信息 lmu 显示用户模块信息 lmf 显示镜像路径 lmm 匹配模块名称 lmD 使用 DML 方式显示 lmv m kernel32 显示 kernel32 模块详细信息 !dlls 列出所有加载的模块和加载数量 !dlls -i 根据初始化顺序 !dlls -l 根据加载顺序(默认项) !dlls -m 根据内存顺序 !dlls -v 显示更多详细信息 !dlls -c _ModuleAddr _仅显示 ModuleAddr 地址的模块信息 !dlls -? 显示帮助 !dlls -v -c kernel32 显示 kernel32.dll 的信息 !lmi _Module _显示模块的详细信息,包括加载符号信息 !lmi kernel32 显示 kernel32.dll 模块的信息 # !address eax 查看对应内存页的属性 # vertarget 显示当前进程的大致信息 # !peb 显示process Environment Block # lmvm 可以查看任意一个dll的详细信息 例如:我们查看cyusb.sys的信息 # d 注意:第二个d表示DWORD格式,此外还有db(byte),du(Unicode),dc(char)等等。 数据查看指令 d{a|b|c|d|D|f|p|q|u|w|W} d{b|c|d|D|f|p|q}分别是显示: byte&ASCII, double-word&ASCII,double-word,double-precision,float,pointer-sized,quad-word数据; DA用于显示ASCII,DU用于显示UNICODE; BYB,BYD,显示binary和Byte及binary和DWORD 补充一个DV,用于查看本地变量用的 # e 命令可以用来修改内存地址 跟d命令一样,e命令后面也可以跟类型后缀,比如ed命 令表示用DWORD的方式修改。下面的命令把054efc14地址上的值修改为11112222。 0:018>ed 054efc14 11112222 修改后可以用dd命令来查看内存。 0:018>dd 0543fc14 L4 L4参数指定内存区间的长度为4个DWORD,这样输出只有1行, 而不是8行了。 修改内存 (edit memory) e{a|u|za|zu} address “String” 其总za和zu表示以0结尾的Ascii和Unicode字符串, a和u则表示没有0结尾 比如 ezu 0x445634 “abc” 表示在0x445634地址写如unicode 字符串abc 比如ea 0x445634 “abc” 表示在0x445634地址写入Ascii字符串abc, 不包含结束符0 e{a|b|d|D|f|q|u|w} address [values] 其中a表示ASCII码,b表示byte, d表示DWORD, D表示double, f表示float, q表示8字节, u表示Unicode String, w表示word 比如eb 0x123432 0x41 0x41 0x41 表示在地址0x123432 写入3个0x41 # s s –[type] range pattern 其中type, b表示byte, w表示word, d 表示dword, a表示ASCII string,u表示unicde string Range 表示地址范围,可以用2种表示:一是起始地址加终止地址, 二是起始地址加L长度(不是字节长度,是单位长度)。如果搜索空间长度超过256M,用L?length。 Pattern指定要搜索的内容. 比如 s -u 522e0000 527d1000 "web"表示在522e0000 和527d1000之间搜索Unicode 字符串”web” 比如s -w 522e0000 L0x100 0x1212 0x2212 0x1234 表示在起始地址522e0000之后的0x100个单位内搜索0x1212 0x2212 0x1234系列的起始地址 # k 命令用来显示当前线程的堆栈,如下 0:018> k 跟d命令一样,k后面也可以跟很多后缀,比如kb kp,kn,kv,kl等,这些后缀控制了显示的格式和信息。 栈指令k[b|p|P|v] 这四条指令显示的内容类似,但是每个指令都有特色; KB显示三个参数; Kp显示所有的参数,但需要Full Symbols或Private PDBSymbols支持。KP与Kp相似,只是KP将参数换行显示了; Kv用于显示FPO和调用约定; KD,用于显示Stack的Dump,在跟踪栈时比较有用。 这些指令区分大小。 # x 查找符号的二进制地址如下 0:018> x msvcr!printf 77bd27c2 msvcrt!printf = 上面的命令找到了printf函数的入口地址在77bd27c2 0:001> x ntdll!GlobalCounter 7c99f72c ntdll!GlobalCounter = 上面的命令表示ntdll!GlobalCounter这个变量保存的地址是7c99f72c。 注意:符号对应的是变量和变量所在的地址,不是变量的值,上面只是找到GlobalCounter这个变量的值是7c99f72,要找到变量的值,需要用d命令读取内存地址来获取。 X命令还支持通配符,比如x ntdll !*命令列出ntdll模块中的所有的符号,以及对应的二进制地址。 # 跟踪指令T,TA,TB,TC,WT,P,PA,PC T 指令单步执行,在源码调试状态下,可指源码的一行,根据不同的选项也可以为一行ASM指令; TA 单步跟踪到指定地址,如果没有参数将运行到断点处; TB 执行到分支指令,分支指令包括calls, returns, jumps, counted loops, and while loops; TC 执行到Call指令; WT Trace and Watch Data,一条强大指令,对执行流程做Profile,执行一下看看结果吧; P,PA,PC 相信不用多做解释,大家也都明白了; # 源代码操作指令.,lsf,lsc,ls,l,lsp .指令打一个源文件,可以打开一个全路径的文件,也可以通过函数地址来打开并定位到源文件中函数的位置,如. –a myapp!main,. j://mydriver//mydriver.c lsf指定一个源文件为当前源文件,使用lsc可显示当前指定的源文件ls可显示源文件的代码。Lsf可以使用全路径,如果源路径已经设置,也可以直接指定源文件名称。如lsf mydriver.c,lsf j://mydriver//mydriver.c lsc显示当前源文件 ls显示当前源文件的代码,如ls 200显示第200行 l 用于设置源文件选项 lsp 设置源文件行在调试时显示范围比如, 显示当前行的前50,后50,lsp 100 但通常使用Windbg时,可以直接用Ctrl+O来打开并查看源文件 # 查询符号 kd> x nt!KeServiceDescriptorTable* 8046e100 nt!KeServiceDescriptorTableShadow = 8046e0c0 nt!KeServiceDescriptorTable = kd> ln 8046e100 (8046e100) nt!KeServiceDescriptorTableShadow | (8046e140) nt!MmSectionExtendResource Exact matches: nt!KeServiceDescriptorTableShadow = # !gle 查看LastError值 # !cs 列出CriticalSection的详细信息 # !threadpool 能看到完成端口,线城池工作线程和timer回调占线程池的情况 # time 可以看到进程跑了多长时间 # !dso 查看当前线程中有哪些对象,分析泄露时用到 !idt //查看中断向量表内容 dt nt!_KINTERRUPT 89c03bb0 //查看对应中断向量的详细内容 !ioapic //显示I/O APIC(即连接至设备的中断控制部件) !pic // !apic //有关PIC的配置情况 使用!process 0 0 获取用户空间的所有的进程的信息 如果有多个相同进程名,!process 0 0 SampleExe.exe kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** PROCESS fe5039e0 SessionId: 0 Cid: 0008 Peb: 00000000 ParentCid: 0000 DirBase: 00030000 ObjectTable: fe529b68 TableSize: 50. Image: System # 使用.process /i 指定进程地址 因为要对用户态代码下断点,这里不用/p,而使用/i If you want to use the kernel debugger to set breakpoints in user space, use the/i option to switch the target to the correct process context. g继续,再次发生int 3中断后,进程Context就已切换,使用!process查看确认。 reload符号文件。 bu, bp下用户态断点。 # ln [address] 搜索离address最近的符号名(list nearest symbols) # 事件处理 可以通过菜单Debug->Event Filter…设置 sx 显示各个事件的代码和目前的处理选项 sx {e|d|i|n} [command] , e|d|i|n分别对应Enabled, Disabled,Output和Ignore 比如 sxe ld user32.dll 表示在加载user32.dll时设置的中断 sxr 恢复成默认设置 # 自动调试子进程 .childdbg 0 Disable child process debugging .childdbg 1 Attach child process automatically ``` ``` Last modification:January 16th, 2021 at 01:07 pm © 允许规范转载 Support 确定不打赏一下支持博主吗 ×Close Appreciate the author Sweeping payments Pay by AliPay