常见的WinDbg命令

http://www.windbg.info/doc/1-common-cmds.html

1)内置帮助命令9)例外,事件和崩溃分析17)有关变量的信息

切换示例 折叠所有示例

2)General WinDbg的命令(清除屏幕,..)10)加载的模块和图像信息18)记忆PDF PDF
3)调试会话(附加,分离,...)11)过程相关信息19)操作内存范围
4)表达和命令12)线程相关信息20)记忆:堆
5)调试器标记语言(DML)13)断点21)应用程序验证程序
6)主要扩展14)追踪和踩踏(F10,F11)22)记录扩展名(logexts.dll)
7)符号15)调用堆栈 
8)来源16)登记册 



1)内置帮助命令
CMD变种/参数描述

? 
?/ d

显示常规命令将常规命令 
显示为DML

。救命

.help 
.help / 
D.help / D a *

显示。命令 
显示。DML格式的命令(给出顶部链接栏) 
显示。以*(通配符)作为DML开头的命令

。链

.chain 
.chain / D.

列出所有加载的调试器扩展将 
所有加载的调试器扩展列为DML(扩展名链接到.extmatch)

.extmatch

.extmatch / e ExtDLL FunctionFilter 
.extmatch / D / e ExtDLL FunctionFilter

显示扩展DLL的所有导出函数。FunctionFilter =通配符字符串 
以DML格式相同(函数链接到“!ExtName.help FuncName”命令) 

示例:.extmatch / D / e uext * (显示uext.dll的所有导出函数)

.hh

.hh 
.hh文字

打开WinDbg的帮助 
文本=要在帮助文件索引中查找的文本 
示例:.hh dt

上 上

2)General WinDbg的命令(显示版本,清除屏幕等)
CMD变种/参数描述

 

转储调试器和加载的扩展DLL的版本信息

vercommand

 

用于启动调试器的转储命令行

vertarget

 

目标计算机的版本

CTRL + ALT + V

 

切换详细模式ON / OFF 
在详细模式下,某些命令(例如寄存器转储)具有更详细的输出。

ñ

n [8 | 10 | 16]

设置数字基数

.formats

.formats Expression

显示数字格式=计算数值表达式或符号,并以多种数字格式显示(十六进制,十进制,八进制,二进制,时间等)。 
示例1:。格式5 
示例2:.formats poi(nLocal1)== .formats @@($!nLocal1)

.CLS

 

清除屏幕

.lastevent

 

显示最近发生的异常或事件(调试器等待的原因?)

.effmach

.effmach 
.effmach。 
.effmach# 
.effmach x86 | amd64 | ia64 | EBC

转储有效机器(x86,amd64,..): 
使用目标计算机的本机处理器模式 
使用为最近事件执行的代码的处理器模式 
使用x86,amd64,ia64或ebc处理器模式 

此设置会影响许多调试器功能: 
- >哪个处理器的开卷用于堆栈跟踪 
- >哪个处理器的寄存器组有效

。时间

 

显示时间(系统启动,处理,内核时间,用户时间)

上 上

3)调试会话(附加,分离,...)
CMD变种/参数描述

。连接

PID

附加到一个过程

。分离

 

结束调试会话,但保持任何用户模式目标应用程序运行

q

q,qq

退出=结束调试会话并终止目标应用程序 
远程调试:q =无效; qq =终止调试服务器

。重新开始

 

重启目标应用程序

上 上

4)表达式和命令
CMD变种/参数描述

;

 

命令分隔符(cm1; cm2; ..)

?表达 
?? 表达

计算表达式(使用默认计算器) 
评估c ++表达式

.expr


.expr 
.expr / q 
.expr / s c ++ 
.expr / s masm

选择默认表达式计算器 
显示当前计算器 
显示可用的计算器 
c ++设置为默认表达式计算器 
masm设置为默认表达式计算器

*

* [任何文字]

注释行说明符 
终止于:行尾

$$

$$ [任何文字]

注释说明符 
终止于:行尾或分号

。回声

.echo String 
.echo“String”

Echo Comment - > comment text + echo it 
终止于:行尾或分号 
使用$$标记或*标记,调试器将忽略输入的文本而不回显它。

上 上

5)调试器标记语言(DML) 

从6.6.07版本的调试器开始,包括一个增强调试器和扩展输出的新机制:DML。 
DML允许输出以标记的形式包含指令和额外的非显示信息。 
调试器用户界面解析出额外信息以提供新行为。 

DML主要用于解决两个问题:
  • 链接相关信息
  • 调试器和扩展功能的可发现性
CMD变种/参数描述

.dml_start

 

踢其他DML命令

.prefer_dml

.prefer_dml [1 | 0]

全局设置:DML增强命令应该默认为DML吗? 
请注意,许多命令如k,lm,..之后输出DML内容。

.help / D.

 

.help有一个新的DML模式,其中给出了一个顶部链接

.chain / D.

 

.chain有一个新的DML模式,其中扩展链接到.extmatch

.extmatch / D.

 

.extmatch有一种新的DML格式,其中导出的函数链接到“!ExtName.help FuncName”命令

LMD

 

lm有一个新的DML模式,其中模块名称链接到lmv命令

千米

 

k具有新的DML模式,其中帧编号链接到.frame / dv

.dml_flow



.dml_flow StartAddr TargetAddr

允许交互式探索函数的代码流。

  1. 从给定的起始地址开始为函数构建代码流图(类似于uf)
  2. 显示给定目标地址的基本块以及当前块引用的引用块和块的链接
示例:.dml_flow CreateRemoteThread CreateRemoteThread + 30

 

上 上

6)主要扩展
CMD变种/参数显示支持的命令..

!Ext.help

 

一般扩展

!Exts.help

 

- || -

!Uext.help

 

用户模式扩展(非特定于操作系统)

!Ntsdexts.help

 

用户模式扩展(特定于操作系统)

!logexts.help

 

记录器扩展

!clr10 \ sos.help

 

调试托管代码

!wow64exts.help

 

Wow64调试器扩展

!Wdfkd.help

 

内核模式驱动程序框架扩展

!Gdikdx.help

 

图形驱动扩展

..

 

 

!NAME.help



!NAME.help功能

显示有关导出函数的详细帮助 
NAME =扩展DLL 
占位符FUNCTION =导出函数的占位符 

示例:!Ntsdexts.help句柄 (显示详细帮助!Ntsdexts.handle)

上 上

7)符号
CMD变种/参数描述

LD

ld ModuleName 
ld *


为所有模块加载模块 加载符号的符号

!符号

 

!sym 
!sym吵闹 
!sym安静

