《逆向工程核心原理》学习笔记(四) 记录下此书第七章栈帧的学习笔记
栈帧简单的来说就是利用EBP(栈帧指针,注意不是ESP)寄存器访问栈内局部变量、参数、函数返回地址等手段。
ESP寄存器承担着栈顶指针的作用,而EBP寄存器负责栈帧指针的职能,运行过程中ESP寄存器的值随时变化,访问栈中函数的局部变量、参数时,因为变化很难以将ESP的值作为基准来编写程序。
我们如果使用了栈帧技术,无论函数调用的深度有多少深,多复杂,调用栈都能得到很好的管理与维护。
调试第七章给的例子,stackframe.exe
od打开 我们转到401000来查看代码
首先我们看到401020处, 这里是程序主函数的起始地址,
esp中保存了main函数执行完毕后要返回的地址
main()函数一开始运行就生成了与其对应的函数栈帧。
00401020 /$ 55 push ebp
首先是push压栈,把ebp的值压入栈,main函数中ebp为栈帧指针,用来把ebp之前的值备份到栈中,(main函数执行完毕,返回之前,该值会再次恢复。)
00401021 |. 8BEC mov ebp,esp
MOV指令将ESP的值传送到EBP,EBP就和ESP相同的值了,并且到main函数执行完毕,EBP的值始终保持不变。
我们就可以通过EBP可以安全访问到存储在栈中的函数参数与局部变量。
执行了push和mov两个指令后(设置好ebp),函数的栈帧就生成了。
进入OD栈窗口,转到ebp
可以看到ebp和ebp的值一致,保存着函数开始执行时EBP持有的初始值。
我们再来看一下局部变量的设置和分析。
我们来看看对应的变量a、b在栈中是怎么生成的
00401023 |. 83EC 08 sub esp,0x8
sub减法指令将ESP减去8个字节,因为一个long占4字节,为a、b局部变量开辟了空间以便将它们保存在栈中。
在main内部,无论esp的值如何变化,变量a、b的栈空间都不会受到损坏,因为ebp的值在main函数内部是固定不变的,我们就能以它为基准来访问函数的局部变量了
add函数的参数传递与调用