Windbg命令将每个结果作为脚本中的参数

时间:2016-02-18 02:45:06

标签: windbg

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

我希望在搜索时有一些条件。

像: $$><<> 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
}

3 个答案:

答案 0 :(得分:4)

您可以结合使用#.foreach$spat

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

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"在指定范围的反汇编中。这是输出:

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 "被那个令牌取代。

如果没有.if我们会得到类似的内容:

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来检查我们的令牌是否以" 记事本开始!"并以" "结束。请注意,我们必须在最后测试冒号。否则我们可能会得到" 记事本!SkipProgramName "和" 记事本!NPInit "。甚至测试" 记事本!WinMain * "不够,因为它可能是本地跳跃的目标。

现在,如果要将此地址传递给任何命令,则必须删除创建.foreach命令的 addr 别名末尾的冒号。我不确定是否有办法,所以我们做最后一招。每当我们找到符合模式的 addr 时,我们设置一个标志,并在每次迭代时检查标志。如果引发该标志,我们使用当前令牌。由于#的输出格式为

Symbol:
address opcode_byte opcode_mnemonic argument ...

符合我们模式的符号后面的标记是一个干净的地址。

例如,以下命令为每个找到的call分解两个操作码:

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是标志。)

现在,在这件恐怖事件发生之后,我加入Thomas建议您使用PyKd,如果您想要更进一步的话。

我们可以使用WinDbg糟糕的脚本语言来做这件事,这并不意味着我们应该

答案 1 :(得分:0)

我不确定我是否理解你的需要,但我认为它与以下内容类似。

使用伪寄存器创建一个可以完成所需操作的脚本,例如

.for(r @$t2=@$t0; @$t2<@$t1; r @$t2=@$t2+1) {.printf "%d, ", @$t2}

在伪寄存器中设置“参数”

0:000> r @$t0 = 0x4
0:000> r @$t1 = 0x10

然后运行脚本:

0:000> $$>< script.wds
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,

考虑到整个任务,我不建议在普通的WinDbg中执行此操作并使用一些更高级别的抽象,例如PyKD,因为

答案 2 :(得分:0)

你的查询不清楚你想做这样的事吗

0:000> .shell -ci ".echo"  type c:\foo.txt
# ${$arg1} ${$arg2} ${$arg3}.shell: Process exited

通过提供您可以搜索的三个参数来运行上述脚本 您提供的范围内的任何指令 参数1是调用,所以我想搜索调用指令 arg 2是一个表达式,因此windbg将被计算为0x12340000之类的地址 arg 3再次是一个评估大小的表达式 结果如下

0:000> $$>a< c:\foo.txt call windbg L900
windbg+0x1009:
01341009 e8340170e8      call    e9a41142
windbg+0x10b5:
013410b5 e834010000      call    windbg+0x11ee (013411ee)
windbg+0x1171:
01341171 e8000060e8      call    e9941176