Windbg

设置 JIT debugger:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug      

REG_SZ:     Auto :            1

REG_SZ:     Debugger :    "c:\windbg.exe"  -p  %ld   -e  %ld  -g

设置 Windows Error Reporting 自动保存 dump:

  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps

  REG_EXPAND_SZ: DumpFolder:   "c:\dumps"

  REG_DWORD:       DumpType:     2(full dump)

 

Execution Data Breakpoint vs. Code Breakpoint

  

  另一个原因: 在 kernel debugging 中, Code Breakpoint 是 process relative 的, 而 ba 由于存在于寄存器 DRx 中, 因此是系统通用的.  如下

 

当遇到 C++ temlate 的时候, 由于 windbg 会把符号中的 '<' 当做 '输入' 符号, 所以导致找不到符号.

 

 

使用 64 位 windbg 调试 wow64 的程序, 分析堆栈的时候, 需要使用 .effmach 对 stack 进行调整.

 

 

监视注册表的方法: 

i.

先使用 regedit.exe 打开你想监视的键值. 

目的是将其加载到内存, 以便我们寻找 KCB(Key Control Block).

 

ii. 寻找 KCB, 

 

iii. 通过 KCB, 我们可以找到 hive.

!reg kcb e1140f08

 

iv. 通过 hive 和 cell index 找到该 key 的 virtual address.

!reg cellindex 0xe17e4758 0x862828

 

v. 解析 key 的内容.

!reg valuelist 0xe17e4758  c736382c

 

vi. 查看 value 的值.

!reg kvalue c73636ec

 

vii. 此时, 这个  c73636ec 就是该 value 的物理地址, 我们可以使用 hard breakpoint... 但是由于该 data 的内容位于地址偏移 +8 的地方, 所以对 'c73636ec + 8' 下断点即可

ba w4 c73636ec+8

 

 

viii. 此后, 再次尝试修改注册表得值, 则会触发断点.

我们使用 !process 查看当前的进程, 发现时 regedit.exe 正在对注册表的特定键值进行修改.

  

在 windbg 中启动 exe 和 attach 到一个已经启动的 exe 是不太一样的, 因为前者会对进程设置一些 gflags(通常都是 heap 的一些检查, 值是 0x70).

 

可以使用 .lastevent 查看崩溃的原因.

 

可以使用 sxe   ld  Foo.dll  来对 Foo.dll 加载到进程的行为下断点.

 

可以使用 ed   ntdll!g_dwLastErrorToBreakOn  5  对 lastError 为 5 的 api 下断点. 这样方便定位到发生了特定错误的位置.

 

可以使用 ~0f 对 0 号线程进行 freeze 操作, ~0u 对其进行 unfreeze. 可以使用 ~0n 对 suspend counter 进行递增, ~0m 进行递减.

对于线程而言, 使用 windbg 进行 freeze 和 win32 api 的 suspend 的含义是不一样的.

关于 suspend:

当一个线程被 suspend 的时候, 其内部等待一个内核对象, 该内核对象的 counter 会变为 1, 每次 suspend 都会使该值增加 1. 如图:

当这个内核对象递减到 0 的时候, 线程将会被投入继续执行. 

关于 freeze:

  使用 windbg 进行 freeze, 就是在恢复执行的时候, 不递减 suspend 的 counter, 使之无法递减到 0, 从而该线程依旧等待内核对象. 通过这种方法实现了 freeze.

 

Access Violation 只有在两种情况下才会发生:

1. 访问了 uncommit 的内存.

2. 访问方式与内存保护条件不符, 比如 write 了一块 read-only 的内存.

Full Page Heap 用于检测 heap overwrite 十分有效. 其原理是将用户分配的内存放在 page 的末端, 并将后一个 page 设置为 uncommit, 这样有任何 overwrite 的行为就会立刻被捕获.

不过也有个条件, 就是当 'alignment' 有设置的时候, 优先考虑对齐问题, 所以上图中在 'Actual User Buffer' 后面还有一段 'Alignment Padding'. 而最后那个 'Additional Guard Page' 就是 uncommit 的内存, 以便用于越界访问时捕获异常.

 

当 stack frame 被破坏时, 使用 k 则无法正常输出调用堆栈. 此时我们可以使用 dps esp L100 来对从 esp 开始的 100 个 pionter 进行解析. 通过这种方法, 可以粗糙的看出调用关系.

 

MSVCRT!exit() 的内部顺序.

注意: 

1. EXE 中的全局变量是在 worker thread 之前析构的.

2. DLL 中的全局变量是在 worker thread 之后析构的.

 

可以使用 `.reload /unl  xxx.dll`  可以加载 unloaded module, 以便解析符号.

posted @ 2014-03-24 10:18  walfud  阅读(605)  评论(0编辑  收藏  举报