获取符号加载状态 
设置噪声符号加载(调试器显示有关其符号搜索的信息) 
设置安静符号加载(=默认值)

X

[选项]模块!符号 
/ t .. 
/ v .. 
/ a .. 
/ n .. 
/ z ..

检查符号:显示与指定模式匹配的符号, 
数据类型 
详细(符号类型和大小) 
按地址 
排序按名称 
排序按大小排序(函数符号的“大小”是内存中函数的大小)

LN


ln Addr

列出最近符号 =显示给定地址处或附近的符号。有用的:

  • 确定指针指向的是什么
  • 查看损坏的堆栈以确定哪个程序进行了调用

 

.sympath

.sympath 
.sympath +

显示或设置符号搜索路径 
将目录附加到上一个符号路径

.symopt

.symopt 
.symopt + Flags 
.symopt- Flags

显示当前符号选项 
添加选项 
删除选项

.symfix

.symfix 
.symfix + DownstreamStore

将符号存储路径设置为自动指向http://msdl.microsoft.com/download/symbols 
+ =将其附加到现有路径 
DownstreamStore =将用作下游存储的目录。默认为WinDbgInstallationDir \ Sym。

.reload

.reload 
.reload [/ f | / v] 
.reload [/ f | / v]模块

重新加载所有模块的符号信息** 
f =强制立即符号加载(覆盖延迟加载); v =详细模式 
Module =仅适用于模块 

**注意:.reload命令实际上不会导致读取符号信息。它只是让调试器知道符号文件可能已经改变,或者应该将新模块添加到模块列表中。要强制执行实际符号加载,请使用/ f选项或ld(加载符号)命令。

 坍方

X *!列出所有模块
x ntdll!*列出ntdll的所有符号
x / t / v MyDll!*使用数据类型,符号类型和大小列出MyDll中的所有符号
x kernel32!* LoadLib *列出kernel32中包含单词LoadLib的所有符号
 
.sympath + C:\ MoreSymbols从C:\ MoreSymbols(文件夹位置)添加符号
 
.reload / f @“ntdll.dll”立即重新加载ntdll.dll的符号。
.reload / f @“C:\ WINNT \ System32 \ verifier.dll”重新加载验证者的符号。使用给定的路径。

还要检查“!lmi”命令。

上 上

8)来源
CMD变种/参数描述

.srcpath

.srcpath 
.srcpath + DIR

显示或设置源搜索路径 
将目录添加到搜索到的源路径

.srcnoisy

{1 | 0}

控制噪声源负载

.lines

[-e | -d | -t]

切换源代码行支持:启用; 禁用; 切换

l(小写字母L)

l + l,ll 
l + o,lo 
l + s,ls 
l + t,lt

显示行数 
除了[s] 
源和行号 
源模式与汇编模式之外的所有内容

上 上

9)例外,事件和崩溃分析
CMD变种/参数描述

G


gH 
gN

Go 
Go异常处理 
Go not handling

.lastevent

 

发生了什么?显示最近的事件或异常

!分析

!analyze -v 
!analyze -hang 
!analyze -f

显示有关当前异常或错误检查的信息; verbose 
用户模式:分析线程堆栈以确定是否有任何线程阻塞其他线程。 
即使调试器未检测到异常,也请参见异常分析。

SX

sx 
sxe 
sxd 
sxn 
sxi 
sxr

显示具有中断状态的所有事件过滤器并处理 
中断第一次机会 
中断第二次机会 
通知; 不要将
忽略事件 
重置过滤器设置中断 为默认值

.exr

.exr-1 
.exr地址


在Addr上显示最近的异常记录 显示异常记录

.ecxr

 

显示与当前异常关联的异常上下文记录(寄存器)

!cppexr

地址

显示C ++异常的内容和类型

 坍方

exr -1显示最近的异常
.exr 7c901230在地址7c901230处显示例外
!cppexr 7c901230在地址7c901230处显示c ++异常

上 上

10)加载的模块和图像信息
CMD变种/参数描述

LM

lm [v | l | k | 你的 f] [m模式] 
lmD

列表模块; 详细| 加载符号| k-kernel或u-user only symbol info | 图像路径; 模块名称必须与
lm的DML模式匹配的 模式; 输出中包含lmv命令链接

!dll文件

!dlls
!dlls -i 
!dlls -l 
!dlls -m 
!dlls -v 
!dlls -c ModuleAddr 
!dlls - ?

所有加载的模块按负载计数 
按初始化顺序 
按加载顺序(默认) 
按内存顺序 

只有版本信息 模块在ModuleAddr 
简要帮助

!imgreloc

ImgBaseAddr

有关重新定位图像的信息

!LMI

有关模块的详细信息(包括确切的符号信息)

!DH

!dh ImgBaseAddr 
!dh -f ImgBaseAddr 
!dh -s ImgBaseAddr 
!dh -h

ImgBaseAddr的转储标头 
f =仅文件标头仅 
s =节标头 
h =简短帮助 

!lmi扩展从图像标头中提取最重要的信息并以简明的摘要格式显示。它通常比!dh更有用。

 坍方

LM显示所有已加载和已卸载的模块
lmv m kernel32显示kernel32.dll的详细信息(所有可能的信息)
LMDlm的DML变体
 
!dlls -v -c kernel32显示kernel32.dll的信息,包括load-count
!lmi kernel32显示有关kernel32的详细信息,包括符号信息
!dh kernel32显示kernel32的标头

上 上

11)过程相关信息
CMD变种/参数描述

!dml_proc

 

(DML)显示当前流程并允许钻取流程以获取更多信息

| (管)

 

打印正在调试的所有进程的状态

.tlist

 

列出系统上运行的所有进程

!PEB

 

显示进程环境块(PEB)的格式化视图

 坍方

!PEB转储进程PEB的格式化视图(仅一些信息)
r $ peb转储地址ob PEB。$ peb ==伪寄存器
dt ntdll!_PEB转储PEB结构
dt ntdll!_PEB @ $ peb -​​r递归(-r)转储我们进程的PEB

上 上

12)线程相关信息
CMD变种/参数描述

~~ 
[命令] 
〜。[命令] 
〜#[命令] 
〜数字[命令] 
~~ [TID] [命令] 
~Ns

list threads 
所有线程 
当前线程 
线程导致当前事件或异常 
线程,其序数为Number 
线程,其线程ID为TID(括号为必需) 
切换到线程N(新当前线程) 

[命令]:适用于一些常规命令比如k,r

Ë〜


〜* e CommandString 
~。e CommandString 
~#e CommandString 
~Number e CommandString

