【问题标题】:Windbg conditional breakpoint with string compare in a nested structureWindbg条件断点与嵌套结构中的字符串比较
【发布时间】:2014-05-13 15:43:25
【问题描述】:

只有当嵌套结构中的字符串作为参数与我选择的特定模式匹配时,我才尝试在函数内打断点,如下所示:

bp `main.c:2236` ".block { .if ( $spat(\"@@(stNames->NameComponent.Buffer)\", \"*ab*\" )){.echo \"BKP HIT! \"; .printf \"%mu str\n\",> @@(NameInfo->FinalComponent.Buffer); } .else {.echo \"NO HIT \"; .printf \"%mu str:\n\", @@(stNames->NameComponent.Buffer); gc;} } "

这个断点设置在函数的开头,在参数符号已经被解析之后。它的行为很奇怪,有时即使 $spat 中的模式不匹配它也会一直被命中,有时即使模式匹配它也不会命中。

我还尝试了this,但没有成功,因为在嵌套结构的情况下我找不到使用 poi() 命令的方法。摘录如下:

bp Kernel32!CreateFileW ".printf \"%mu\\n\", poi(esp+4); as /mu ${/v:FileName} poi(esp+4); .block{.if $spat(\"${FileName}\", \"*target*\") {.echo Hit} .else {.echo Not Yet;g;}}"

