sir

堆栈基础1-函数调用栈

新手入门pwn之栈溢出系列,先学习堆栈的基础,函数调用栈这些.

运行时栈

运行时栈(runtime stack)是有cpu内部硬件直接支持的, 也是实现过程调用和过程返回机制的基本组成部分。 在大多数时我们称运行时栈为: 堆栈

这里的堆栈和数据结构里的栈抽象数据类型是不同的,堆栈即运行时栈在系统层上(由硬件直接实现) 处理子过程调用; 堆栈抽象数据类型通常用于实现依赖后进先出操作的算法,一般使用高级语言如c++/java等编写。

栈方向

https://www.zhihu.com/question/36103513
https://www.cnblogs.com/xkfz007/archive/2012/06/22/2558935.html

栈方向跟体系结构有关系,x86是向下增长,x86硬件直接支持的栈确实是“向下增长”的,由高地址向低地址增长:push指令导致sp自减一个slot,pop指令导致sp自增一个slot。其它硬件有其它硬件的情况。arm没有固定,但一般操作系统会选择向下增长

image.png

在内存管理中,与栈对应是堆。对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方式是向下的,是向着内存地址减小的方向增长。在内存中,“堆”和“栈”共用全部的自由空间,只不过各自的起始地址和增长方向不同,它们之间并没有一个固定的界限,如果在运行时,“堆”和 “栈”增长到发生了相互覆盖时,称为“栈堆冲突”,系统肯定垮台。

三个寄存器

函数状态主要涉及三个寄存器

image.png

push / pop操作

运行时栈是有cpu直接管理的内存数组, 它使用连个寄存器,ss和esp(32是esp,16位是sp,64位是rsp), ss寄存器存放的段地址,esp是堆栈指针寄存器,指向最后压入到堆栈上的数据。我们很少直接操纵esp的值,而是由call,ret,push和pop指令间接修改的。

堆栈段的操作步骤

http://bestwing.me/2017/03/18/stack-overflow-one/

函数调用方式和栈帧

参考:https://www.zhihu.com/question/22444939

如下代码:

函数调用大致包括以下几个步骤:

栈帧的调整过程:

函数调用图如下:

image.png

栈帧调整图如下:

image.png

函数调用时栈内的数据从高地址到低地址分别是函数参数入栈(从右到左),返回地址入栈,ebp入栈,esp分配填充地址, 局部变量mov入栈.

函数调用的汇编代码为:

main函数

参数入栈的方式:取决于调用约定,一般情况下:
X86 从右向左入栈,X64 优先寄存器,参数过多时才入栈

image.png

main函数的栈帧:

我们看到函数调用后首先是函数参数入栈,函数调用后会发生什么呢? 我们来看一看

image.png

func_A的栈帧: ebp=0019FED8

func_B的汇编代码:

将这段代码的所有汇编一步一步跟踪了解清楚了后,对堆栈算是大概了解了,下面就是入门栈溢出了,之后学到栈溢出再来更新.

喜欢 0