Windbg脚本将命令结果分配给变量 [英] Windbg scripting assigning the result of a command to a variable

查看:261
本文介绍了Windbg脚本将命令结果分配给变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,我需要始终以相同的方式调查转储文件,并且我想使它自动化。我正在使用Windbg作为工具,并且正在考虑使用Windbg脚本。

Regularly I need to investigate dumpfiles, always in the same way, and I'd like to automate this. I'm using Windbg as a tool, and I'm thinking of using Windbg scripting.

我已经使用PYKD进行了一些首次尝试,但是我不喜欢太多的开销,所以我选择了标准的Windbg脚本,但这真是一场噩梦,让我告诉你我想做什么:

I have done some first attempts with PYKD, but I don't like the overhead that much, so I've opted for the standard Windbg scripting, but this is getting into a nightmare, let me show you what I want to do:

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脚本中执行此操作?

Now, how to do this in a Windbg script?


  1. 启动 kb 命令并将结果放入变量中。 (如何执行?我已经尝试使用 as aS ,但似乎都不起作用)
  2. b $ b
  3. 如果我无法获得整个 kb 的一个变量,请尝试使用 .foreach ,例如以下示例:

  1. Launch the kb command and put the result in a variable. (How to do that? I already tried using as and aS but neither seems to work)
  2. If I can't get the whole kb result in one variable, try to use a .foreach, as in following example:

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

=>工作: kb 大约有8行结果,而单词 TEST 被打印78次。

=> even that is not working: kb has about 8 lines of results, while the word TEST is printed 78 times.

代替打印单词 TEST,而是打印变量 token 并查看其外观。

=>怎么做?我已经尝试过 .printf%msu \n,$ {token} @ $ token 。 ..但什么都没用。

Instead of printing the word "TEST", print the variable token and see what it looks like.
=> How to do that? I already tried .printf "%msu \n" , ${token}, or @$token, ... but nothing is working.

即使我能正常工作:如何进行字符串处理,十进制/十六进制数字转换,...​​?

Even if I get this working: how can I do string manipulation, decimal/hexadecimal number conversion, ...?

不要忘记:如何编译这样的脚本?我当前正在尝试在Windbg中运行该脚本,有时会产生编译错误,但是这些错误非常难以理解(我添加了新行,导致了问题,但是复杂错误(不是错字)甚至没有提到新添加的错误)行)。

Not to forget: how do I compile such a script? I'm currently trying to run the script in Windbg, which sometimes gives compilation errors, but those are very unreadable (I add a new line, causing a problem, but the complication error (not a typo) does not even mention that newly added line).

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

You might say: just have a look at the examples, mentioned under this URL, but I can't find one example of a standard Windbg command, being run, and have its result stored in a variable (which is the first thing I need to do).

如果我的脚本能够正常工作,我可能会将这篇文章变成一般的 Windbg脚本常见问题解答对于提到的(以及新添加的)问题。

In case I get my script working, I might turn this post into a general "Windbg scripting FAQ" for the mentioned (and newly added) questions.

在第一个答案后进行编辑

我意识到我弄错了使用 kb 命令:我需要使用的实际命令是〜* k ,给出以下结果:

Edit after first answer
I realise that I've mistaken with the kb command: the actual command I need to use is ~* k, giving following result:

(小提示:为了强调DML超链接,我只是一个屏幕截图,而不是文本副本)

(Small remark: I've just a screenshot, instead of a text copy, in order to emphasize the DML hyperlinks)

如您所见,有一些DML结果,我想在行上单击单击,其中包含 CServiceModule :: Run 。当我手动执行此操作时,似乎可以理解为以下命令:

As you can see, there are some DML results, and I would like to "click" on the line, containing CServiceModule::Run. When I do this by hand, there seems to be a translation towards the following command:

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

此处26520是6798的HexToDec转换,

和14812是39DC的HexToDec转换。

(均可从屏幕快照的 Id:6798.39dc <中检索/ code>)

Here 26520 is the HexToDec conversion of 6798,
and 14812 is the HexToDec conversion of 39DC.
(Both to be retrieved from the screenshot's Id: 6798.39dc)

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

So I "need" the string manipulation and the HexToDec conversion in order to simulate DML clicking. If, however, you know an easier way to do put this "click" action into a script, I'd very very thankful!

推荐答案

.foreach空间是定界符
,此命令并不用于读取行

for .foreach space is the delimiter this command is not meant for reading lines

如果要打印令牌,请按原样使用别名解释器

if you want to print the token use it as is in a alias interpreter

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

我不理解您的进一步查询,所以我假设您的意图低于

i do not understand your further queries so iam assuming your intent below

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

再次我不知道要转换为十六进制或dec

的内容,因此以下假设

尝试从堆栈中将十六进制表示为很好的字符串

again i don't know what you want to convert to hex or dec
so assumption below
trying to dec a hex from stack as well uppercasing strings

像这样的脚本

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 --- path ----

dx @ $ scriptcontents.kbtok()

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

第一段中的堆栈样本输出

sample output for stack in first paragraph

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()

您不编译脚本
脚本被解释

you do not compile a script scripts are interpreted

对于windbg脚本使用$$> a< ---脚本的路径----

用于javascript使用 .scriptload 命令

for a windbg script use $$>a< ---path to script----
for javascript use .scriptload command

这篇关于Windbg脚本将命令结果分配给变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