基础栈溢出

目录

一、C语言函数调用栈

1.基础概念

2.过程

      函数调用的发生

      函数调用的结束

二、实例

1.工具的使用

2.进行攻击

 三、ret2shellcode



在了解栈溢出之前,我们先来了解一下缓冲区溢出,缓冲区溢出的本质是向定长的缓冲区中写入了超长的数据,造成超出的数据覆写了合法内存区域,而缓冲区溢出主要有三种:栈溢出、堆溢出以及Date段溢出,由于栈溢出是最基础、最常见且危害最大的二进制漏洞,我们首先学习栈溢出。

在学习之前我们要知道一些关于栈的基础知识,这里我们就不细说了,自行了解即可。

一、C语言函数调用栈

1.基础概念

函数调用栈是值程序运行时内存中一段连续的区域,用来保存函数运行时的状态信息,包括函数参数和局部变量等,注意函数调用栈在内存中是从高地址到低地址生长的。每调用一个子函数,将会在函数调用栈中新增一个栈帧。具体方式如下图所示:

栈的寄存器:

(1)esp:栈指针寄存器,其中存放着一个永远指向系统栈最上面一个栈桢的栈顶的指针。

(2)ebp:基址指针寄存器,其中存放着一个永远指向系统栈最上面一个栈桢的底部(当前函数的基地址)的指针。

(3)eip:指令寄存器,其中存放着一个永远指向下一条等待执行的指令地址的指针。eip可被jmp,call和ret等指令隐含的改变

栈结构预览:

2.过程

caller:调用函数 callee:被调用函数 

函数调用的发生

<1>将callee中参数逆序压入栈内

首先是将被调用函数的参数压入栈内(push),同时栈顶对应的内存地址也依次变化,切记为按照逆序依次压入,如果被调用函数不需要参数的话,可省略这一步骤。这些参数仍会保存在调用函数(caller)的函数状态内,之后压入栈内的数据都会作为被调用函数(callee)的函数状态来保存。

<2>将caller的返回地址压入栈内

在参数压入完毕之后,再将调用函数(caller)在进行调用之后的下一条指令地址作为返回函数压入栈内,以保存调用函数(caller)的指令(eip)信息

<3>将当前ebp值压入栈内并将当前栈顶地址传至ebp寄存器中

保存完caller的指令信息之后,我们在将ebp寄存器的值(此时保存的是调用函数的基地址)压入栈内,并将ebp寄存器的值更新为当前栈顶的地址(此时为被调用函数的基地址)。

<4>将callee的局部变量压入栈内

这里就是被调用函数局部变量的压栈

到这里函数调用的发生就完成了,在这个压栈的过程中,由于栈在内存中由高地址向低地址生长,故esp寄存器的值也在不断减小。压入栈的数据依次为调用参数、返回地址、调用函数的基地址以及局部变量。其中除调用参数以外的数据构成了被调用函数(callee)的状态。

在调用时,程序会将被调用函数的指令地址存到指令寄存器(eip)中从而使程序依次执行被调用函数的指令,后续我们也是根据这个来进行攻击。

函数调用的结束

在函数调用的发生结束之后,将进行函数调用的结束。而这一过程的核心就是丢弃被调用函数的状态,并将栈顶恢复为调用函数的状态。以下便是过程(由于可以与函数调用发生的过程结合来看,这里就不配图了):

<1>将被调用函数的局部变量弹出栈外,栈顶会指向被调用函数的基地址

<2>将基地之内存储的调用函数(caller)的基地址从栈内弹出并保存在ebp寄存器内,这样调用函数的基地址信息得以恢复,栈顶会指向返回地址。

<3>再将返回地址从栈内弹出并存到eip寄存器内以恢复调用函数的eip信息

<4>到这里调用函数的状态完全恢复,之后便继续执行调用函数的指令了。

我们可以通过下面这个代码作为示例来分析函数调用栈的工作方式:

函数调用栈的工作方式

二、实例

1.工具的使用

* [ ] IDA Pro
  
* [ ] pwntools
  
* [ ] pwndbg
  
* [ ] checksec
  
* [ ] ROPgadget
  
* [ ] one_gadget
  
* [ ] LibcSearcher
  
* [ ] main_arena_offset

 这里暂时只用到前四个,其他以后会用到,这里关于这几种工具的用法就不具体描述了

2.进行攻击

<1>使用python3打开交互(本地)

python3 
from pwn import * 
io = process("地址") 
io.recvline()//接受

 <2> 编写一个payload以覆盖掉函数之前的返回地址进而达到栈溢出攻击效果

payload = //字节长度必须足够能覆盖掉返回地址的长度

 <3>将payload发送过去,再进行交互

io.sendline(payload)
io.interactive()//此时以获得shell

 <4>本地打通之后再打远程

io.remote("远程服务器的地址")

 <5>可以将整个攻击流程写入一个脚本然后python一次性运行

vim exp.py
    //整个流程
python3 exp.py

 三、ret2shellcode

一般情况下程序中不一定存在后门函数,这个时候就需要我们手动输入一个shellcode,初期一把将shellcode直接写入栈缓冲区(目前由于 the NX bits 保护措施的开启,栈缓冲区不可执行,故当下的常用手段变为向 bss 缓冲区写入 shellcode 或向堆缓冲区写入 shellcode 并使用 mprotect 赋予其可执行权限)

目前先写到这里,随时补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值