栈溢出漏洞原理详解与利用

0x01 前言

和我一样,有一些计算机专业的同学可能一直都在不停地码代码,却很少关注程序是怎么执行的,也不会考虑到自己写的代码是否会存在栈溢出漏洞,借此机会我们一起走进栈溢出。

0x02 程序是怎么运行的

在了解栈溢出之前我们先了解一下程序执行过程

程序的执行过程可看作连续的函数调用。当一个函数执行完毕时,程序要回到call指令的下一条指令继续执行,函数调用过程通常使用堆栈实现

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
  test1(1);
  test2(2);
  test3(3);
  return 0;
}
int test1(int test1){
int a = 6;
  printf("1");
  return 1;
}
int test2(int test2){
  printf("2");
  return 2;
}
int test3(int test3){
  printf("3");
  return 3;
}

编译成32位可执行文件,放在ollydbg中就行调试,来详细看一下执行过程

因为程序的执行可以看做一个一个函数的执行(main函数也一样),因此我们挑选其中一个即可,在test1()函数设置断点

F7单步调试第一步mov dword ptr ss:[esp],0x1,进行传参,简洁明了。

第二步call mian.00401559,进入test(),这里我们关注一下esp和栈顶值,将该指令的下一条指令的地址进行压栈,既然有压栈那么就会有出栈,这就与函数中的retn指令形成呼应。

第三步push ebp,就是把ebp的值进行压栈,那么这个ebp是什么呢?有什么用呢?

EBP叫做扩展基址指针寄存器(extended base pointer) ,里面放一个指针,该指针指向系统栈最上面一个栈帧的底部,用于C运行库访问栈中的局部变量和参数。那么这一步的意义就是:保存旧栈帧中的帧基指针以便函数返回时恢复旧栈帧

第四步,mov ebp,esp,将esp的值放在ebp中,我们再来了解一下什么是esp?

ESP(Extended Stack Pointer)为扩展栈指针寄存器,是指针寄存器的一种,用于存放函数栈顶指针,指向栈的栈顶(下一个压入栈的活动记录的顶部),也就是它不停在变,刚才提到的ebp指向栈底,在函数内部执行过程中是不变。

那么我们再看一下这一步的作用:

从第三步可以知道esp存储的值是旧栈帧中的帧基指针,而esp值栈顶指针,随时都在变,因此为了函数结束后能恢复,把esp值(外层函数栈底地址)保存在本函数栈底ebp中。简而言之,将内部函数ebp的值作为地址,它存放外函数的ebp的值。这一步在末尾也存在逆向指令leave。

第五步是sub esp,0x28,开辟该函数的局部变量空间

紧接着第六步mov dword ptr ss:[ebp-0xC],0x6,给变量a一个大小是0xC的空间,并且赋值。

然后就是传参字符1的ascii码,调用printf函数,把返回值放到eax。

我们重点来看leave指令,可以发现ebp的值恢复了,esp的值也变了,相当于mov esp,ebp;pop ebp

最后执行retn指令,至此一个函数执行完毕,esp和eip的值都被改变,相当于pop eip,然后程序继续执行。EIP是指令寄存器,存放当前指令的下一条指令的地址。CPU该执行哪条指令就是通过EIP来指示的

0x03 栈溢出

分析完这一过程,相信大家对函数是怎么执行的应该明朗了,那么我们言归正传,继续聊一下栈溢出。首先我们先看一下什么是栈?

栈可以看作是一个漏斗,栈底地址大,栈顶地址小,然后在一个存储单元中,按照由小到大进行存储,它的目的是赋予程序一个方便的途径来访问特定函数的局部数据,并从函数调用者那边传递信息。

栈溢出属于缓冲区溢出,指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。

另外,我们也不难发现,发生栈溢出的基本前提是:程序必须向栈上写入数据、写入的数据大小没有被良好地控制。引用一个例子来了解一下栈溢出

#include <stdio.h>
#include <string.h>
void success() { puts("You Hava already controlled it."); }
void vulnerable() {
  char s[12];
  gets(s);
  puts(s);
  return;
}
int main(int argc, char **argv) {
  vulnerable();
  return 0;
}

很显然符合以上两个条件,gets()成为突破口我们在主函数处下断点,运行和调试

lea eax,dword ptr ss:[ebp-0x14] 这时开辟一个空间给变量,也即是s,如图所示

