堆栈溢出攻击原理分析

0x01 概述

之前就听说过堆栈溢出攻击,但是一直都没仔细想过其中的原理,也不知道实际该怎么实现,今天花了一下午讨论了一下有了点自己的理解。记录下来。

0x02 分析

堆栈溢出思路是,对于不进行对用户输入数据进行检测的程序,可以把输入数据写到正常存放数据区域的后面,把函数返回地址修改掉,执行自己的代码。 主要有两种方式。

第一种

内存中栈的结构大概是这样的

栈底(高地址)寄存器ebp(64位为rbp) ......这里是其他数据 这里是函数返回地址 ......这里是局部变量,数据放在这里 ......这里是其他数据 栈顶(低地址)寄存器esp(64位为rsp)

通过写入超过变量分配内存大小的数据从低地址写到高地址把返回地址修改掉 然后程序就会执行修改后的地址中的指令

  1. 首先查找执行call rsp/esp指令所在的地址记为jmpAddr
  2. 调试定位返回地址相对于输入数据地址的偏移量
  3. 编译自定义的程序,提取shellcode
  4. 用pad+jmpAddr+shellcode的形式输入数据

运行之后应该就执行了shellcode的指令了。 pad用于填充前面的数据,一直到函数返回地址所在位置。 继续写入jmpAddr,把跳板地址写入函数返回地址所在位置,这样函数返回将会调用jmpAddr处的指令,即call rsp/esp。 接着继续往高地址写入shellcode的内容 这里要注意的是因为写入数据是一个字节一个字节的往高地址写入,所以应当以小端方式写入地址。 在函数返回时子程序出栈esp/rsp栈顶应当指向shellcode的位置 函数返回跳转到jmpAddr执行call esp/rsp,调用esp/rsp处的程序 此时便进行了调用shellcode的操作。

第二种

windows下的程序在执行过程中遇到错误会调用错误处理程序。 一样的道理,写入数据的时候把错误处理程序的入口指向执行call ebx的地址,这时ebx基地址寄存器中的地址位于入口地址前4个字节。在四个字节前写入jmp 04跳过入口地址执行紧接其后的shellcode即可。


更新

前面的内存描述应该有个地方说的不太对,frame的栈底应该是在返回函数的位置。上面说的栈顶和栈底不是同一个栈的。当函数返回的时候栈底应当就是前一个栈的栈顶了。

Show Comments