Using Windbg script I want to check the presence of a certain string in an argument of any function.
0:000> g
Breakpoint 0 hit
eax=00000001 ebx=00000000 ecx=0
In the .if
command you used, ${MSG}
does not get replaced due to a missing $. Try searching for MSG as the proof:
0:001> .if ($spat(@"${MSG}","*MSG*") == 0) {.echo NotFound} .else {.echo Found}
Found
It gets replaced in
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}'
but that is missing has quotation marks before Cannot. It also gets replaced in
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}'
but there, the quotation marks are closed by the quotation marks inside the string. Also, the @
symbol does not help:
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}'
So this is one of those cases where IMHO they forgot to consider escape characters in WinDbg. Very frustrating and always a source of errors.
Luckily there is PyKD and the code to check for the string is
>>> "hello" in loadWStr(ptrPtr(reg("esp")+8))
True
reg("esp")
gets the value of the ESP register. +8
adds 8 of course. ptrPtr()
gets a pointer sized value from that address. loadWStr()
reads from that value until it hits a NUL character. "hello" in
performs a find operation. You could also use .find("hello")>0
.
Here's how I tried it:
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()
You can put the following code into a .PY file
from pykd import *
print "hello" in loadWStr(ptrPtr(reg("esp")+8))
And then run it without the interactive console like this:
0:003> !py e:\debug\hello.py
True
In WinDbg, you need to get rid of the quotation marks. One way to do that is .foreach
:
0:001> .foreach (token {.echo $MSG}){.echo ${token}}
Cannot
find
hello
The output does not contain quotation marks any more. Let's assign this output to another alias:
0:001> as /c NOQ .foreach (token {.echo ${$MSG}}){.echo ${token}}
With this new alias, your command will work:
0:001> .if ($spat("${NOQ}","*hello*") == 0) {.echo NotFound} .else {.echo Found}
Found
wow Thomas that is probably termed as going to the extremes
@deb if finding a match is the main requirement you can try some thing like this
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> $ ----------------------------------------------------------------------------------------------------------------------
From the comments:
Let's see if I get any WDS based answer.
Hard to believe that you want to go the long tramp. But ok, here it is, the WinDbg built-in solution:
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"}
What it does? Well, I leave that as an exercise to you, spoilers below.
r $t9=1;
sets the T9 pseudo register to a defined value so that it is not accidentally equal to the value used for comparison later.
s -[1]w 00570000 L1000 0
does a memory search for a DWORD (w
) of value 0, which is equal to a Unicode end of string.[1]
limits the output to the address only.
.foreach /ps fffff (endaddr { ... }) {...};
assigns the address to the endaddr variable./ps fffff
skips other findings if there are many.
s -[1]u 00570000 ${endaddr} "hello"
does a memory search, this time for a Unicode string (u
), also limiting to address output ([1]
).
.foreach /ps fffff (findaddr {...}) {...}
takes the output of the search. The findaddr variable is unused here but might be useful in the final command, depending on what you're trying to achieve.
r $t9=2
changes the T9 pseudo register to a value indicating that the search term was found.
.if (@$t9==2) { ... } .else { ... }
does something based on the T9 pseudo register.