执行特定于线程的命令(CommandString =一个或多个要执行的命令): 
所有线程 
当前线程 
线程导致当前事件 
线程带序数

〜F

〜线程f

冻结线程(参见〜代表Thread语法)

〜U

〜线程你

解冻线程(参见〜用于线程语法)

〜n的

〜线程n

挂起thread =递增线程的挂起计数

-M

〜线程m

恢复线程=减少线程的暂停计数

!TEB

 

显示线程环境块(TEB)的格式化视图

!TLS

!tls -1 
!tls SlotIdx 
!tls [-1 | SlotIdx] TebAddr

-1 =转储当前线程的所有槽 
SlotIdx =转储仅指定槽 
TebAddr =指定线程; 如果省略,则使用当前线程

.ttime

 

显示线程时间(用户+内核模式)

!逃跑

[标志:0 | 1 | 2]

显示每个线程消耗的时间信息(0-用户时间,1内核时间,自创建线程以来经过的2次)。快速找出哪些线程失控或消耗太多CPU时间

!GLE

!gle 
!gle -all

转储当前线程的 
最后一个错误转储所有线程的最后一个错误 

兴趣点: 
SetLastError(dwErrCode)检查kernel32的值!g_dwLastErrorToBreakOn并可能执行DbgBreakPoint。 

if((g_dwLastErrorToBreakOn!= 0)&&(dwErrCode == g_dwLastErrorToBreakOn)) 
DbgBreakPoint(); 

缺点是只能从KERNEL32.DLL中调用SetLastError。 
其他对SetLastError的调用被重定向到位于NTDLL.DLL,RtlSetLastWin32Error中的函数。

!错误

!error ErrValue 
!error ErrValue 1

解码并显示有关错误值的信息 
将ErrValue值视为NTSTATUS代码

 坍方

〜* k调用所有线程的堆栈〜!uniqstack
~2 f冻结线程TID = 2
〜#f冻结导致当前异常的线程
〜3你解冻线程TID = 3
~2e r; K表; KD== ~2r; 〜2K; 〜2KD
〜* e!gle将重复每个扩展命令!gle为每个被调试的线程
 
!tls -1转储当前线程的所有TLS插槽
 
逃亡71(用户时间)+ 2(内核时间)+ 4(自线程启动以来经过的时间)
 
!TEB转储我们的线程TEB的格式化视图(仅一些信息)
dt ntdll!_TEB @ $ teb转储当前线程的TEB

上 上

13)断点
CMD变种/参数描述

BL

 

列出断点

公元前

bc * 
bc#[#] [#]

清除所有断点 
清除断点#

是* 
是#[#] [#]

启用所有bps 
启用bp#

BD

bd * 
bd#[#] [#]

禁用所有bps 
禁用bp#

BP

bp [地址] 
bp [地址] [“CmdString”] 

