问题 Windbg脚本中的字符串比较


使用Windbg脚本我想检查任何函数的参数中是否存在某个字符串。

0:000> g
Breakpoint 0 hit
eax=00000001 ebx=00000000 ecx=00422fc6 edx=00000000 esi=03d574e8 edi=00000005
eip=76d8fd3f esp=000cf7ac ebp=000cf7c8 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
USER32!MessageBoxW:
76d8fd3f 8bff            mov     edi,edi

0:000> du poi(esp+8)
03d574e8  "Cannot find "hello""

这里传递给第二个参数 MessageBoxW 是 Cannot find "hello"

所以我想检查一下字符串的存在 hello 在第二个参数里面。

基于此 MSDN文章,我尝试了以下命令,但它不起作用:

0:000> r $t1 = poi(esp+8)
0:000> as /mu $MSG $t1
0:000> .echo ${$MSG}
Cannot find "hello"
0:000> .if ($spat(@"${MSG}","*hello*") == 0) {.echo NotFound} .else {.echo Found}
NotFound

它应该回来 Found 我猜!

谢谢。


9149
2018-03-31 15:38


起源

如果你有双引号内的双引号,如“找不到”你好“”那么$ spat将无法工作,因为它需要引用字符串“$ {foo}”将成为“找不到”写一个简单的strcmp扩展并通过你的搜索你将更好的关闭iirc我发布了一个比较代码的字符串 - blabb
我已经更新了我的答案,提供了有关@“$ {MSG}”的更多详细信息以及使用内置WinDbg命令的另一种选择。 - Thomas Weller


答案:


逃避$ {MSG}有什么问题?

在里面 .if 你用的命令, ${MSG} 由于失踪而没有被替换 $。尝试搜索 味精 作为证据:

0:001> .if ($spat(@"${MSG}","*MSG*") == 0) {.echo NotFound} .else {.echo Found}
Found

它被取代了

0:001> .if ($spat(${$MSG},"*hello*") == 0) {.echo NotFound} .else {.echo Found}
Syntax error at '(Cannot find "hello","*hello*") == 0) {.echo NotFound} .else {.echo Found}'

但缺少之前有引号 不能。它也被取代了

0:001> .if ($spat("${$MSG}","*hello*") == 0) {.echo NotFound} .else {.echo Found}
Syntax error at '("Cannot find "hello"","*hello*") == 0) {.echo NotFound} .else {.echo Found}'

但在那里,引号由字符串内的引号关闭。而且, @ 符号没有帮助:

0:001> .if ($spat(@"${$MSG}","*hello*") == 0) {.echo NotFound} .else {.echo Found}
Syntax error at '(@"Cannot find "hello"","*hello*") == 0) {.echo NotFound} .else {.echo Found}'

所以这是恕我直言,他们忘了在WinDbg中考虑转义字符的情况之一。非常令人沮丧,总是一个错误的来源。

PyKD扩展的解决方案

幸运的是有 PyKD 并检查字符串的代码是

>>> "hello" in loadWStr(ptrPtr(reg("esp")+8))
True

reg("esp") 获取ESP寄存器的值。 +8 当然增加了8个。 ptrPtr() 从该地址获取指针大小的值。 loadWStr() 从该值读取,直到它达到NUL字符。 "hello" in 执行查找操作。你也可以使用 .find("hello")>0

这是我尝试的方式:

0:003> .dvalloc 2000
Allocated 2000 bytes starting at 00470000
0:003> eu 00470000 "Cannot find \"hello\""
0:003> du 00470000 
00470000  "Cannot find "hello""
0:003> ep 00470000+1008 00470000 
0:003> r esp=00470000+1000
0:003> .load E:\debug\Extensions\pykd\x86\pykd.dll
0:003> !pycmd
Python 2.7.8 |Anaconda 2.1.0 (32-bit)| (default, Jul  2 2014, 15:13:35) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> "hello" in loadWStr(ptrPtr(reg("esp")+8))
True
>>> exit()

您可以将以下代码放入.PY文件中

from pykd import * 
print "hello" in loadWStr(ptrPtr(reg("esp")+8))

然后在没有交互式控制台的情况下运行它:

0:003> !py e:\debug\hello.py
True

使用WinDbg解决方案

在WinDbg中,您需要删除引号。一种方法是 .foreach

0:001> .foreach (token {.echo $MSG}){.echo ${token}}
Cannot
find
hello

输出不再包含引号。让我们将此输出分配给另一个别名:

0:001> as /c NOQ .foreach (token {.echo ${$MSG}}){.echo ${token}}

使用这个新别名,您的命令将起作用:

0:001> .if ($spat("${NOQ}","*hello*") == 0) {.echo NotFound} .else {.echo Found}
Found

9
2018-03-31 19:35



我不知道pykd。太酷了! - Brian Rasmussen
谢谢!毫无疑问我想要类似的东西。但即使是windbg脚本也会让调试过程变得非常慢,而且pykd会让它变得更慢:(让我们看看我是否得到任何基于wds的答案.. :) - Dev.K.
很好的解释和例子!你觉得,@ Deb.K。提到,PyKD明显比windbg脚本慢? - Marc Sherman
@MarcSherman:对不起,我没有测量到很少使用断点。当然,在经常遇到断点时,性能是一个重点。我正在考虑将此作为自己的问题发布,但我需要为此编写一个场景(SSCCE,可能是C ++)。 - Thomas Weller


