WinDBG 是否支持多行命令?

Does WinDBG support multi-line commands?

为了可读性,如果能够有多行“脚本”(无论调用 WinDBG 的语法是什么)代码就更好了。

例如,我想搜索一大块内存,寻找看起来有点像 wxArrayString 的东西...

r $t1 = 0xe53801c
r $t2 = 0x2e800
.for (r $t3 = 0; @$t3 < 0x400; r $t3 = @$t3 + 1) {
   .if (@@c++(
     ((int)(((MyModule!wxArrayString*)(@$t1+@$t2+(@$t3*8)))->m_compareFunction) >= 0x10000) &&
     ((int)(((MyModule!wxArrayString*)(@$t1+@$t2+(@$t3*8)))->m_pItems) >= 0x10000) &&
     (((MyModule!wxArrayString*)(@$t1+@$t2+(@$t3*8)))->m_nCount <= 5000) &&
     (((MyModule!wxArrayString*)(@$t1+@$t2+(@$t3*8)))->m_nCount > 0) &&
     (((MyModule!wxArrayString*)(@$t1+@$t2+(@$t3*8)))->m_nSize <= 10000) &&
     (((MyModule!wxArrayString*)(@$t1+@$t2+(@$t3*8)))->m_nSize > 0)
   )) {
     dx ((MyModule!wxArrayString*)(@$t1+@$t2+(@$t3*8)))
   }  
}

将其合并到一行中并不难,但如果我不必每次都想测试代码中的更改时都这样做,那就太好了。

有没有办法做到这一点(使用续行或其他魔法)?

如果您的编辑器允许并支持具有不同行尾的文件(在一个文件中!),这是可行的:

在您希望看到换行符的地方插入 Macintosh 换行符(CR;0x0D),在您希望 WinDbg 结束语句的地方插入 Unix 换行符(LF;0x0A)。

$<, $><, $$<, $$><, $$ >a<(MSDN;不是一些注入)有一些细节:

The $$>< and $>< tokens execute the commands that are found in the script file literally, which means they open the script file, replace all carriage returns with semicolons, and execute the resulting text as a single command block.

其实这种说法是错误的。它用分号代替 0x0A,即 LF(换行)而不是回车 return(CR)。

示例:

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  2E 65 63 68 6F 20 22 57 6F 77 0D 2E 65 63 68 6F  .echo "Wow..echo
00000010  20 74 68 65 72 65 20 69 73 20 61 20 6C 69 6E 65   there is a line
00000020  62 72 65 61 6B 22 0A 72 20 24 74 30 0A 6B 20 4C  break".r $t0.k L
00000030  31     

这看起来像 4 行,但将作为 1 行执行:

2:004> $$>a< b:\newline.windbg
Wow .echo there is a linebreak
$t0=00000000
 # ChildEBP RetAddr      
00 0116f508 7726c088     ntdll!LdrpDoDebuggerBreak+0x2b

WinDbg 命令解析器、脚本解析器和任何解析器都实现了……嗯……我想是以一种非常简单的方式实现的。他们没有考虑转义字符等。请注意,他们不关心 .echo",甚至会在字符串中间替换甚至替换 LF。这样的例子还有很多。

也许您想研究 Python 使用 编写脚本,实施 WinDbg 扩展或类似扩展。

numbers/address 10000 是 m_compareFunction 的 m_pItems 一个例子,而不是实际值 ??

m_compareFunction是一个函数指针

0:000> ?? labels[0].m_compareFunction
<function> * 0x00000000`00000000 

m_pItems 是一个 wxString *

0:000> ?? labels[0].m_pItems
class wxString * 0x000001c8`2553f598
   =00007ff7`cc3b8a60 npos             : 0xffffffff`ffffffff
   +0x000 m_impl           : std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
   +0x028 m_convertedToChar : wxString::ConvertedBuffer<char>

加上$t1+$t2也可以消除

无论如何把你的脚本放在像 myscript.wds 这样的 txt 文件中并使用
$$>a< myscript.wds
执行它 您可以将脚本编写为多行

:\>cat d:\myscript.wds
r? $t0 = labels
?? @$t0
?? @$t0[0]
?? @$t0[1].m_pItems
?? @$t0[3].m_nCount
:\>

已执行

0:000> $$>a< d:\myscript.wds
class wxArrayString [8] 0x00000035`350fe650
   +0x000 m_compareFunction : (null) 
   +0x008 m_nSize          : 0x20
   +0x010 m_nCount         : 0x13
   +0x018 m_pItems         : 0x000001c8`2553f598 wxString
   +0x020 m_autoSort       : 0
class wxArrayString
   +0x000 m_compareFunction : (null) 
   +0x008 m_nSize          : 0x20
   +0x010 m_nCount         : 0x13
   +0x018 m_pItems         : 0x000001c8`2553f598 wxString
   +0x020 m_autoSort       : 0
class wxString * 0x000001c8`26f40fa8
   =00007ff7`cc3b8a60 npos             : 0xffffffff`ffffffff
   +0x000 m_impl           : std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >
   +0x028 m_convertedToChar : wxString::ConvertedBuffer<char>
unsigned int64 0

还有如果你用r?你可以消除所有的铸造

0:000> r @$t0 = 0x00000035`350fe654
0:000> r? $t19 = (widgets!wxArrayString *)@$t0
0:000> ?? @$t19
class wxArrayString * 0x00000035`350fe654
   +0x000 m_compareFunction : 0x00000020`00000000     int  +2000000000
   +0x008 m_nSize          : 0x00000013`00000000
   +0x010 m_nCount         : 0x2553f598`00000000
   +0x018 m_pItems         : 0x350ff800`000001c8 wxString
   +0x020 m_autoSort       : 35