[~thrd] bp [#] [选项] [地址] [通过] [“CmdString”]

在地址
CmdString = Cmd1 处设置断点 ; CMD2; ..每次BP被击中时执行。 

~Trd ==线程也表示bp适用。 
#=断点ID 
传递=在#Passes之后激活断点(之前忽略它)

BU

bu [地址] 

见bp ..

设置未解决的断点。模块加载时设置bp

BM

bm SymPattern 
bm SymPattern [“CmdString”] 

[~thrd] bm [Options] SymPattern [#Passes] [“CmdString”]

设置符号断点。SymPattern可以包含通配符 
CmdString = Cmd1; CMD2; ..每次BP被击中时执行。 

~Trd ==线程也表示bp适用。 
Passes =在#Passes之后激活断点(之前被忽略) 

语法bm SymPattern等效于使用x SymPattern,然后在每个结果上使用bu。

BA

ba [r | w | e] [Size]地址 

[~thrd] ba [#] [r | w | e] [Size] [Options] [Addr] [Passes] [“CmdString”]

访问中断:[r =读/写,w =写,e =执行],大小= [1 | 2 | 4字节] 

[~Thrd] == bp也适用的线程。 
#=断点ID 
传递=在#Passes之后激活断点(之前忽略它)

BR

br OldID NewID [OldID2 NewID2 ...]

重新编号一个或多个断点

 坍方


使用bp,断点位置始终转换为地址。相反,bu或bm断点始终与符号值相关联。 


简单的例子
bp`mod!source.c:12`在指定的源代码处设置断点
bm myprogram!mem *SymbolPattern等同于使用x SymbolPattern
bu myModule!func加载myModule后立即设置bp
ba w4 77a456a8打破写访问
bp @@(MyClass :: MyMethod)中断方法(如果相同的方法被重载并因此存在于多个地址上,则非常有用)



Breakpoitns与选项
仅触发一次的断点
bp mod!addr / 1
在k-1传球后将开始击球的断点
bp mod!addr k



带命令的断点:命令将在命中断点时执行。
每次遇到断点时都会生成一个日志
ba w4 81a578a8“k; g”
每次击中BP时都要创建转储
bu myModule!func“.dump c:\ dump.dmp; g”
DllMain要求MYDLL - >检查原因
bu MYDLL!DllMain“j(dwo(@ esp + 8)== 1)'。echo MYDLL!DllMain - > DLL_PROCESS_ATTACH; kn';'g'”
LoadLibraryExW(anyDLL)调用 - >显示anyDLL的名称
bu kernel32!LoadLibraryExW“.echo LoadLibraryExW for - >; du dwo(@ esp + 4); g”
LoadLibraryExW(MYDLL)调用? - >仅在为MyDLL调用LoadLibrary时才中断
bu kernel32!LoadLibraryExW“; as / mu $ {/ v:MyAlias} poi(@ esp + 4); .if($ spat(\”$ {MyAlias} \“,\”* MYDLL * \“)!= 0 ){kn;} .else {g}“
  • LoadLibrary的第一个参数(在地址ESP + 4处)是指向所讨论的DLL名称的字符串指针。
  • MASM $ spat运算符会将此指针与预定义的字符串通配符进行比较,在我们的示例中为* MYDLL *
  • 不幸的是,$ spat可以接受别名或常量,但没有内存指针。这就是我们首先将我们的字符串存储到别名(MyAlias)的原因。
  • 只有当$ spat比较的模式匹配时,我们的kernel32!LoadLibraryExW断点才会命中。否则应用程序将继续执行。
跳过函数的执行
bu sioctl!DriverEntry“r eip = poi(@esp); r esp = @esp + 0xC; .echo sioctl!DriverEntry跳过; g”
  • 在函数的入口点,堆栈顶部的值包含返回地址 
    r eip = poi(@esp) - >将EIP(指令指针)设置为偏移量0x0处的值 
  • DriverEntry有2x4字节参数= 8字节+ 4字节用于返回地址= 0xC 
    r esp = @esp + 0xC - >将0xC添加到Esp(堆栈指针),有效地展开堆栈指针
bu MyApp!WinMain“r eip = poi(@esp); r esp = @esp + 0x14; .echo WinSpy!WinMain进入; g”
  • WinMain有4x4字节参数= 0x10字节+ 4字节,返回地址= 0x14


如何以编程方式在代码中设置brekpoint?
  • KERNEL32!的DebugBreak
  • NTDLL!DbgBreakPoint
  • __asm int 3(仅限x86)

上 上

14)跟踪和步进(F10,F11) 

每个步骤执行单个汇编指令或单个源代码行,具体取决于调试器是处于汇编模式还是源模式。 
使用l + t和lt命令或WinDbg工具栏上的按钮在这些模式之间切换。
CMD变种/参数描述

g(F5)


gu

Go(F5) 
Go up =执行直到当前函数完成 
gu~ = g @ $ ra 
gu~ = bp / 1 / c @ $ csp @ $ ra; g 
- > $ csp =与x86上的esp相同 
- > $ ra =当前堆栈上的返回地址

p(F10)



PR 
计数 
P [计数] “命令” 
P = StartAddress [COUNT] [ “命令”]

[〜螺纹] P [= StartAddress] [COUNT] [ “命令”]

单步 - 执行单个指令或源代码行。子程序被视为一个步骤。 

切换寄存器和标志的显示 
Count =在停止之前
逐步执行的指令或源行的计数 在执行步骤后要执行的Command = debugger命令 
StartAddress =使执行从指定的地址开始。默认是当前的EIP。 

~Thread =解冻指定的线程,冻结所有其他线程

t(F11)


..

单个跟踪 - 执行单个指令或源代码行。对于子程序,也跟踪每个步骤。

PT

pt 
..

步骤到下一次返回 - 类似于GU(上行),但保留在当前函数的上下文中 
如果EIP已经在返回指令上,则执行整个返回。返回此返回后,将继续执行,直到达到另一个返回

TT

tt 
..

跟踪下一个返回 - 类似于GU(上行),但保留在当前函数的上下文中 
如果EIP已经在返回指令上,则调试器将跟踪到返回并继续执行,直到达到另一个返回

个人计算机

电脑 
..

步骤到下一个呼叫 - 执行程序直到达到呼叫指令 
如果EIP已经在呼叫指令上,则将执行整个呼叫。返回此调用后,将继续执行,直到达到另一个调用

TC

tc 
..

跟踪下一个调用 - 执行程序直到达到调用指令 
如果EIP已经在调用指令上,调试器将跟踪调用并继续执行,直到达到另一个调用

PA

pa StopAddr 


par
pa StopAddr “Command” 
pa = StartAddress StopAddr [“Command”]

步骤解决 ; StopAddr =执行将停止的地址 
被调用的函数被视为单个单元 

切换显示的寄存器和标志 
Command =在执行步骤后要执行的调试器命令 
StartAddress =使执行从指定的地址开始。默认是当前的EIP。

TA

ta StopAddr 
..

跟踪解决 ; StopAddr =执行将停止的地址 
跟踪被调用的函数

重量

wt 

wt [Options] [= StartAddr] [EndAddr] 
wt -l Depth .. 
wt -m Module [-m Module2] .. 
wt -i Module [-i Module2] .. 
wt -oa .. 
wt -or .. 
wt -oR .. 
wt -nc .. 
wt -ns .. 
wt -nw ..

跟踪和观察数据。转到函数的开头并执行wt。它将贯穿整个函数并显示统计信息。 

StartAddr =执行开始; EndAddr =结束跟踪的地址(默认=当前函数的RET之后) 
l =跟踪调用的最大深度 
m =限制跟踪模块 
i =忽略模块中的代码 
oa =转储调用站点的实际地址 
或=转储返回寄存器值子函数的(EAX值) 
oR =适当类型的转储返回寄存器值(EAX值) 
nc =单个调用的无信息 
ns =无摘要信息 
ns =无警告

.step_filter

.step_filter 
.step_filter“FilerList” 
.step_filter / c

转储当前过滤器列表=跟踪时跳过的函数(t,ta,tc) 
FilterList = Filter 1; 过滤2; ...与要跳过的函数相关联的符号(跳过) 
清除过滤器列表 

.step_filter在汇编模式下不是很有用,因为每个函数调用都在不同的行上。

 坍方

G
g`:123`; ?POI(计数器); G执行当前程序到源行123; 打印计数器的值; 恢复执行
 
p一小步
PR切换显示寄存器
p 5“kb”5x步骤,之后执行“kb”
 
个人计算机步骤到下一个CALL指令
pa 7c801b0b步骤直到达到7c801b0b
 
重量跟踪和观察子功能
wt -l 4 -oR跟踪子功能到深度4,显示其返回值

上 上

15)调用堆栈
CMD变种/参数描述

ķ

k [n] [f] [L] [#Frames] 
kb ... 
kp ... 
kP ... 
kv ...

转储栈; n =带帧#; f =相邻帧之间的距离; L =省略源线; 显示
前3个参数 的堆栈帧数 
所有参数:参数类型+名称+值 
所有参数格式化(新行) 
FPO信息,调用约定

KD

kd [WordCnt]

显示原始堆栈数据+可能的符号信息== dds esp

千米

 

链接到.frame#; dv的DML变体

.kframes

 

设置堆栈长度。默认值为20(0x14)。

。帧

.frame 
.frame# 
。frame / r [#]

show current frame 
指定帧 #show 
寄存器值 

.frame命令指定将使用哪个本地上下文(范围)来解释局部变量,或显示当前本地上下文。 
当执行近程调用时,处理器将EIP寄存器的值(包含CALL指令之后的指令的偏移量)压入堆栈(稍后用作返回指令指针)。这是构建框架的第一步。每次进行函数调用时,都会创建另一个框架,以便被调用的函数可以访问参数,创建局部变量,并提供返回调用函数的机制。框架的组成取决于函数调用约定。

!uniqstack

!uniqstack 
!uniqstack [b | v | p] [n] 
!uniqstack - ?

显示所有线程的堆栈 
[b =前3个参数,v = FPO +调用约定,p =所有参数:参数类型+名称+值],[n =带帧#] 
简要帮助

!findstack

!findstack符号 
!findstack符号[0 | 1 | 2] 
!findstack - ?

找到包含符号或模块的所有堆栈 
[0 =仅显示TID,1 = TID +帧,2 =整个线程堆栈] 
简要帮助

 坍方

ķ显示调用堆栈
KN调用堆栈与帧号
KB显示前3个参数的调用堆栈
kb 5仅显示前5帧

从堆栈中获取3个以上的函数参数
dd ChildEBP + 8(参数从ChildEBP + 8开始) 
dd ChildEBP + 8(第X帧)== dd ESP(第X-1帧) 

 
!uniqstack获取我们进程的所有堆栈(每个线程一个)
!findstack kernel32 2显示包含“kernel32”的所有堆栈
 
。帧显示当前帧
.frame 2为本地上下文设置第2帧
.frame / r 0d在帧0中显示寄存器

上 上

16)登记册
CMD变种/参数描述

[R


Reg1,Reg2 
r Reg =  

r Reg :类型 











r Reg:[Num]类型 


〜螺纹r [Reg:[Num] Type]

转储所有寄存器 
仅转储指定的寄存器(即:r eax,edx) 
分配给寄存器的值(即:r eax = 5,edx = 6) 

类型=显示寄存器的数据格式(即:r eax:uw) 
ib =有符号字节 
ub =无符号字节 
iw =有符号字(2b) 
uw =无符号字(2b) 
id =有符号字(4b) 
ud =无符号双字(4b) 
iq =有符号qword(8b) 
uq =无符号qword(8b) ) 
f = 32位浮点 
d = 64位浮点 

Num =要显示的元素数量(即:r eax:1uw) 
默认值为完整寄存器长度,因此r eax:uw将显示两个值,因为EAX是32位寄存器。 

Thread =要从中读取寄存器的线程(即:~1 r eax

R M

rM Mask 
rM Mask Reg1,Reg2 
rM Mask Reg = Value 
..

掩码
转储指定的转储寄存器类型 仅指定来自当前掩码 
的寄存器值分配给寄存器 

掩码的标志 
0x1 =基本整数寄存器 
0x4 =浮点寄存器== rF 
0x8 =段寄存器 
0x10 = MMX寄存器 
0x20 =调试寄存器 
0x40 = SSE XMM寄存器== rX

R f值

rF 
rF Reg1,Reg2 
rF Reg =值 
..

转储所有浮点寄存器== rM 0x4 
仅转储指定的浮点寄存器
要分配给寄存器的 值

RX

rX 
rX Reg1,Reg2 
rX Reg =值 
..

转储所有SSE XMM寄存器== rM 0x40 
仅转储指定的SSE XMM寄存器
分配给寄存器的 值

R M

rm 
rm? 
面具

转储默认寄存器掩码。该掩码控制寄存器如何通过“r”显示。 
转储可能的掩码位列表 
指定显示寄存器时要使用的掩码。

 坍方

R M ?显示可能的位掩码
1仅启用整数寄存器
[R转储所有整数寄存器
r eax,edx仅转储eax和edx
r eax = 5,edx = 6为eax和edx分配新值
r:1ub只转储来自eax的第一个字节
 
rm 0x20启用调试寄存器掩码
[R转储调试寄存器
 
R f值转储所有浮点寄存器
rM 0x4转储所有浮点寄存器
rm 0x4; [R转储所有浮点寄存器

上 上

17)有关变量的信息
CMD变种/参数描述

DT

dt -h 
dt [mod!] 名称 
dt [mod!]名称字段 [字段] 
dt [mod!]名称[字段] 地址 
dt [mod!]名称* 

dt [ -n | y ] [mod!]名称[ - n | y ] [Field] [Addr] 


dt [-n | y] [mod!]名称[-n | y] [Field] [Addr] -abcehioprsv 

简要帮助 
转储变量信息 
仅转储'field-name(s)'(结构或联合) 
要转储的结构的地址 
列表符号(通配符) 

-n Name = param是一个名称(如果名称可以被误认为是地址,则使用) 
-y Name =部分匹配而不是默认完全匹配 

-a =显示新行中的数组元素及其索引 
-b = Dump仅连续块struct 
-c = Compact输出(一行中的所有字段) 
-i =不缩进子类型 
-l ListField = Field是指向列表中下一个元素的指针 
-o =忽略偏移值(struct的字段) 
-p =从物理地址转储 
-r [l] =递归转储子类型/字段(最多l级) 
-s [size] =仅对于枚举,枚举仅给定大小的类型。 
-v =详细输出。

DV

dv 
dv 模式 
dv [ / i / t / V ] [模式] 
dv [/ i / t / V / a / n / z ] [模式]

显示局部变量和参数 
vars匹配模式 
i =类型(本地,全局,参数),t =数据类型,V =内存地址或寄存器位置 
a =按地址排序,n =按名称排序,z =按大小排序

 坍方

dt ntdll!_PEB *列出包含单词_PEB的所有变量
dt ntdll!_PEB * -v列表,详细输出(包括地址和大小)
dt ntdll!_PEB * -v -s 9仅列出大小为9个字节的符号
 
dt ntdll!_PEBdump _PEB info
dt ntdll!_PEB @ $ peb转储_PEB用于我们的流程
dt ntdll!_PEB 7efde000在Addr 7efde000上转储_PEB 
您可以使用“r @ $ peb”或“!peb”获取我们流程的PEB地址。
dt ntdll!_PEB Ldr SessionId仅转储PEB的Ldr和SessionId字段
dt ntdll!_PEB Ldr -y OS *转储Ldr字段+以OS *开头的所有字段
 
dt mod!var m_cs。dump m_cs并扩展其子字段
dt mod!var m_cs ..将其子字段扩展为2个级别
 
dt ntdll!_PEB -r2递归转储(2级)
 
dv / t / i / V.使用类型信息(/ t),地址和EBP偏移量(/ V)转储局部变量,将它们分类为类别(/ i) 
注意:dv还将显示使用“this calling-convention”调用的方法的THIS指针的值”。 
BUG:在dv显示正确的值之前,您必须先执行一些命令。 
在函数的入口点,THIS指针出现在ECX中,因此您可以从那里轻松获取它。

上 上

18)记忆
CMD变种/参数描述

d *

d [A | U | C | W | W | d | ç| q | F | D] [/ c#] [地址] 













dy [b | d] ..

显示内存 [#columns to display] 
a = ascii chars 
u = Unicode chars 

b = byte + ascii 
w = word(2b) 
W = word(2b)+ ascii 
d = dword(4b) 
c = dword(4b)+ ascii 
q = qword(8b) 

f =浮点(单精度 - 4b) 
D =浮点(双精度 - 8b) 

b =二进制+字节 
d =二进制+双字

E *

e [b | w | d | q | f | D] Addr值 








e [a | 你的 za | zu] Addr“String”

编辑存储器 
b =字节 
w =字(2b) 
d = dword(4b) 
q = qword(8b) 

f =浮点(单精度 - 4b) 
D =浮点(双精度 - 8b) 

a = ascii字符串 
za = ascii string(以NULL结尾) 
u = Unicode字符串 
zu = Unicode字符串(以NULL结尾)

ds,dS


ds [/ c#] [地址] 
dS [/ c#] [地址]

转储字符串结构(struct!not null-delimited char sequence) 
s = STRING或ANSI_STRING 
S = UNICODE_STRING 

d * S


dds [/ c#] [地址] 
dqs [/ c#] [地址]

显示单词和符号(Addr中的内存假定为符号表中的一系列地址) 
dds = dwords(4b) 
dqs = qwords(8b)

dd *,dq *,dp *




dd * 
dq * 
dp * 


d * a 
d * u 
d * p

显示引用的内存 =在指定的Addr处显示指针,取消引用它,然后以各种格式显示结果位置的内存。 

第二个char确定使用的指针大小: 
dd * - > 32位指针使用 
dq * - > 64位指针使用 
dp * - >标准大小:32位或64位,具体取决于CPU架构 

第3个字符确定如何显示解除引用的内存: 
d * a - >取消引用mem作为asci chars 
d * u - >取消引用mem作为Unicode字符 
d * p - >取消引用mem作为dword或qword,具体取决于CPU架构。如果此值与任何已知符号匹配,则也会显示此符号。

DL




dl [b] Addr MaxCount大小

显示链接列表(LIST_ENTRY或SINGLE_LIST_ENTRY) 
b =以相反顺序转储(按照BLinks而不是FLinks) 
Addr =列表的起始地址 
MaxCount = max要转储的元素 
大小=每个元素的大小

使用!list为每个元素 执行一些命令列表中的元素。

!地址


!地址 -? 
!地址Addr 
!address -summary 
!address -RegionUsageXXX

显示有关目标进程使用的内存的信息 
简要帮助 
使用Addr 
Dump摘要信息
转储区域信息进程 转储指定区域(RegionUsageStack,RegionUsagePageHeap,..)

!vprot

!vprot - ? 
!vprot地址

简要帮助 
转储虚拟内存保护信息

!将mapped_file

!mapped_file - ? 
!mapped_file地址

简要帮助 
转储包含给定Addr的文件的名称

 坍方

dd 0046c6b0在0046c6b0显示dwords
dd 0046c6b0 L1在0046c6b0显示1 dword
dd 0046c6b0 L3在0046c6b0显示3个dword
du 0046c6b0在0046c6b0显示Unicode字符
du 0046c6b0 L5在0046c6b0显示5个Unicode字符
 
dds esp == kd在堆栈上显示单词和符号
 
!mapped_file 00400000转储包含地址00400000的文件名
 
!地址显示我们流程的所有内存区域
!address -RegionUsageStack显示我们流程的所有堆栈区域
!地址尤其显示我们的线程堆栈的已提交子区域的信息。 
注意:对于堆栈溢出,SubRegionSize(已提交内存的大小)将很大,即:
<span style="color:#4f6b72"><span style="color:#333333"><span style="color:#333333"><span style="color:#333333">   AllocBase:SubRegionBase - <strong>SubRegionSize</strong>
   ---------------------------------------------
   001e0000:002d6000  -  0000a000</span></span></span></span>



确定线程的堆栈使用情况
<span style="color:#4f6b72"><span style="color:#333333"><span style="color:#333333">		
                堆栈标识符内存标识符^
                -------------------------------------------------- -------
-------------- < -  _TEB.StackBase SubRegionBase3 + SubRegionSize3
| |
| MEM_COMMIT |
| |
| ------------ | < -  _TEB.StackLimit SubRegionBase3 ^,SubRegionBase2 + SubRegionSize2
| PAGE_GUARD |
| ------------ | SubRegionBase2 ^,SubRegionBase1 + SubRegionSize1
| |
| MEM_RESERVED |
| |
| ------------ | < -  _TEB.DeallocationStack AllocationBase或RegionBase,SubRegionBase1 ^
  
                DeallocationStack:dt ntdll!_TEB TebAddr DeallocationStack
				</span></span></span>
从MSDN CreateThread> dwStackSize>“线程堆栈大小”: 
“每个新线程都接收自己的堆栈空间,包括已提交和已保留的内存。默认情况下,每个线程使用1 Mb的预留内存和一页已提交的内存。系统将根据需要从保留的堆栈内存中提交一个页面块。“

上 上

19)操作内存范围
CMD变种/参数描述

C

c范围DestAddr

比较记忆

m Range DestAddr

移动记忆

F

f范围模式

填充内存。Pattern =一系列字节(数字或ASCII字符)

小号

范围模式 

s - [标志] b 范围模式 


s - [标志] w 范围'模式' 
- [标志] d 范围'模式' 
- [标志] q 范围'模式' 


- [标志] 范围“模式“ 
s - [Flags] u 范围”模式“ 


s - [标志,l长度] sa 范围 
s - [标志,l长度] su 范围 


s - [标志] v 范围对象

搜索存储器 

b =字节(默认值) 
模式=一系列字节(数字或ASCII字符) 

w =字(2b) 
d = dword(4b) 
q = qword(8b) 
模式=用单引号括起来(例如, 'Tag7') 

a = ascii字符串(不能以空值终止) 
u = Unicode字符串(不能以空值终止) 
Pattern =用双引号括起来(例如,“This string”) 

搜索包含printable的任何内存ascii strings 
搜索包含可打印Unicode字符串的任何内存 
长度=此类字符串的最小长度; 默认值为3个字符 

搜索相同类型的对象。 
Object =指向Object或Object本身的指针的Addr 

标志 
------- 
w =仅搜索可写内存 
1 =仅输出搜索匹配的地址(如果使用.foreach,则非常有用)
标志必须包围通过一组没有空格的括号。 
示例:s - [swl 10]类型范围模式

.holdmem


.holdmem -a Range 
.holdmem -o 
.holdmem -c Range 
.holdmem -D 
.holdmem -d {Range | 地址 }

保持并比较记忆。比较是按字节逐字节 
存储器范围到安全 
显示所有已保存的存储器范围 
比较所有已保存存储器范围的范围 
删除所有已保存的存储器范围 
删除指定的存储器范围(包含Addr或与Range重叠的任何已保存范围)

 坍方

c Addr(Addr + 100)DestAddr将Addr中的100个字节与DestAddr进行比较
c Addr L100 DestAddr- || -
 
m Addr L20 DestAddr从Addr移动20个字节到DestAddr
 
f地址L20'A''B''C'用模式“ABC”填充指定的内存位置,重复几次
f地址L20 41 42 43- || -
 
s 0012ff40 L20'H''''''''''o'搜索内存位置0012FF40到0012FF5F的模式“Hello”
s 0012ff40 L20 48 65 6c 6c 6f- || -
s -a 0012ff40 L20“你好”- || -
s - [w] a 0012ff40 L20“你好”只搜索可写内存

上 上

20)记忆:堆
CMD变种/参数描述

!堆

!堆- ? 

!heap 
!heap -h 
!heap -h [HeapAddr | Idx | 0] 
!heap -v [HeapAddr | Idx | 0] 
!heap -s [HeapAddr | 0] 
!heap -i [HeapAddr] 
!heap -x [-v] Address 
!heap -l

简要帮助 

索引和HeapAddr列表堆 
列表满口具有索引和范围(= startAddr(= HeapAddr),endAddr) 
详细堆信息[IDX =堆IDX,0 =所有堆] 
验证堆[IDX =堆IDX,0 =所有堆] 
摘要信息,即保留和提交的内存 [Idx = heap Idx,0 =所有堆] 
给定地址的块的详细信息
包含地址的 搜索堆块(v =搜索整个进程虚拟空间) 
搜索可能泄漏的堆块

!heap -b,-B

!heap Heap -b [alloc | realloc | free] [Tag] 
!堆Heap -B [alloc | realloc | 自由]

在堆管理器中设置条件断点[Heap = HeapAddr | Idx | 0] 
删除条件断点

!heap -flt

!heap -flt s Size 
!heap -flt r SizeMin SizeMax

转储与指定大小匹配的分配信息 
按范围过滤

!heap -stat

!heap -stat 
!heap -stat -h [HeapHandle | 0]

转储堆句柄列表 
每个AllocSize转储使用统计信息[HeapHandle =给定堆| 0 =所有堆]。 
统计信息包括每个AllocSize的AllocSize,#blocks,TotalMem。

!heap -p

!heap -p - ? 
!heap -p 
!heap -p -h HeapHandle 
!heap -p -a UserAddr 
!heap -p -all 

扩展页堆帮助 
NtGlobalFlag,HeapHandle + NormalHeap列表的摘要** 
有关包含Handle的页面堆的详细信息 
包含UserAddr的堆分配的详细信息。可用时打印回溯。 
流程中所有堆中所有分配的详细信息。 
输出包括每个HeapAlloc调用的UserAddr和AllocSize

似乎以下适用于Windows XP SP2:

a)正常堆

  1. CreateHeap - >创建一个_HEAP
  2. AllocHeap - >创建一个_HEAP_ENTRY
b)启用页面堆(gflags.exe / i MyApp.exe + hpa)
  1. CreateHeap - >创建一个_DPH_HEAP_ROOT(+ _HEAP + 2x _HEAP_ENTRY)**
  2. AllocHeap - >创建一个_DPH_HEAP_BLOCK
**启用页面堆后,每个CreateHeap调用仍然会有一个带有两个常量_HEAP_ENTRY的_HEAP。 


 
术语描述堆类型
HeapHandleHeapCreateGetProcessHeap 返回的值
对于普通堆:HeapHandle == HeapStartAddr
普通和页面
HeapAddr= startAddr = NormalHeap普通和页面
UserAddr,UserPtr=范围内的值[ HeapAlloc ... HeapAlloc + AllocSize] 
对于正常堆,此范围进一步在Heap [startAddr-endAddr]内
普通和页面
UserSize= AllocSize(传递给HeapAlloc的值)普通和页面
 
_堆= HeapHandle = HeapStartAddr 
对于每个HeapCreate,都会创建一个_HEAP结构。 
您可以使用“!heap -p -all”来获取这些地址。
正常堆
_HEAP_ENTRY对于每个HeapAlloc,都会创建一个_HEAP_ENTRY。 
您可以使用“!heap -p -all”来获取这些地址。
正常堆
 
_DPH_HEAP_ROOT=通常HeapHandle + 0x1000 
对于每个HeapCreate,都会创建一个_DPH_HEAP_ROOT。 
您可以使用“!heap -p -all”来获取这些地址。
页面堆
_DPH_HEAP_BLOCK对于每个HeapAlloc,都会创建一个_DPH_HEAP_BLOCK。 
您可以使用“!heap -p -all”来获取这些地址。
页面堆

 

 坍方

dt ntdll!_HEAPdump _HEAP struct
dt ntdll!_DPH_HEAP_ROOTdump _DPH_HEAP_ROOT struct。 
启用页面堆。然后,您可以使用“!heap -p -all”来获取进程中实际_DPH_HEAP_ROOT结构的地址。
dt ntdll!_DPH_HEAP_BLOCKdump _DPH_HEAP_BLOCK结构。 
启用页面堆。然后,您可以使用“!heap -p -all”来获取进程中实际_DPH_HEAP_BLOCK结构的地址。
 
!堆列出所有带索引和HeapAddr的堆
!堆-h列出包含范围信息的所有堆(startAddr,endAddr)
!heap -h 1具有索引1的堆的详细堆信息
!heap -s 0所有堆的摘要(保留和提交的内存,..)
 
!heap -flt s 20转储大小为20字节的堆分配
 
!heap -stat转储HeapHandle列表。HeapHandle = HeapCreate或GetProcessHeap返回的值
!heap -stat -h 00150000转储使用统计信息HeapHandle = 00150000
 
!heap 2 -b alloc mtagHeapAlloc上的断点使用索引2在堆中使用TAG = mtag进行调用
 
!heap -p转储堆句柄列表
!heap -p -a 014c6fb0堆分配的详细信息,包含地址014c6fb0 + call-stack(如果可用)
!heap -p -all转储流程中所有堆中所有分配的详细信息


谁分配了内存 - 谁叫HeapAlloc?
  1. 在GFlags中为您的图像选择“创建用户模式堆栈跟踪数据库”(gflags.exe / i MyApp.exe + ust)
  2. 从WinDbg的命令行执行!heap -p -a [UserAddr],其中[UserAddr]是您的分配地址***。
  3. 虽然!heap -p -a [UserAddr]将转储调用堆栈,但不会包含任何源信息。 
  4. 要获取源信息,您还必须在步骤1中启用页堆(gflags.exe / i MyApp.exe + ust + hpa)
  5. 做一个dt ntdll!_DPH_HEAP_BLOCK StackTrace [MyHeapBlockAddr],其中[MyHeapBlockAddr]是在步骤3中检索到的DPH_HEAP_BLOCK地址。
  6. 执行dds [StackTrace] “,其中[StackTrace]是在步骤5中检索的值。 
    请注意,dds将转储包含源信息堆栈


谁创建了一个堆 - 谁叫HeapCreate?
  1. 在GFlags中为您的图像选择“创建用户模式堆栈跟踪数据库”和“启用页堆”(gflags.exe / i MyApp.exe + ust + hpa)
  2. a)从WinDbg的命令行执行!heap -p -h [HeapHandle],其中[HeapHandle]是HeapCreate返回的值。您可以执行!heap -stat!heap -p来获取进程的所有堆句柄。 
    b)或者你可以使用!heap -p -all直接获取你进程的所有_DPH_HEAP_ROOT的地址。
  3. 做一个dt ntdll!_DPH_HEAP_ROOT CreateStackTrace [MyHeapRootAddr],其中是在步骤2中检索到的_DPH_HEAP_ROOT的地址
  4. 执行dds,其中[CreateStackTrace]是在步骤3中检索的值。


发现内存泄漏
  • 从WinDbg的命令行做一个!address -summary。 
    如果RegionUsageHeapRegionUsagePageHeap正在增长,那么堆上可能存在内存泄漏。继续以下步骤。
  1. 在GFlags中为您的图像启用“创建用户模式堆栈跟踪数据库”(gflags.exe / i MyApp.exe + ust)
  2. 从WinDbg的命令行执行!heap -stat,获取所有活动的堆块及其句柄。
  3. 做一个!heap -stat -h 0。这将列出每个AllocSize的句柄特定分配统计信息。 
    对于每个AllocSize,列出以下内容:AllocSize,#blocks和TotalMem。 使用最大TotalMem的AllocSize
  4. 做一个!heap -flt s [Size]。[Size] =我们在上一步中确定的AllocSize。此命令将列出具有该特定大小的所有块。
  5. 做一个!heap -p -a [UserAddr]来从你分配了那么多字节的地方获取堆栈跟踪。使用在步骤4中获得的[UserAddr]。
  6. 要获取源信息,您还必须在步骤1中启用页堆(gflags.exe / i MyApp.exe + ust + hpa)
  7. 做一个dt ntdll!_DPH_HEAP_BLOCK StackTrace [MyHeapBlockAddr],其中[MyHeapBlockAddr]是在步骤5中检索的DPH_HEAP_BLOCK地址。
  8. 执行dds [StackTrace] “,其中[StackTrace]是在步骤7中检索的值。 
    请注意,dds将转储包含源信息堆栈


***什么是[UserAddr]?
  1. [UserAddr]通常是HeapAlloc返回地址
    <span style="color:#4f6b72"><span style="color:#333333"><span style="color:#333333">int AllocSyze = 0x100000; // == 1 MB
    BYTE * <strong>pUserAddr</strong> =(BYTE *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,<strong>AllocSyze</strong>);</span></span></span>
  2. 通常,[UserAddr .... UserAddr + AlloSize]范围内的任何地址也是有效参数:
    <span style="color:#4f6b72"><span style="color:#333333"><span style="color:#333333">!heap -p -a [ <strong>UserAddr .... UserAddr + AlloSize</strong> ]</span></span></span>

上 上

21)应用程序验证程序 
应用程序验证程序配置文件和跟踪Microsoft Win32 API(堆,句柄,锁,线程,DLL加载/卸载等),例外,内核对象,注册表,文件系统。使用!avrf扩展程序,我们可以访问此跟踪信息!
CMD变种/参数描述

!avrf

 

显示Application Verifier选项。如果发生了应用程序验证程序停止,则显示停止的性质以及导致停止的原因。

!avrf

- ? 

-vs N 
-vs -a ADDR 

-hp N 
-hp -a ADDR 

-cs N 
-cs -a ADDR 

-dlls N 
-ex N 
-cnt 
-threads 
-trm 
-trace INDEX 
-brk [INDEX]

简要帮助 

转储vspace日志中的最后N个条目(MapViewOfFile,UnmapViewOfFile,..)。 
在vspace日志中搜索ADDR。 

HeapAlloc,HeapFree,new和delete日志 
在堆日志中搜索ADDR。 

DeleteCriticalSection API日志(最后#Entries)。~CCriticalSection隐式调用它。 
在关键部分删除日志中搜索ADDR。 

LoadLibrary / FreeLibrary日志 
异常日志 
全局计数器(WaitForSingleObject,HeapAllocation调用,...) 
线程信息+子线程的启动参数 
TerminateThread API日志 
转储堆栈跟踪与INDEX。 
dump或set / reset break触发器。

上 上

22)记录扩展(logexts.dll) 

你必须在GFlags中为你的图像启用以下选项: 
- >“创建用户模式堆栈跟踪数据库” 
- >“堆栈回溯:(Megs)” - > 10 
- >看来你好像有时还需要检查并指定GFlags中的“Debugger”字段
CMD变种/参数描述

!logexts.help

 

显示所有Logexts.dll扩展命令

!LOGE

!loge [dir]

启用日志记录+可能会初始化它,如果尚未完成。输出目录可选。

!LOGI

 

初始化(=将Logger注入目标应用程序)但不启用日志记录。

!的logD

 

禁用日志记录

!商标

!logo 
!logo [e | d] [d | t | v]

列表输出设置 
启用/禁用[d - 调试器,t - 文本文件,v - 详细日志]输出。使用logviewer.exe检查详细日志。

!logc

!logc 
!logc p# 
!logc [e | d] * 
!logc [e | d]#[#] [#]

列出所有类别
列出类别中的 API# 
启用/禁用所有类别 
启用/禁用类别#

!logb

!logb p 
!logb f

打印缓冲区内容到调试器 
刷新缓冲区到日志文件

!10gm的

!logm 
!logm [i | x] [DLL] [DLL]

显示模块包含/排除列表 
指定模块包含/排除列表

 坍方



启用19-ProcessesAndThreads和22-StringManipulation日志记录:
!LOGE启用日志记录
!logc d *禁用所有类别
!logc p 19显示类别19的API
logc e 19 22启用类别19和22
!logo dv禁用详细输出
!logo dt禁用文本输出
!logo ed启用调试器输出

在2007年11月1日至2009年1月31日期间,本文发表在software.rkuster.com上

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值