【问题标题】:Windbg scripting assigning the result of a command to a variableWindbg 脚本将命令的结果分配给变量
【发布时间】:2018-09-05 13:10:07
【问题描述】:

我经常需要以相同的方式调查转储文件,并且我希望将其自动化。我正在使用 Windbg 作为工具,并且正在考虑使用 Windbg 脚本。

我已经对 PYKD 进行了一些初步尝试,但我不太喜欢开销,所以我选择了标准的 Windbg 脚本,但这会变成一场噩梦,让我告诉你我想要什么做:

0:001> kb
 # RetAddr           : Args to Child                                                           : Call Site
00 00007ffc`26272685 : ffffffff`fffffffe 00007ff7`06e563f0 00007ff7`00000000 0000005a`1fb6fd70 : user32!NtUserGetMessage+0xa
01 00007ff7`06d87596 : 00000000`00000008 00007ff7`06e5d048 00000000`00007c1c 0000005a`00000004 : user32!GetMessageW+0x25
02 00007ff7`06d87673 : 0000005a`1f2b3710 00007ff7`06e5c7d0 0000005a`1f2ac270 00000000`00000002 : <Application>!CServiceModule::Run+0x8ee [sourcefile.cpp @ 1905] 
03 00007ffc`26875ada : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : <Application>!CServiceModule::ServiceMain+0x63 [sourcefile.cpp @ 1379] 
04 00007ffc`26ef13d2 : 00007ffc`26875aa0 0000005a`1f2ac270 00000000`00000000 00000000`00000000 : sechost!ScSvcctrlThreadA+0x3a
05 00007ffc`270454f4 : 00007ffc`26ef13b0 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0x22
06 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x34
0:001> dx Debugger.Sessions[0].Processes[26520].Threads[14812].Stack.Frames[2].SwitchTo();dv /t /v
// The second command "dx ..." happens by clicking on the DML link of the line, corresponding with the line, containing "CServiceModule::Run".

现在,如何在 Windbg 脚本中执行此操作?

  1. 启动kb 命令并将结果放入变量中。 (怎么做?我已经尝试过使用asaS,但似乎都不起作用)
  2. 如果我无法将整个kb 结果转化为一个变量,请尝试使用.foreach,如下例所示:

    .foreach ( token { kb} ) 
    {
     .printf "TEST\n"
    }
    

    => 即使这样也不起作用:kb 有大约 8 行结果,而单词 TEST 打印了 78 次。

  3. 不要打印单词“TEST”,而是打印变量 token 并查看它的样子。
    => 怎么做?我已经尝试过.printf "%msu \n" , ${token}@$token,...但没有任何效果。

  4. 即使我得到这个工作:我怎样才能进行字符串操作,十进制/十六进制数字转换,...​​?

  5. 不要忘记:如何编译这样的脚本?我目前正在尝试在 Windbg 中运行脚本,有时会出现编译错误,但那些非常不可读(我添加了一个新行,导致出现问题,但并发症错误(不是拼写错误)甚至没有提到新添加的行)。

您可能会说:看看this URL 下提到的示例,但我找不到一个正在运行的标准 Windbg 命令示例,并将其结果存储在一个变量中(即我需要做的第一件事)。

如果我的脚本正常工作,我可能会将这篇文章变成一般的“Windbg 脚本常见问题解答”,以解决上述(和新添加的)问题。

第一次回答后编辑
我意识到我误用了kb 命令:我需要使用的实际命令是~* k,结果如下:

(小注:我只是截图,而不是文字副本,为了强调DML超链接)

如您所见,有一些DML结果,我想“点击”一下,包含CServiceModule::Run。当我手动执行此操作时,似乎有对以下命令的翻译:

dx Debugger.Sessions[0].Processes[26520].Threads[14812].Stack.Frames[2].SwitchTo()

这里的 26520 是 6798 的 HexToDec 转换,
而14812是39DC的HexToDec转换。
(均取自截图Id: 6798.39dc

所以我“需要”字符串操作和 HexToDec 转换来模拟 DML 点击。但是,如果您知道将这个“点击”操作放入脚本的更简单方法,我将非常感谢!

【问题讨论】:

    标签: debugging scripting windbg dump


    【解决方案1】:

    foreach 空格是分隔符 此命令不适用于读取行

    如果您想打印令牌,请在别名解释器中按原样使用它

    0:001> kb
     # ChildEBP RetAddr  Args to Child              
    00 0147fa44 7706f20f 7642d6f7 00000000 00000000 ntdll!DbgBreakPoint
    01 0147fa74 75d1ed6c 00000000 0147fac0 770337eb ntdll!DbgUiRemoteBreakin+0x3c
    02 0147fa80 770337eb 00000000 7642d643 00000000 kernel32!BaseThreadInitThunk+0xe
    03 0147fac0 770337be 7706f1d3 00000000 00000000 ntdll!__RtlUserThreadStart+0x70
    04 0147fad8 00000000 7706f1d3 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b
    0:001> r $t0 =0 ;.foreach (token { kb } ) { r $t0 = @$t0+1 ; .printf "\"token\" %2d  ${token}\n" , @$t0 }
    "token"  1  #
    "token"  2  ChildEBP
    "token"  3  RetAddr
    "token"  4  Args
    "token"  5  to
    "token"  6  Child
    "token"  7  00
    "token"  8  0147fa44
    "token"  9  7706f20f
    "token" 10  7642d6f7
    "token" 11  00000000
    "token" 12  00000000
    "token" 13  ntdll!DbgBreakPoint
    "token" 14  01
    "token" 15  0147fa74
    "token" 16  75d1ed6c
    "token" 17  00000000
    "token" 18  0147fac0
    "token" 19  770337eb
    "token" 20  ntdll!DbgUiRemoteBreakin+0x3c
    "token" 21  02
    "token" 22  0147fa80
    "token" 23  770337eb
    "token" 24  00000000
    "token" 25  7642d643
    "token" 26  00000000
    "token" 27  kernel32!BaseThreadInitThunk+0xe
    "token" 28  03
    "token" 29  0147fac0
    "token" 30  770337be
    "token" 31  7706f1d3
    "token" 32  00000000
    "token" 33  00000000
    "token" 34  ntdll!__RtlUserThreadStart+0x70
    "token" 35  04
    "token" 36  0147fad8
    "token" 37  00000000
    "token" 38  7706f1d3
    "token" 39  00000000
    "token" 40  00000000
    "token" 41  ntdll!_RtlUserThreadStart+0x1b
    

    我不明白您的进一步查询,所以我假设您的意图如下

    0:001> $$ putting the result of kb into a variable use javascript 
    0:001> dx @$foo = Debugger.Utility.Control.ExecuteCommand("kb")
    @$foo = Debugger.Utility.Control.ExecuteCommand("kb")                
        [0x0]            :  # ChildEBP RetAddr  Args to Child              
        [0x1]            : 00 0147fa44 7706f20f 7642d6f7 00000000 00000000 ntdll!DbgBreakPoint
        [0x2]            : 01 0147fa74 75d1ed6c 00000000 0147fac0 770337eb ntdll!DbgUiRemoteBreakin+0x3c
        [0x3]            : 02 0147fa80 770337eb 00000000 7642d643 00000000 kernel32!BaseThreadInitThunk+0xe
        [0x4]            : 03 0147fac0 770337be 7706f1d3 00000000 00000000 ntdll!__RtlUserThreadStart+0x70
        [0x5]            : 04 0147fad8 00000000 7706f1d3 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b
    0:001> dx -r0 @$foo[1]
    @$foo[1]         : 00 0147fa44 7706f20f 7642d6f7 00000000 00000000 ntdll!DbgBreakPoint
    0:001> dx -r0 @$foo[2]
    @$foo[2]         : 01 0147fa74 75d1ed6c 00000000 0147fac0 770337eb ntdll!DbgUiRemoteBreakin+0x3c
    

    再次,我不知道您要转换为十六进制或十进制
    所以下面的假设
    尝试从堆栈中提取十六进制以及大写字符串

    这样的脚本

    function log(a1,a2) 
    { 
        host.diagnostics.debugLog(a1 +"    " +a2 + "\n"); 
    }
    
    function exec (cmdstr)
    {
        return host.namespace.Debugger.Utility.Control.ExecuteCommand(cmdstr);    
    }
    
    
    function kbtok()
    {
        var temp = exec("kb")
        for ( line of temp ) 
        {
            var token = line.split(" ")
            for (tok of token)
            {
                //log(tok)
                try {
                    var num = host.parseInt64(tok,16)
                    log(tok , num)                
                }
                catch(err) {
                    log(tok.toUpperCase(), " ")
                }
    
            }
        }
    }
    

    像这样使用它

    .load jsprovider
    .scriptload ---路径----
    dx @$scriptcontents.kbtok()

    第一段中堆栈的示例输出

    0:001> dx @$scriptContents.kbtok()
    
    #     
    CHILDEBP     
    RETADDR     
    
    ARGS     
    TO     
    CHILD 
    
    
    00    0
    013bfef4    20709108
    7706f20f    1996943887
    763ed3a7    1983828903
    00000000    0
    00000000    0
    NTDLL!DBGBREAKPOINT     
    01    1
    013bff24    20709156
    75d1ed6c    1976692076
    00000000    0
    013bff70    20709232
    770337eb    1996699627
    NTDLL!DBGUIREMOTEBREAKIN+0X3C     
    02    2
    013bff30    20709168
    770337eb    1996699627
    00000000    0
    763ed3f3    1983828979
    00000000    0
    KERNEL32!BASETHREADINITTHUNK+0XE     
    03    3
    013bff70    20709232
    770337be    1996699582
    7706f1d3    1996943827
    00000000    0
    00000000    0
    NTDLL!__RTLUSERTHREADSTART+0X70     
    04    4
    013bff88    20709256
    00000000    0
    7706f1d3    1996943827
    00000000    0
    00000000    0
    NTDLL!_RTLUSERTHREADSTART+0X1B     
    @$scriptContents.kbtok()
    

    你不编译脚本 脚本被解释

    对于 windbg 脚本使用 $$>a ---脚本路径----
    对于 javascript 使用 .scriptload 命令

    【讨论】:

    • 非常感谢您的快速回复,我已经编辑了我的问题,以便更好地解释我对字符串操作和HexToDec() 转换的需求。
    • 您仍然不清楚我不想编辑我的答案并将两个未真实的答案放入同一个中,而且您似乎已经打开了一个新问题,所以我希望在那里回复(顺便说一句,如果您不介意既然你问了一个新问题来链接这个回滚你的编辑会使这个问题变得整洁)
    • 我知道不鼓励 cmets,但是...谢谢!这太有帮助了
    猜你喜欢
    • 2022-01-04
    • 1970-01-01
    • 2011-01-23
    • 2020-04-22
    • 2013-03-06
    • 2012-06-20
    • 2017-04-16
    • 2013-05-05
    • 1970-01-01
    相关资源
    最近更新 更多