String comparison in Windbg script

后端 未结 3 516
感情败类
感情败类 2021-02-07 11:29

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         


        
相关标签:
3条回答
  • 2021-02-07 12:12

    What's wrong with escaping ${MSG}?

    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.

    Solution with PyKD extension

    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
    

    Solution with WinDbg

    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
    
    0 讨论(0)
  • 2021-02-07 12:17

    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> $ ----------------------------------------------------------------------------------------------------------------------
    
    0 讨论(0)
  • 2021-02-07 12:23

    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.

    0 讨论(0)
提交回复
热议问题