最常见的两种exploit是:缓冲区溢出,格式化字符串
CPU(Intel,x86)各主要寄存器的一般用途:
寄存器 | 用途 |
---|---|
EAX | 存储器:用于执行计算,并用于存储函数的返回值。基本操作,如加、减、比较的时候使用这个通用寄存器 |
EBX | 存储数据 |
ECX | 计数器:常用于计数循环的次数。 |
EDX | 数据 |
ESP | 栈顶指针 |
EBP | 基指针(常用来表示一个函数帧的底部) |
ESI | 源操作数指针 |
EDI | 目的地址指针 |
EIP | 指令指针 |
注意: 栈是从低地址向高地址,堆是高地址向低地址生长
x86处理器采用的是小端序(低位在前面,例如0x123456->0x563412)
程序存储器分为(按照内存中的顺序排列)
名字 | 类型 |
---|---|
text | 禁用写权限,固定大小 |
data | 存储全局变量,静态变量。存储的是已经初始化的,可以改写,固定大小 |
bss | 存储全局变量,静态变量。存储的是未初始化的,可以改写,固定大小 |
heap | 用于其他的变量(moonife:动态申请的)(比如malloc操作等等,分配的空间在heap里面)。大小可变,对从存储器的低地址向高地址增长 |
stack | 大小可变,函数调用时作为中间结果暂存器。存储所有传递的变量,以及函数执行后的EIP的返回地址 |
函数参数以及局部变量的入栈顺序
void test(int a,int b,int c,int d){
char flag;
char buffer[10];
}
void main(){
test(1,2,3,4);
}
栈顶 | … |
---|---|
buffer | 低地址 |
flag | |
SFP | |
ret | |
a/1 | |
b/2 | |
c/3 | |
d/4 | 高地址 |
栈底 |
调用的时候4321这样入栈
用户进程空间映像如下图所示:
当函数 Do_Something(param 1)被调用,有以下步骤:
- Push param 1
- Call Do_Something 的同时 push EIP(返回地址)
- Push EBP,这是必须的 ,因为我们需要改变 EBP 的值来引用栈中的值,这是通过 mov ebp,esp
- 来实现的,所以栈中的数据,很容易被引用。
- 最后,局部变量被压入栈,在我们这个例子是:do_something::buffer[128]。
- 因此,当函数结束的时候,将返回main函数。