Windbg 脚本中的字符串比较

String comparison in Windbg script

我想使用 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 article,我尝试了以下命令,但它不起作用:

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

应该return Found我猜!

谢谢。

转义 ${MSG} 有什么问题?

在您使用的 .if 命令中,由于缺少 $${MSG} 没有被替换。尝试搜索 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

来自评论:

Let's see if I get any WDS based answer.

很难相信你想要长期流浪。但是好吧,这就是 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 执行内存搜索以查找值为 0 的 DWORD (w),它等于字符串的 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 伪寄存器做了一些事情。

wow Thomas 这可能被称为走极端

@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> $ ----------------------------------------------------------------------------------------------------------------------