linux pwn栈溢出漏洞原理

学习栈溢出首先了解一下linux pwn常见的保护
》RELRO
部分RELRO:将.got段映射为只读(但.got.plt还是可以写)重新排列各个段来减少全局变量溢出导致覆盖代码段的可能性.
完全RELRO:
执行部分RELRO的所有操作,让链接器在链接期间(执行程序之前)解析所有的符号, 然后去除.got的写权限,将.got.plt合并到.got段中, 所以.got.plt将不复存在.
》.stack canary
在函数返回值之前添加的一串随机数(不超过机器字长),末位为/x00(提供了覆盖最后一字节输出泄露canary的可能)
》.NX标识页表是否可执行
》.pie:elf文件加载基址随机化
没有随机化。即关闭 ASLR。
保留的随机化。共享库、栈、mmap() 以及 VDSO 将被随机化。
完全的随机化。在 1 的基础上,通过 brk() 分配的内存空间也将被随机化。
加载了地址随机化在做题的时候每次加载的位置会不一样,可以用命令:(sudo bash -c "echo 0 > /proc/sys/kernel/randomize_va_space将随机化暂时关闭)

linux栈溢出基本原理:
首先了解一下栈的结构,
栈是一种数据结构,采用小端模式进行存储,即小地址单元存储数据的低位(即尾端)。是一种只能在一端进行插入和删除操作的特殊线性表。按照先进后出的原则存储数据,栈最重要的是栈保存了一个函数调用时所需要的维护信息,一般包含如下几方面的信息:
1.函数的返回地址和参数
2. 临时变量:包括函数的非静态局部变量以及编辑器自动生成的其他临时变量。

栈溢出原理:
栈溢出是指在栈内写入超过自身实际大小的内容造成改变栈中相邻变量的值的情况,从而破坏程序运行或者获得系统控制权的攻击手段。实现栈溢出要保证两个基本条件1、要程序必须向栈上写入数据2、程序并未对输入内容的大小进行控制。。。我们平时所说的的栈溢出漏洞利用就是利用栈溢出来劫持控制流到达任意代码执行的效果:
那么整个过程栈内发生了什么样的变化呢?
当栈内发生函数调用时,调用函数被保存在栈内,被调用函数被压入调用栈的栈顶;在函数调用结束时,栈顶的函数被弹出,栈顶恢复到调用函数的状态

那么栈是怎样进和出的呢?先看一下栈的数据结构
栈有两种状态入栈(push)和出栈(pop)
在这里插入图片描述在这里插入图片描述
假设a、b存在了stack上,

int main(){
    int a=0x100;
    int b=0x200;
    .......
    return 0;
    }

此时分布如图所示:
在这里插入图片描述在这里插入图片描述
callee就是被调用函数,caller为调用函数
函数调用时栈内发生的变化
主要涉及三个寄存器--esp,ebp,eip
esp 存储函数调用栈的栈顶地址,在压栈和退栈时发生变化。
ebp 用来存储当前函数状态的基地址,在函数运行时不变,可以用来索引确定函数参数或局部变量的位置。
eip 用来存储即将执行的程序指令的地址,eip 指向相邻的下一条指令,程序按照eip的指令执行
栈顶函数状态以及寄存器的变化:
在调用函数的时候会将被调用函数的状态保存起来,创建被调用函数的状态,因为我们最终函数调用结束时,栈顶恢复到调用函数的状态。
在这里插入图片描述
》1、将调用函数的参数逆序依次压入栈内,这里为什么是逆序,就是前面讲到的栈先进后出的原则
》2、将被调用函数的参数压入栈内然后将调用函数进行调用之后的下一条指令地址作为返回地址压入栈内
函数调用时的内部变化
1、将调用函数的返回地址压入栈内为将当前的 ebp 寄存器的值压入栈内,并将 ebp 寄存器的值更新为当前栈顶的地址

在这里插入图片描述
2、将调用函数的返回地址压入栈内后,将当前的 ebp 寄存器的值(也就是调用函数的基地址)压入栈内,并将 ebp 寄存器的值更新为当前栈顶的地址。这样caller的 ebp(基地址)信息得以保存。同时,ebp 被更新为调用函数的基地址
3、 将调用函数的基地址(ebp)压入栈内,并将当前栈顶地址传到 ebp 寄存器内再之后是将(callee)的局部变量等数据压入栈内
4、 将被调用函数的局部变量压入栈内在压栈的过程中。调用参数、返回地址、调用函数的基地址,以及局部变量等都可以被压入栈中,其中调用参数以外的数据共同构成了调用函数的状态。在发生调用时,程序还会将调用函数的指令地址存到 eip 寄存器内,这样就达到了上面所说的,让eip做我们想要做的事情

攻击:
在发生函数调用或者结束函数调用时,程序的控制权会在函数状态之间发生跳转,可以通过修改函数状态来实现攻击。控制程序执行指令最关键的寄存器就是 eip,让 eip 载入攻击指令的地址,也就拿到了相应的权限
1、在退栈过程中,返回地址会被传给 eip,所以只需要让溢出数据用攻击指令的地址来覆盖返回地址就可以了。
2、可以在溢出数据内包含一段攻击指令,也可以在内存其他位置寻找可用的攻击指令。
主要有以下几个方面:指向溢出数据中的一段指令(shellcode)、指向内存中已有的某个函数(return2libc)、指向内存中已有的一段指令(ROP)、修改某个被调用函数的地址,让其指向另一个函数(GOT)
参考:https://paper.seebug.org/271/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值