【问题讨论】:

    标签: c windbg windows-kernel


    【解决方案1】:

    表达式\"@@(stNames->NameComponent.Buffer)\" 可能是does not evaluate to a quoted string 独立评估

    在编写条件时,尽可能将条件分解
    并将它们放在一个txt文件中并将脚本文件提供给断点
    bp:32" $$>a< c:\\windscrypted.txt 这样更容易理解

    如果问题独立,提供正确答案也会很有帮助 可复制的内容

    由于我无法评估问题中难以理解的表达,我在下面提供了一个演示,看看这是否是所要求的

    帮助编译和链接

    structnest:\>type "c:\Program Files\Microsoft Visual Studio 10.0\VC\compile.bat"
    
    @ECHO OFF
    REM Compile and Link Helper Utility.
    REM Add New Entry CompileMe in Visual_Studio_IDE->Tools->ExternalTools.
    REM Provide path to this bat file in command
    REM Provide $(ItemFileName)$(ItemExt) as Arguments
    REM $(BinDir) as Initial Directory
    REM Enjoy One Click Compile & link Simple Single File Demo Sources
    @call "C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
    cl /Zi /nologo /W4 /analyze %1% /link /RELEASE
    pause
    

    源文件详细信息

    structnest:\>dir /b
    structnest.cpp
    
    structnest:\>type structnest.cpp
    #include <windows.h>
    #include <winternl.h>
    #include <stdio.h>
    #define SOMESIZE 20
    
    typedef VOID (NTAPI *g_RtlInitUnicodeString) (PUNICODE_STRING DestinationStri
    ng, PCWSTR SourceString );
    
    #pragma pack (1)
    typedef struct _OUTNEST
    {
        int a;
        int b;
        short c;
        UNICODE_STRING Nestin;
    }OutNest,*POutNest;
    #pragma pack()
    
    int main (void)
    {
        POutNest MyNest = ( POutNest  ) calloc ( 0x01  , sizeof(OutNest)   );
        PWSTR    buff   = ( PWSTR     ) calloc ( 0x30 ,  sizeof(wchar_t)   );
        HMODULE hMod = LoadLibrary("ntdll.dll");
        if ( (hMod != NULL) && (MyNest != NULL)  && (buff != NULL))
        {
            g_RtlInitUnicodeString RtlInitUnicodeString = ( g_RtlInitUnicodeString )
     GetProcAddress ( hMod , "RtlInitUnicodeString");
            if (RtlInitUnicodeString != NULL )
            {
                for (int i = 0; i< SOMESIZE; i++)
                {
                    swprintf_s(buff, 0x29 , L"this is string number %.2d",i);
    
                    RtlInitUnicodeString(&MyNest->Nestin,buff);
                    printf("%S\n",MyNest->Nestin.Buffer);
                }
                printf("done\n");
                goto getout;
            }
            printf("GetprocAddress failed\n");
            goto getout;
        }
        printf("calloc() %p %p LoadLib %p failed\n" , MyNest,buff,hMod);
    getout:
        if (MyNest)
            free(MyNest);
        if(buff)
            free(buff);
        if(hMod)
            FreeLibrary(hMod);
        return 0;
    }
    structnest:\>"c:\Program Files\Microsoft Visual Studio 10.0\VC\compile.bat" stru
    ctnest.cpp
    Setting environment for using Microsoft Visual Studio 2010 x86 tools.
    structnest.cpp
    Press any key to continue . . .
    
    structnest:\>dir /b *.exe
    structnest.exe
    
    structnest:\>structnest.exe
    this is string number 00
    this is string number 01
    this is string number 02
    this is string number 03
    this is string number 04
    this is string number 05
    this is string number 06
    this is string number 07
    this is string number 08
    this is string number 09
    this is string number 10
    this is string number 11
    this is string number 12
    this is string number 13
    this is string number 14
    this is string number 15
    this is string number 16
    this is string number 17
    this is string number 18
    this is string number 19
    done
    

    脚本文件详细信息

    structnest:\>type c:\nestedbreak.txt
    as /mu ${/v:mystr} @@( MyNest->Nestin.Buffer );
    .block { r $t0 = $spat( "${mystr}", "*11" ); }
    .if( @$t0 != 1 ) { gc } ;
    
    explanation of script file
    
    as /mu ${/v:mystr}
    Sets the alias equivalent equal to the null-terminated Unicode string 
    that begins at Address @@( MyNest->Nestin.Buffer ). 
    .block {} to force alias evaluation.
    a Pseudo register $t0 is set to the result of $spat() can be 0 or 1
    
    "${mystr}" on alias evaluation will become "this is string number 00" 
    a Double Quoted string not address or some other expression 
    
    "*11" is again a Double Quoted wild card pattern string it will match "11"
     at any position in the Input String .
    
    .if is a conditinal that will break only when @$t0 == 1 
    

    现在我们有了一个更易于理解的条件,其中每个 表达式是可独立验证的,我们在断点处使用它

    执行详情

    structnest:\>cdb -c ".lines;g main;r;.echo SET A CONDITINAL BREAK POINT AND RUN
    THE EXE;bp `:32` \" $$^>a^< c:\\nestedbreak.txt \";g ;.lastevent;.echo why did w
    e break here ? now that we broke lets go again;g;q " structnest.exe
    
    explanation as follows
    
    cdb.exe      console mode windbg;
    .lines;     load line information (lineinfo default off in cdb.exe needed to set bp on src lines)
    g main;     ( we are interested in our code for which we have src not some random system module)
    r;      print the registers to confirm we reached main properly
    .echo       just a signal to show that we are alive and kicking
    `:32` "$$>a< c:\\nestedbreak.txt"   conditional break point on src line 32 ( inner double quotes/ unaccpetable > < chars escaped )
    g;      run the exe
    .lastevent;     shows the reason why we broke;
    .echo       a signal to indicate that we broke
    g;q;        finish running the exe and quit debugger
    

    执行输出详情

    structnest:\>cdb -c ".lines;g main;r;.echo SET A CONDITINAL BREAK POINT AND RUN
    THE EXE;bp `:32` \" $$^>a^< c:\\nestedbreak.txt \";g ;.lastevent;.echo why did w
    e break here ? now that we broke lets go again;g;q " structnest.exe
    
    Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
    
    0:000> cdb: Reading initial command '.lines;g main;r;.echo SET A CONDITINAL BREA
    K POINT AND RUN THE EXE;bp `:32` " $$>a< c:\\nestedbreak.txt ";g ;.lastevent;.ec
    ho why did we break here ? now that we broke lets go again;g;q '
    
    Line number information will be loaded
    
    eax=00034180 ebx=7ffd6000 ecx=00000001 edx=0041a5f0 esi=00000000 edi=00000000
    eip=00401000 esp=0013ff7c ebp=0013ffc0 iopl=0         nv up ei pl zr na pe nc
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
    structnest!main:
    00401000 55              push    ebp
    
    
    SET A CONDITINAL BREAK POINT AND RUN THE EXE
    
    this is string number 00
    this is string number 01
    this is string number 02
    this is string number 03
    this is string number 04
    this is string number 05
    this is string number 06
    this is string number 07
    this is string number 08
    this is string number 09
    this is string number 10
    Last event: 16d0.2784: Hit breakpoint 0
      debugger time: Thu May 15 16:10:10.625 2014 (UTC + 5:30)
    why did we break here ? now that we broke lets go again
    this is string number 11
    this is string number 12
    this is string number 13
    this is string number 14
    this is string number 15
    this is string number 16
    this is string number 17
    this is string number 18
    this is string number 19
    done
    quit:
    
    structnest:\>
    

    【讨论】:

      【解决方案2】:

      您可以为windbg 使用python 扩展。它允许使用 python 回调设置条件断点。

      kd>!pycmd
      >>>myApp = module("MyApp.exe")
      >>>setBp( myApp.Func1, lambda : getParam("var2").filed3 > 10 )
      >>>quit()
      kd>g
      

      你可以看到: 1) myApp.Func1 - pykd 通过符号信息查找偏移量 2) getParam("var2") - pykd 查找函数参数 3) getParam("var2").filed3 - 使用结构很容易

      【讨论】:

      • 谢谢。例如,如果“filed3”的类型为 char * 或 wchar_t *,并且您必须将其与“my_pattern”进行比较,会怎样?
      • 当然!通过 RE 使用 C 字符串检查 field3: setBp( myApp.Func1, lambda : re.match('Nt.*File', loadWStr(getParam("var2").filed3))) 我仅将 lambda 函数用于简短声明.您可以使用任何 python“可调用”对象。
      猜你喜欢
      • 1970-01-01
      • 2018-07-15
      • 2015-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-08
      • 2015-09-03
      • 1970-01-01
      相关资源
      最近更新 更多