我们想执行sucess()函数,要怎么办呢?

执行完vulnerable()函数后,会还原ebp,改变esp的值(leave),然后retn,也就是pop eip,然后CPU根据eip指针指向的指令继续运行。

我们能抓到的点就是控制eip,怎么控制?通过控制栈顶的值,那么栈顶的值是什么?栈顶的值是进入该函数时储存的下一条指令的地址。这里提一点,进入函数,要保存两个值:下一条命令的地址、EBP旧栈帧的帧基指针,只有这样才能完全恢复。

此时我们可以构造payload,来控制我们要控制的地方,栈中存储EBP值的存储单元的上一个存储单元,也就是图中的存储address的存储单元

我们先试验一下输入0x14 *'A'+BBBB+0000,发生的变化

很好,按照我们的预想进行(python -c 'print "A"* 0x18+p32(0x00401520)') 就可以达到栈溢出的效果

0x04 尾记

还没有入门,只是个人的见解,如有错误,希望各位大佬指出。

(0)

相关推荐

  • 程序编译后运行时的内存分配

    一.编译时与运行时的内存情况 1.编译时不分配内存 编译时是不分配内存的.此时只是根据声明时的类型进行占位,到以后程序执行时分配内存才会正确.所以声明是给编译器看的,聪明的编译器能根据声明帮你识别错误 ...

  • 反调试入门篇(1)——花指令

    花指令 花指令是一种反静态调试的最基础手段(对于动态调试来说就没有用处),我们可以通过在程序的代码中添加一些不影响程序运行的垃圾机器码,进而影响反汇编结果的准确性,达到程序保护的目的 花指令分类 1. ...

  • 九阳电磁炉电路图及电路原理详解(图文)

    关于九阳电磁炉的电路图,九阳电磁炉整个电路的组成部分有哪些,九阳JYC-21CS21电磁炉电源电路的工作原理是怎么样的,电磁炉是应用电磁感应原理对食品进行加热的,一起来了解下. 九阳电磁炉的电路图 一 ...

  • 九阳电磁炉电路图及电路原理详解(2)

    九阳电磁炉电路图及电路原理详解(第2页) 三.九阳电磁炉的电路原理 电磁炉是应用电磁感应原理对食品进行加热的. 电磁炉的炉面是耐热陶瓷板,交变电流通过陶瓷板下方的线圈产生磁场,磁场内的磁力线穿过铁锅. ...

  • 过程能力指数Cp与Cpk计算原理详解

    [爆赞公开课]CQI-9热处理系统评估(第四版)公开课,2021年5月开课 [公开课]IATF16949:2016汽车工业内审员精品课程,5.15-5.16 GD&T培训苏州第24期,5.15 ...

  • ASIO4ALL,linkpro,studio one跳线原理详解与操作步骤

    1.1需要的软件: 1.ASIO4ALL:将板载声卡的WDM驱动转化为ASIO驱动 点亮同一声卡驱动下的麦克风和扬声器 2.Linkpro:调用ASIO驱动,创建N个虚拟的扬声器和虚拟的麦克风及音频通 ...

  • 好文分享:ext文件系统机制原理详解

    原文:https://www.cnblogs.com/f-ck-need-u/p/7016077.html作者:骏马金龙 文章有些长,但是作者总结的非常好,能学到很多技术细节知识.请大家耐心阅读. 将 ...

  • 水平电池技术原理详解

    1980年,美国军方为水平电池研究立项,开启了铅酸电池革命的序幕. 易德维能源科技有限公司攻克核心技术,成为世界上唯一批量生产商品化水平电池的制造商. 旭派水平电池,打破了铅酸电池一百六十多年的传统制 ...

  • 硬盘的读写原理详解

    作者 |hguisu 来源|https://reurl.cc/V3kAV6 硬盘的种类主要是SCSI .IDE .以及现在流行的SATA等:任何一种硬盘的生产都要一定的标准:随着相应的标准的升级,硬盘 ...

  • Buck电路工作原理详解

    Buck电路工作原理详解

  • 双稳态触发器的工作原理详解

    双稳态触发器是脉冲和数字电路中常用的基本触发器之一.双稳态触发器的特点是具有两个稳定的状态,并且在外加触发信号的作用下,可以由一种稳定状态转换为另一种稳定状态.在没有外加触发信号时,现有状态将一直保持 ...