让我们摇滚。 下面我们有一个C程序,旨在接受和打印命令行参数:

黑客基础:第2部分

Convert2.c接受要打印的字符串以及使用atoi()函数转换为整数的字符串。 但是,该程序有意包含一个错误。 注意,检查命令行参数数量的代码块已被注释掉。 当程序尝试访问无法访问的内存时,这将导致分段错误:

黑客基础:第2部分

我们可以使用gdb进一步探索:

黑客基础:第2部分

注意“ where”命令似乎显示了执行堆栈

仔细看看这一行:

黑客基础:第2部分

GDB告诉我们argv(指向字符串列表的指针)指向某个地址0xbffff894 这是字符串列表中第一个字符串的地址的开头。 让我们检查一下内存:

黑客基础:第2部分

三个十六进制字中的每一个代表一个命令行自变量(实际上是指向命令行自变量的指针)。 第一个参数始终是可执行文件的名称(在本例中为“ a.out ”),第二个参数在本例中为“ test ”。

由于我们没有提供第三个命令行参数,因此我们无法访问地址0x00000000的内存。 当我们尝试在源代码中使用“ count = atoi(argv [2]); ”行访问它时 我们遇到了细分错误。

这个示例(间接)突出显示了我们尚未讨论的另一个gdb工具-“ bt”。 如果您在gdb中执行“ where”命令的位置查看两个屏幕截图,则会看到一个堆栈。 您可以使用bt实用程序随时显示执行堆栈的状态。 让我们使用一个示例程序来说明这一点:

黑客基础:第2部分

Main()调用func1() ,后者调用func2() 我们的执行堆栈如下所示:

黑客基础:第2部分

注意,这是我们运行“ bt”后的堆栈外观:

黑客基础:第2部分

最上面的框架是我们当前正在使用的框架。 我们可以通过打印n的值(在func2()中此值为30)来验证这一点:

黑客基础:第2部分

p是“打印”的缩写

我们还可以从一帧移到另一帧-即使当前帧尚未完成执行:

黑客基础:第2部分

我们还可以通过运行“信息框架”来获取有关每个框架的信息:

黑客基础:第2部分

在这里,我们看到的是帧#2住在0x7fffffffe5a0调用帧#1,它住在0x7fffffffe580。

这就是我们可以使用bt实用工具检查gdb中的执行堆栈,并希望将其用作跟踪分段错误的工具的方式。

From: https://hackernoon.com/the-basics-of-hacking-part-2-w1d3368v

相关文章: