0x01 栈帧是什么
“IA32 programs make use of the program stack to support procedure calls”.
“IA32程序使用程序栈帧来支持子程序调用”(出自CSAPP,即《深入理解计算机系统》)
个人理解,栈帧就是内存的一段数据,在内存栈区域,对子程序的数据进行一个临时保存。
什么是栈?
栈和堆类似,都是操作系统中分配给用户程序使用的一段内存区域,根据CSAPP中的图:
附中文解释:
- Kernel virtual memory:内核虚拟内存,内核是操作系统常驻于内存中的一部分,而这一段空间就是为内存所保留的。应用程序开发者对这一段空间没有权限读写,也不能直接调用内核代码中的函数。
- User stack(created at run time):用户栈区域(执行时创建),在用户虚拟地址空间的最顶部是用户栈,编译器用它来实现函数调用,用户栈在程序执行时自动扩展,尤其是在我们每一次调用函数时。
- Run-time heap(created at run time by malloc):执行时堆(在执行时通过malloc函数创建),代码和数据区域之后紧跟着就是执行时堆,与代码和数据区域不同的是,代码和数据区域在程序执行时已经固定了大小,而它和栈一样是动态扩展的,在C库函数malloc和free的调用下,它被动态的分配和销毁。
- Memory mapped region for shared libraries:为共享库映射的内存区域,在地址空间的中间部分附近,保留着共享库的代码和数据以及Math库的代码和数据。在动态链接的时候,这部分会起到很大的作用。
而 栈帧 ,就是在栈这一段空间里边,为每一个函数所分配的部分了。
0X02 栈帧体现在逆向中的应用
栈帧结构如下:
假设P子程序调用了Q子程序,P(caller), Q(current frame)。
P中最后一段存储的即是return address,也就是从Q返回需要的返回地址,这就象征着P子程序栈帧的结束,从下面开始,就是Q子程序的栈帧。Q子程序的栈帧开始的第一个部分就是保存ebp寄存器内容。而调用Q子程序所需要的参数则保存在从Q保存的EBP地址+4开始到+4+4i 对应第i个参数,也就是说 ebp的地址 + 4 + 4 * i 对应第i个参数
所以在IDA PRO里边对于一个函数进行反编译,常常可以看到ebp被保存,然后ebp的地址 +4 + 4 * i被提出来使用,其实是对第i个参数的使用。
在IDA PRO里边反编译可以看到,函数的开始一般对应两行:
push ebp ;保存原ebp内容
mov ebp, esp;将保存ebp内容后的栈顶指针赋给新的ebp
而在ida反编译的内容中一般会有类似于
arg_0 = dword ptr 8
的内容,这其实是分析出的参数。使用的时候,会这样用
cmp [ebp+arg_0], 0CAFEBABEh
这里的,[ebp+arg_0]所取得的内容,即是第1个参数的内容了(i=1,而ida以0开始,所以分析成arg_0,意思是argument 0,也就是第0个参数)
转载请注明:江海志の博客 » stack frame栈帧简介