Windbg 命令的每个结果作为脚本中的参数 [英] Windbg command's each result as parameter in script
问题描述
我打算在进程转储的特定内存区域中搜索操作码.
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
}
推荐答案
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屋!