Windbg 命令的每个结果作为脚本中的参数 [英] Windbg command's each result as parameter in script

查看:36
本文介绍了Windbg 命令的每个结果作为脚本中的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算在进程转储的特定内存区域中搜索操作码.

I intend to search opcodes in specific memory area in process's dump.

我想在搜索时有一些条件.

I want to have some conditions while searching.

喜欢:$$><<>script.wds #call 00400000 L?01000000

like: $$><<>script.wds #call 00400000 L? 01000000

for(00400000 ~ 01000000)
{
    // this condition is if argument's opcode which is address is not in this area 
   .if(arg1's opcode !in 00400000 ~ 01000000)
      .print arg1
}

推荐答案

您可以组合使用 #, .foreach$spat.

You can use a combination of #, .foreach and $spat.

假设您想在 notepad!WinMain 中找到几个第一个 call 操作码.你可以这样做:

Lets say you want to find the few first call opcodes in notepad!WinMain. You could do something like this:

0:000> .foreach (addr {# call notepad!WinMain L20}) { .if ($spat("addr", "notepad!*:")) {.echo addr} }
notepad!WinMain+0xa:
notepad!WinMain+0x19:
notepad!WinMain+0x20:
notepad!WinMain+0x33:
notepad!WinMain+0x39:
notepad!WinMain+0x45:

现在是解释.

# call notepad!WinMain L20 在指定范围的反汇编中搜索字符串call".这是输出:

# call notepad!WinMain L20 searches for the string "call" in the disassembly on the specified range. This is the output:

0:000> # call notepad!WinMain L20
notepad!WinMain+0xa:
01002940 ff1514110001    call    dword ptr [notepad!_imp__GetCommandLineW (01001114)]
notepad!WinMain+0x19:
0100294f ff151c120001    call    dword ptr [notepad!_imp__GetSystemMetrics (0100121c)]
notepad!WinMain+0x20:
01002956 ff1510110001    call    dword ptr [notepad!_imp__GetProcAddress (01001110)]
notepad!WinMain+0x33:
01002969 ffd0            call    eax
notepad!WinMain+0x39:
0100296f e874f2ffff      call    notepad!SkipProgramName (01001be8)
notepad!WinMain+0x45:
0100297b e8e51b0000      call    notepad!NPInit (01004565)

.foreach (var {cmd}) {commands} 执行 cmd,在空格处分割输出,并执行 {commands}对于它获得的每个令牌,var"被替换为该令牌一次.

The .foreach (var {cmd}) {commands} executes cmd, splits the output at whitespaces, and executes {commands} once for each of the tokens it got with "var" being replaced with that token.

如果没有 .if,我们会得到类似的结果:

Without the .if we'd get something like:

0:000> .foreach (addr {# call notepad!WinMain L20}) {.echo addr}
notepad!WinMain+0xa:
01002940
ff1514110001
call
dword
ptr
[notepad!_imp__GetCommandLineW
(01001114)]
notepad!WinMain+0x19:
0100294f
ff151c120001
call
dword
ptr
[notepad!_imp__GetSystemMetrics
 .
 .
 .

最后我们添加 .if 来检查我们的令牌是否以notepad!"开头并以:"结尾.请注意,我们必须在最后测试冒号.否则我们可能会得到notepad!SkipProgramName"和notepad!NPInit".甚至测试notepad!WinMain*"还不够,因为它可能是本地跳转的目标.

Finally we add the .if to check whether our token starts with "notepad!" and ends with ":". Note that we have to test for the colon at the end. Otherwise we might get "notepad!SkipProgramName" and "notepad!NPInit". Even testing for "notepad!WinMain*" isn't enough, since it might be the target of local jumps.

现在,如果你想把这个地址传递给任何命令,你必须去掉addr别名.foreach命令末尾的冒号.我不确定有没有办法做到这一点,所以我们做最后一个技巧.每次我们找到符合模式的 addr 时,我们都会设置一个标志,并在每次迭代时检查该标志.如果该标志被提升,我们将使用当前令牌.由于 # 的输出形式为

Now, if you want to pass this address to any command, you have to get rid of the colon at the end of the addr alias the .foreach command created. I'm not sure there's even a way to do it, so we do one last trick. Every time we find and addr that fits the pattern we set a flag, and at every iteration we check the flag. If the flag is raised, we use the current token. Since the output of # is of the form

Symbol:
address opcode_byte opcode_mnemonic argument ...

与我们的模式匹配的符号后面的标记是一个干净的地址.

The token following the symbol that matches our pattern is a clean address.

例如,以下命令为找到的每个 call 反汇编两个操作码:

For example, the following command disassembles two opcode for each call found:

0:000> .foreach (addr {# call notepad!WinMain L20}) { .if (@$t0==1) { u addr L2; r @$t0=0;}; .if ($spat("addr", "notepad!*:")) { r @$t0 = 1} }
notepad!WinMain+0xa:
01002940 ff1514110001    call    dword ptr [notepad!_imp__GetCommandLineW (01001114)]
01002946 68d8130001      push    offset notepad!`string' (010013d8)
notepad!WinMain+0x19:
0100294f ff151c120001    call    dword ptr [notepad!_imp__GetSystemMetrics (0100121c)]
01002955 50              push    eax
notepad!WinMain+0x20:
01002956 ff1510110001    call    dword ptr [notepad!_imp__GetProcAddress (01001110)]
0100295c 33f6            xor     esi,esi
notepad!WinMain+0x33:
01002969 ffd0            call    eax
0100296b ff7514          push    dword ptr [ebp+14h]
notepad!WinMain+0x39:
0100296f e874f2ffff      call    notepad!SkipProgramName (01001be8)
01002974 50              push    eax
notepad!WinMain+0x45:
0100297b e8e51b0000      call    notepad!NPInit (01004565)
01002980 85c0            test    eax,eax

(伪寄存器 $t0 是标志.)

(The pseudo-register $t0 is the flag.)

现在,在完成这个恐怖之后,我加入 Thomas 建议您使用 PyKd 如果你想更进一步.

And now, after this horror is done I join Thomas in suggesting you use PyKd if you want to go even a further beyond that.

我们可以使用 WinDbg 可怕的脚本语言来做到这一点的事实并不意味着我们应该.

The mere fact that we can do this using WinDbg's awful awful scripting language doesn't mean that we should.

这篇关于Windbg 命令的每个结果作为脚本中的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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