【问题标题】:How to Iterate through Memory Dump in Windbg?如何遍历 Windbg 中的内存转储?
【发布时间】:2011-12-28 15:57:08
【问题描述】:

我有一个位于特定内存地址的相对虚拟地址 (RVA) 数组。我可以将它转储到 windbg 并查看 RVA 列表,如下所示:

dd 77f10000+00002650 和 输出是: 77f12650 000034a6 000034af 000034b9 000034ce ....

这里,77f10000 是 DLL 的基地址,00002650 是我显示的数组的 RVA。

现在,内存转储中的每个 RVA 都可以添加到 DLL 的基地址中,并且可以查看该位置的相应字符串。

例如,如果我取数组中的第一个条目,即:000034a6

将此 RVA 添加到 DLL 的基地址 77f10000 并显示如下:

da 77f10000+000034a6 和 输出为:77f134a6 "AbortDoc"

现在,通过这种方式,我可以通过执行以下操作来查看数组中下一个对应 RVA 的下一个字符串:

da 77f10000+000034af 和 输出为:77f134af "AbortPath"

同样我想遍历数组中剩余的条目并显示相应的字符串。

我想在 windbg 中使用一个单行脚本来执行此操作。我想学习如何做到这一点,但是我在网上找不到足够的文档或示例来帮助我制作类似的东西。

我认为 .foreach 命令可以用来做到这一点:

示例:.foreach(myVariable {dd 77f10000+00002650}){!do } myVariable 将存储 windbg 命令的输出。但是,我需要从该行中一次选择一个元素并进行迭代。

任何帮助将不胜感激。

谢谢。

【问题讨论】:

    标签: windbg


    【解决方案1】:

    不幸的是,它比应有的更难,因为 dd 命令不仅显示结果,还显示结果的地址,因此 .foreach 将遍历两者。虽然我不能在一行中完成,但我是在一个脚本文件中完成的,由于 cmets,它看起来很长:

    $$ Set up the base of the RVA array as a pointer to an integer.
    r? @$t0 = ((int *)(0x8068f764))
    
    $$ To break down the command:
    
    $$ r?                - Allows you to assign a pseudo register and give it a type
    $$ @$t0              - Pseudo register for use in scripting
    $$ ((int *)(address) - Assign the type int * to the result
    
    
    $$ Loop over the entries in the array, 100 is arbitrary and should be replaced
    .for (r @$t1 = 0; @$t1 < 100; r @$t1 = @$t1 + 1) 
    {
        $$ Display the ASCII string at the given offset. This is similar to:
        $$ 
        $$ printf("%s\n", baseAddr+(offsetArray[i])
        $$
        $$ @@c++() is required so that @$t0 is treated as an int *
    
        da nt+(@@c++(@$t0[@$t1]));
    }
    

    保存到 TXT 文件并使用以下命令运行:

    0: kd> $$><c:\dumps\dumprvas.txt
    80691a4b  "CcCanIWrite"
    80691a57  "CcCopyRead"
    80691a62  "CcCopyWrite"
    80691a6e  "CcDeferWrite"
    80691a7b  "CcFastCopyRead"
    80691a8a  "CcFastCopyWrite"
    ...
    

    如果我真的这样做了,我会进一步清理它,并将基地址和条目​​计数参数添加到脚本中,这将使它更有用。为了清楚起见,我把它留在这里(好吧,这些脚本可以预期的尽可能清晰:))。

    -斯科特

    【讨论】:

    • 感谢漂亮的脚本。我将练习windbg脚本。 x module!* 命令的输出与该模块的导出名称表中的函数名称之间有区别吗?我的理解是,x 命令将列出该模块中的所有符号名称,与导出名称表中的函数名称相比,这将更加冗长。
    • 没错。唯一的例外是,如果您正在执行的模块没有符号(即 PDB),则打开“x mod!*”。在这种情况下,调试器默认为“导出符号”,它只会显示模块的导出。
    【解决方案2】:

    很晚的答案,但这里是一个要求的单行线:)

    0:000> .foreach /ps 1  /pS 1 (place { dd /c 1 gdi32+2650 l?5 }) {da gdi32 + place } 
    

    测试输出

    0:000> .foreach /ps 1  /pS 1 (place { dd /c 1 gdi32+2650 l?5 }) {da gdi32 + place } 
    77f134a6  "AbortDoc"
    77f134af  "AbortPath"
    77f134b9  "AddFontMemResourceEx"
    77f134ce  "AddFontResourceA"
    77f134df  "AddFontResourceExA"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多