我打算在进程转储中的特定内存区域中搜索操作码。
我希望在搜索时有一些条件。
像: $$><<> 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
}
答案 0 :(得分:4)
假设您想在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,因为
!address
PAGE_EXECUTE
es中搜索
答案 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