如何在Windbg中遍历内存转储?

如何在Windbg中遍历内存转储?,windbg,Windbg,我有一个位于特定内存地址的相对虚拟地址(RVA)数组。我可以将其转储到windbg中,并查看RVA列表,如下所示: dd 77f10000+00002650和 输出为: 77f12650 000034a6 000034af 000034b9 000034ce 这里,77f10000是DLL的基址,00002650是我显示的数组的RVA 现在,内存转储中的每个RVA都可以添加到DLL的基址,并且可以查看该位置的相应字符串 例如,如果我取数组中的第一个条目:000034a6 通过将此RVA添加到D

我有一个位于特定内存地址的相对虚拟地址(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“中止路径”

类似地,我希望迭代数组中的其余条目并显示相应的字符串

我想在windbg中使用一行程序脚本来实现这一点。我想学习如何做到这一点,但是我在网上找不到足够的文档或例子来帮助我制作类似的东西

我认为,.foreach命令可用于执行以下操作:

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

任何帮助都将不胜感激


谢谢。

不幸的是,这比应该的要难,因为dd命令不仅显示结果,而且还显示结果的地址,因此。foreach将对这两个结果进行迭代。虽然我不能在一行中完成,但我是在一个脚本文件中完成的,由于注释的原因,该脚本文件看起来很长:

$$ 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]));
}
$$将RVA数组的基设置为指向整数的指针。
r@$t0=((整数*)(0x8068f764))
$$要分解该命令,请执行以下操作:
$$r?-允许您分配伪寄存器并为其指定类型
$$@$t0-用于脚本编写的伪寄存器
$$((int*)(address)-将int*类型分配给结果
在数组中的条目上循环$$,100是任意的,应该替换
。对于(r@$t1=0;@$t1<100;r@$t1=@$t1+1)
{
$$显示给定偏移量处的ASCII字符串。这类似于:
$$ 
$$printf(“%s\n”,baseAddr+(offsetArray[i])
$$
$$@@c++()是必需的,因此@$t0被视为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"
...

0:kd>$$>不幸的是,这比应该的要难,因为dd命令不仅显示结果,还显示结果的地址,因此。foreach将对这两个结果进行迭代。虽然我无法在一行中完成,但由于注释的原因,我在一个看起来很长的脚本文件中完成了此操作:

$$ 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]));
}
$$将RVA数组的基设置为指向整数的指针。
r@$t0=(整数*(0x8068f764))
$$要分解该命令,请执行以下操作:
$$r?-允许您分配伪寄存器并为其指定类型
$$@$t0-用于脚本编写的伪寄存器
$$((int*)(address)-将int*类型分配给结果
在数组中的条目上循环$$,100是任意的,应该替换
。对于(r@$t1=0;@$t1<100;r@$t1=@$t1+1)
{
$$显示给定偏移量处的ASCII字符串。这类似于:
$$ 
$$printf(“%s\n”,baseAddr+(offsetArray[i])
$$
$$@@c++()是必需的,因此@$t0被视为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"
...

0:kd>$$>很晚才回答,但根据要求,这里有一行:)

测试输出

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"

很晚才回答,但这里有一个一行的要求:)

测试输出

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"

感谢您的精彩脚本。我将练习windbg脚本。x module!*命令的输出与该模块的导出名称表中的函数名称之间是否存在差异?我的理解是,x命令将列出该模块中的所有符号名称,这将比函数更详细导出名称表中显示的名称。这是正确的。唯一的例外是,如果您正在执行“x mod!*”的模块没有符号(即PDB)。在这种情况下,调试器默认为“导出符号”这将向您展示模块的导出。感谢您的精彩脚本。我将练习windbg脚本。x module!*命令的输出与该模块的导出名称表中的函数名称之间是否存在差异?我的理解是,x命令将列出该模块中的所有符号名称,即g与导出名称表中的函数名相比,将更加详细。这是正确的。唯一的例外是,如果您正在执行“x mod!*”打开操作的模块没有符号(即PDB)。在这种情况下,调试器默认为“导出符号”,这将仅显示模块的导出。