4.2 gdb调试之栈帧信息

您所在的位置:网站首页 栈帧存储信息 4.2 gdb调试之栈帧信息

4.2 gdb调试之栈帧信息

2024-05-22 08:44| 来源: 网络整理| 查看: 265

4.2 gdb调试之栈帧信息前言

这篇文章,是为了介绍缓冲区溢出攻击做准备。

在开始之前,我们希望具备以下背景知识。

(gdb我用的比较少,只会简单的,还没熟练。我们的界面或许会有些不一样,因为插件的缘故,但不影响)

看起来,略微有些复杂,需要自己调试一遍。

虚拟内存的概念

程序在内存中的布局

简单的gdb使用:100个gdb小技巧

简单的汇编语言

[toc]

摘要和总结

我们先给出gdb的调试方法。

然后结合栈帧信息和汇编代码,分析函数调用过程中的栈(栈帧)变化情况。

调试过程调试的代码//我们用一个最简单的程序:memery_layout.c /** * 使用gdb调试该程序,展示内存布局 */ #include void func(int a,int b){ int x,y; x = a + b; y = a - b; } int main(void){ int x=0; int y=0; func(4,3); return 0; }调试过程

在开始调试之前,我们先进行编译:gcc -g -o memery_layout memery_layout.c

开始调试:gdb -q memery_layout

显示程序:l

打断点:break func 、break 10

运行到断点:run

显示程序的调用栈信息:bt (backtrace)

显示当前栈帧的详细信息:info frame(关于这个栈帧信息的解读,我们放在后面)

跳转到上一个栈帧:up

显示当前栈帧的详细信息:info frame

跳转到下一个栈栈:down

继续运行到下一个断点:c

查看全部局部变量信息:info locals

查看x变量内容、地址:print x 、print &x

查看寄存器内容:info registers

查看指定寄存器(rbp)内容:print $rbp

查看汇编代码:disassemble /rm

查看内存内容(0x7fffffffdc70地址,5个单元/16十六进制格式显示/g表示八字节):x /5xg 0x7fffffffdc70

栈帧信息分析栈帧结构

关于调试过程上面已经介绍,下面便不再赘述。

参考文章:x86_64架构下的函数调用及栈帧原理

因为调试的现象和它的不一样。所以我在下面画出我的栈帧图片。

因为参数只有两个,通过寄存器传参,所以没有画参数压栈的情况。

我按照info frame 的信息划分栈帧。

我们先看下栈帧的基本结构。

寄存器介绍

%rax :通常存储函数调用的返回结果,也被用在idiv (除法)和imul(乘法)命令中。

%rsp :堆栈指针寄存器,指向栈顶位置。pop操作通过增大rsp的值实现出栈,push操作通过减小rsp的值实现入栈。

%rbp :栈帧指针。标识当前栈帧的起始位置。 。并不是当前栈帧开始的地方

%rdi, %rsi, %rdx, %rcx,%r8, %r9 :六个寄存器,当参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9;当参数为7个以上时,前 6 个与前面一样, 但后面的依次从 “右向左” 放入栈中,即和32位汇编一样。

栈帧信息分析

蓝色方框:标明我们现在在第0层。

绿色方框,是上一个栈帧的信息,保存在当前栈帧。

called by frame at 0x7fffffffdcb0 :由0x7fffffffdcb0 位置开始的栈帧调用

saved rip = 0x555555554640 :当前栈帧要保存上一个栈帧将要执行的地址0x555555554640

rip at 0x7fffffffdc88 :返回地址(上一个栈帧将要执行的地址),保存在0x7fffffffdc88

rbp at 0x7fffffffdc80:上一个栈帧指针内容保存在0x7fffffffdc80

Previous frame's sp is 0x7fffffffdc90 :上一个栈帧的栈顶指针。(这我画成红框,框错了。。)

红色方框是当前栈帧信息

frame at 0x7fffffffdc90 :当前栈帧的起始地址0x7fffffffdc90

Locals at 0x7fffffffdc80:局部变量从0x7fffffffdc80 开始。

代码分析

那么当前的rbp值是什么?局部变量为甚从上面 0x7fffffffdc80的地方开始?

仅从栈帧的信息,是无法验证。这时候,我们来看看它的汇编代码。

补充下压栈:push指令可以分解为=%rsp栈顶指下移+mov 源数据

绿色方框

通过压栈方式,保存上一个栈帧指针。由上一节,我们知道,它被保存在0x7fffffffdc80

将当前栈顶,保存在rbp中。即,设置栈帧指针。所以如上面结构图所示,当前栈帧位置,是保存上一个栈帧的内存位置。

蓝色方框

从寄存器中取出参数,放入内存。

红色方框

进行计算,计算的结果放入局部变量局部变量的起始地址,从rbp指向的内存的下面开始。

还原

将上一个栈帧地址,还原到rbp中

ret 返回调用(下面介绍)

函数的调用与返回

这里,我们仅仅着重看下call 和ret

我们也看下main函数的汇编代码。

我们可以看到,两个参数,从右向左,传递给寄存器。

然后,调用0x5555555545fa位置的func 函数。

通过上一张图,我们能看出0x5555555545fa是func函数的起始位置。

call 还干了一件事,把下一条要执行的地址,压入栈中。我们可以通过内存查看。

绿色方框 ---> 两个局部变量的值

蓝色方框 ---> 上一个栈帧的值

红色方框 ---> 返回地址

栈帧指针-不是栈帧开始的地方

栈帧寄存器存储的不是栈帧开始的地方。

我们用第0层的栈帧来看:frame at 0x7fffffffdc90 + Saved registers: rbp at 0x7fffffffdc80

当前栈帧开始的地方是0x7fffffffdc90,而栈帧寄存器里面的值是0x7fffffffdc80

而且,我倾向与将返回地址,划分在当前栈帧,而不是上一个栈帧。

`0x7fffffffdc90` 这个内存中的内容,我不知道代表什么。不是寄存器的值

我们可以看出0x7fffffffdc98里面是两个int 0,是上一个栈帧的内容。

我们可以通过,frame 0x7fffffffdc90 跳转到当前栈帧。

How to interpret GDB “info frame” output?

info frame command

Previous4.1 程序在内存中的布局Next4.3 缓冲区溢出攻击

Last updated 3 years ago



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3