进程运行时的内存
high address | command-line arguments and environment variables | |
---|---|---|
stack | ||
heap | ||
uninitalized data(bss) | initialized to zero by exec | |
initialized data | read from program file by exec | |
low address | text | read from program file by exec |
command-line arguments and environment variables:
在程序运行前传递给程序,环境变量也在此处存储
stack:
存储函数的参数、返回地址和函数的局部变量,从高地址向低地址延伸。
heap:所有动态分配的内存划分于此。任何时候使用malloc都会从heap分配。heap从低地址向高地址生长
uninitialized data(BSS segment):
所有未初始化的数据存放于此,包括没有初始化的全局变量和静态变量。
内核默认将它们置为0.
initialized data(Data segement)
存放所有经过初始化的数据。
text:
存放可执行代码。loader指令从这里取出指令并运行。只读。
常用寄存器
%eip: 指令指针寄存器,存放下一条指令的地址。每次执行完后根据指令的大小自增
%esp:堆栈指针寄存器,存放栈顶指针。
%ebp:基址指针寄存器。函数开始时与esp相等。
内存管理
假设有以下程序:
void func(int a,int b)
{
int c;
int d;
//some code
}
void main()
{
func(1,2);
//next instruction
}
假设eip指向了main函数中的func调用,则接下来:
发现函数调用,从右向左将参数压入堆栈
需要知道完成后返回的地址。因此将下一条指令的地址压入堆栈。
找到要调用的参数的地址。将eip设为那个值。现在执行func函数。
我们现在在一个新函数中,因此要改变ebp的值。在改变之前,我们将它保存到栈中,这样返回时可以回到main函数
将ebp的值设为与esp相同。
将局部变量(不是参数)推入,改变栈顶指针esp的值
func执行完后,要回到原来栈。首先使esp等于ebp;从栈中弹出之前保存的ebp的值,重新赋给ebp。现在基底指针指向了之前在main中指向的位置。
弹出返回地址,赋值给指令指针eip。于是控制流又到了main函数。
执行func时栈的样子:
局部变量d | esp |
---|---|
局部变量c | |
ebp在main中指向的地址 | ebp |
返回地址 | |
1 | |
2 |
缓冲区溢出漏洞
目的:访问分配给缓冲区内存之外的空间并进行读写
通过修改返回地址控制程序运行
以开头的程序为例:
32位系统编译:
gcc vuln.c -o vuln -fno-stack-protector
64位系统编译
gcc vuln.c -0 vuln -fno-stack-protector -m32
(gcc安装32位编译libc文件:
apt-get update
apt-get purge libc6-dev
apt-get install libc6-dev
apt-get install libc6-dev-i386
)
对程序进行反汇编:
objdump -d vuln
secret地址:000011b9
说明:
这里汇编语言格式为AT&T。特点:寄存器前要加%;立即数前要加$;目标操作数在源操作数数右边。
push ebp //保存ebp的值
mov esp,ebp //将esp赋给ebp
sub $0x24, %esp //esp减少24H,其中的空间属于局部变量
lea (load effective address),取有效地址。用法:把源操作数的地址偏移量传送目的操作数。只与地址有关!
lea -0x1c(%ebp) %eax // ebp前1cH字节
总之。。。现在缓冲区中共有28字节(1cH),正好位于ebp之前;之后的4字节就是ebp所指向的ebp在main中的值;再往后4字节时返回地址,即指令指针eip所要获得的地址。
构造payload:前28+4个字节随便填,后4个字节填secretFunction的地址。这里肯定是000011b9!
根据机器是大头位序还是小头位序填写。
这里是小头位序,所以是b9110000
。。。。。。
好吧这边没有关PIE,得到的地址都是错的。需要对文件进行重新编译。新增参数:
关闭PIE:
-no-pie
关闭NX:
-z noexecstack
关闭canary:
-fno-stack-protector
新的小头位序:82910408
再次尝试成功了。
存在漏洞的C函数:
原文:https://www.cnblogs.com/Moon-on-Flat/p/14833547.html