站在C语言的肩膀上学汇编(2):栈

懒人利器2021-01-18 21:01:12
  1. C语言函数的局部变量保存在栈上;

  2. C语言函数的调用信息保存在调用栈上;

  3. C语言可以利用栈溢出攻击;

C语言中很多概念都跟运行时栈相关,但它对C层是透明的,要想真正了解这些概念, 就需要去汇编层了解“运行时栈”的实现。

站在C语言的肩膀上学汇编(1):栈

2. C语言函数的调用信息保存在调用栈上

#include<stdio.h>int func2(){ return 0;}int func(){int funcValue1 = 3; int funcValue2 = 4; func2(); return 0;}int main(){ int mainValue1 = 1; int mainValue2 = 2; func(); return 0;}

这个函数的运行时栈示意图为:

  • 当程序执行main函数体代码时,rbp(base pointer)指向0x7fffffffe180, rsp(stack pointer)指向0x7fffffffe170, 也就是rbp指向main函数运行时栈的栈底, rsp指向main函数运行时栈的栈顶。

  • 当程序执行func函数体代码时,rbp(base pointer)指向0x7fffffffe160, rsp(stack pointer)指向0x7fffffffe150, 也就是rbp指向func函数运行时栈的栈底, rsp指向func函数运行时栈的栈顶。

  • 由此可知,rbp 一直指向当前运行时函数的栈底,rsp一直指向当前运行时函数的栈顶。

  • 当func函数执行完退出到main函数体时,rbp(rsp)需要重新指向main函数运行时栈的栈底(顶),所以需要把main函数的运行时栈的栈底存储在栈上,也就是地址为0x7fffffffe160内存里存0x7fffffffe180。

  • 由于func函数执行完后,需要执行main函数体的return 0语句; 所以需要把return 0;语句的代码地址保存到栈上,也就是地址0x7fffffffe160内存里保存的内容0x0040053f。

具体的执行过程见下图

  • 函数的汇编代码

  • 每行汇编代码执行完,rsp, esp里对应的值

  • 对应汇编代码的含义

callq 会先把下行代码压入栈,然后再跳转到对应的函数处执行;leaveq movq %rbp, %rsp; popq %rbp;retq 弹出栈顶元素,跳转到栈顶元素所指地址处;

结论

  • C语言函数调用栈的内存布局为:

3. C语言可以利用栈溢出攻击

(0)

相关推荐