来自评论:

让我们看看我是否得到任何基于WDS的答案。

很难相信你想去长流浪汉。但好吧,这就是WinDbg内置解决方案:

r $t9=1;.foreach /ps fffff (endaddr {s -[1]w 00570000 L1000 0}) {.foreach /ps fffff (findaddr {s -[1]u 00570000 ${endaddr} "hello"}) {r $t9=2} }; .if (@$t9==2) { .echo "Found"} .else {.echo "Not Found"}

它能做什么?好吧,我把它作为练习留给你,下面的破坏者。

  r $t9=1; 将T9伪寄存器设置为定义的值,以便它不会意外地等于稍后用于比较的值。

  s -[1]w 00570000 L1000 0 记忆搜索DWORD(w)值为0,等于字符串的Unicode结尾。 [1] 仅将输出限制为地址。

  .foreach /ps fffff (endaddr { ... }) {...}; 将地址分配给endaddr变量。 /ps fffff 如果有很多,会跳过其他调查结果。

  s -[1]u 00570000 ${endaddr} "hello" 进行内存搜索,这次是一个Unicode字符串(u),也限制地址输出([1])。

  .foreach /ps fffff (findaddr {...}) {...} 获取搜索的输出。 findaddr变量在这里未使用,但在最终命令中可能很有用,具体取决于您要实现的目标。

  r $t9=2 将T9伪寄存器更改为表示找到搜索词的值。

  .if (@$t9==2) { ... } .else { ... } 做一些基于T9伪寄存器的东西。


1
2018-04-01 13:05



谢谢!但是我在MSDN文章中看到了一个带有$ spat()的例子(提到了问题)..这似乎更容易做同样的选择,但不知何故它不能按我的意图工作..你有什么想法吗?那个功能? - Dev.K.


托马斯可能被称为走向极端

@deb如果找到匹配是主要要求,你可以尝试这样的事情

0:000> .printf "%y\n" , @eip
USER32!MessageBoxW (7e466534)
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> du poi(@esp+8)
00408168  "cannot find "hello""
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> .foreach /pS 1 /ps 100 (place { dpu @esp+8 l1 }) { s -u place l100 "\"hello\"" }
00408180  0022 0068 0065 006c 006c 006f 0022 0000  ".h.e.l.l.o."...
0040827a  0022 0068 0065 006c 006c 006f 0022 0020  ".h.e.l.l.o.". .
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> .foreach /pS 1 /ps 100 (place { dpu @esp+8 l1 }) { s -u place l100 "\"z\"" }
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> .foreach /pS 1 /ps 100 (place { dpu @esp+8 l1 }) { s -u place l100 "\"zoop\"" }
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> .foreach /pS 1 /ps 100 (place { dpu @esp+8 l1 }) { s -[l 20]u place l100 "can" }
00408168  0063 0061 006e 006e 006f 0074 0020 0066  c.a.n.n.o.t. .f.
0040819c  0063 0061 006e 006e 006f 0074 0020 0066  c.a.n.n.o.t. .f.
004081d0  0063 0061 006e 006e 006f 0074 0020 0066  c.a.n.n.o.t. .f.
00408204  0063 0061 006e 006e 006f 0074 0020 0066  c.a.n.n.o.t. .f.
00408238  0063 0061 006e 006e 006f 0074 0020 0066  c.a.n.n.o.t. .f.
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> .foreach /pS 1 /ps 100 (place { dpu @esp+8 l1 }) { s -[1]u place l100 "can" }
0x00408168
0x0040819c
0x004081d0
0x00408204
0x00408238
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> .foreach /pS 1 /ps 100 (place { dpu @esp+8 l1 }) { .foreach (vlace { s -[1]u place l100 "can"} ) {du vlace} }
00408168  "cannot find "hello""
0040819c  "cannot find "iello""
004081d0  "cannot find "jello""
00408204  "cannot find "fello""
00408238  "cannot find "kello""
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> .foreach /pS 1 /ps 100 (place { dpu @esp+8 l1 }) { .foreach (vlace { s -[1]u place l100 "ello"} ) {du vlace} } 
00408184  "ello""
004081b8  "ello""
004081ec  "ello""
00408220  "ello""
00408254  "ello""
0040827e  "ello" baby"
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> lsf msgboxw.cpp
msgboxw.cpp
0:000> $ ----------------------------------------------------------------------------------------------------------------------
0:000> ls 0,15
     1: #include <windows.h>
     2: #pragma comment(lib,"user32.lib")
     3: int main (void)
     4: {
     5:     MessageBoxW(0,L"cannot find \"hello\"",L"test",0);
     6:     MessageBoxW(0,L"cannot find \"iello\"",L"test",0);
     7:     MessageBoxW(0,L"cannot find \"jello\"",L"test",0);
     8:     MessageBoxW(0,L"cannot find \"fello\"",L"test",0);
     9:     MessageBoxW(0,L"cannot find \"kello\"",L"test",0);
    10:     MessageBoxW(0,L"saying \"hello\" baby",L"test",0);
    11: return 0;
    12: }
    13: 
    14: 
0:000> $ ----------------------------------------------------------------------------------------------------------------------

1
2018-04-02 10:04