当前位置:天才代写 > tutorial > C语言/C++ 教程 > 小览CallStack(挪用栈)(三)-用调试器剧本查察挪用栈信息

小览CallStack(挪用栈)(三)-用调试器剧本查察挪用栈信息

2017-11-03 08:00 星期五 所属: C语言/C++ 教程 浏览:903

副标题#e#

在这一系列之前的两篇文章中,我先容了如安在windbg中查察挪用栈的相关 信息(详见小览call stack(挪用栈)(一)),以及挪用约定(详见小览call stack(挪用栈) (二)——挪用约定)。本日的这篇博客在二者的基本 之上,先容如何利用调式器剧本措施来调查挪用栈。对CallStack感乐趣的伴侣 可以在此基本上开拓越发详尽的脚原来调查CallStack的信息;对换试感乐趣的 伴侣则可以看一下DScript的用处。

我们先来看一个例子,下面的措施并不是一个美妙的措施片断,可是它可以或许 辅佐我们说明问题。措施利用了一个简朴的递归,把1到参数d的和累加到sum之 上。在main中,我们把d设为10,这样,在断点处,我们就能得到一个深度为11 的挪用栈。

#include <stdio.h>

int SumToOne(int d, int sum)
{
    sum += d;
    if (d != 1)
        sum = SumToOne(d-1, sum);
    else
        sum = sum; // 这条语句利便配置断点
    return sum;
}

void main()
{
    int sum = SumToOne(10, 0);
    printf("sum=%d", sum);
}

然后,在当前文件夹下,编辑调试器剧本文件DumpStack.txt,内容如下

.printf "Dump %d frames\n", ${$arg1}
r $t1=@ebp;
.for (r $t0=1; $t0<=${$arg1}; r $t0=$t0+1)
{
    .printf "frame %d, d=%d sum=%d\n", $t0, poi($t1+8), poi($t1+c)
    r $t1=poi($t1)
}

在windbg中,运行措施,当措施遏制在断点处时,执行剧本

$$>a< “dumpStack.txt”a

如下图所示

小览CallStack(调用栈)(三)-用调试器脚本检察调用栈信息


#p#副标题#e#

我们看到了10个frame以及它的参数信息。

此刻,对这个调试剧本稍加表明,稍显来看看剧本的语法:

调试剧本的挪用要领,windbg的语法是$$>a< “剧本文件名 ”参数。个中$$>a<中的a示意运行剧本的时候传入参数(argument)

调试剧本的参数:在调试剧本中,用${$argi}来引用第i个参数。由于windbg 默认16进制数,所以我们在挪用这个参数的时候,用了a($$>a< "dumpStack.txt" a)

剧本变量的赋值和引用:这里利用了windbg别名(alias)的语法,各人可以把 别名类比成c中的宏。在赋值的时候,用r $别名= 的名目,引用的时候,利用$ 别名

取值操纵:c中的*p操纵在windbg中,要用poi(p),原因是因为windbg默认支 持MSAM语法。

节制语句:.for语句的利用和任何一种语言的for语句思想一样,不再多述

输出语句:.printf和c中的printf也基内情似,这里也不多述

相识了语法之后,来看看算法:

剧本通过poi($t1+8), poi($t1+c)来显示每个frame中d和sum的值,这里$t1 代表了每个frame中ebp的值,所以简朴的说,就是把每个frame中ebp+8,ebp+c 的值输出。在先容挪用约定的博客中,我报告了这个偏移量的由来,在这里重温 一下。由于函数SumToOne是stdcall,压栈顺序从右往左,如下表所示

前一个ebp
eip
d
sum

ebp指向存储前一个ebo的位置,所以d的位置在ebp+8,sum在ebp+c

前往下一个frame,只需要把栈上ebp位置的值取出,作为新的ebp就可以了。 因为根基上每一个措施在举办栈操纵之前城市备份老的ebp(push ebp),然后把 当前的esp作为新的ebp(mov ebp, esp)

总结一下,本日这篇博文作为这个系列的竣事,通过一个调式器剧本,温习 了之前报告的挪用栈的相关观念。同时也展示了调试器剧本的相关语法。

 

    关键字:

天才代写-代写联系方式