逆向及BOF基础实践

逆向及BOF基础实践

20145316 许心远

  一、缓冲区溢出基础知识

  缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。第一个缓冲区溢出攻击--Morris蠕虫,发生在1988年,由罗伯特,莫里斯(R ob。rtMorris)制造,它曾造成全世界6000多台网络服务器瘫痪。

  计算机程序一般都会使用到一些内存,这些内存或是程序内部使用,或是存放用户的输入数据,这样的内存一般称作缓冲区。溢出是指盛放的东西超出容器容量而溢出来了,在计算机程序中,就是数据使用到了被分配内存空间之外的内存空间。而缓冲区溢出,简单的说就是计算机对接收的输入数据没有进行有效的检测(理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,使得溢出的数据覆盖了其他内存空间的数据。

  缓冲区溢出中,最为危险的是堆栈溢出,因为入侵者可以利用堆栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,带来的危害一种是程序崩溃导致拒绝服务,另外一种就是跳转并且执行一段恶意代码,比如得到shell,然后为所欲为。

  (本次实验就是跳转到shell)。

  缓冲区溢出攻击的目的在于扰乱具有某些特权运行的程序的功能,这样可以使得攻击者取得程序的控制权,如果该程序具有足够的权限,那么整个主机就被控制了。一般而言,攻击者攻击root程序,然后执行类似"exec(sh)"的执行代码来获得root权限的shell。为了达到这个目的,攻击者必须达到如下的两个目标:

  1. 在程序的地址空间里安排适当的代码。

  2. 通过适当的初始化寄存器和内存,让程序跳转到入侵者安排的地址空间执行。

  (本次实验是基于目标二的实现来完成的。)

  二、实践:通过构造输入参数,造成BOF攻击,改变程序执行流程

  (一)反汇编,了解程序的基本功能

                      1.先建立一个以自己学号姓名命名的个人文件夹,将pwn1放入

     

2.pwn1是可执行文件,直接运行即可,知道功能是回显输入

但输入过长时出现"segmentation fault"提示,即非法占用内存(缓冲区溢出)

3.用指令objdump反汇编pwn1,管道后的more表示按页显示,按空格键即可翻页

4.简单分析下反编译的代码

Main函数:注意main函数的第四行call 8048491<foo>,是跳转到foo函数的意思,这一行指令是本次实践的关键

 

Foo函数:本来应该跳转到的函数,功能是回显输出,但存在缓冲区溢出漏洞。系统只预留了?(不会看)字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址

Getshell函数:本实验我们目标要触发的就是这个"捣乱"的函数——恶意代码,它可以实现shell外壳的功能

  (二)确认输入字符串哪几个字符会覆盖到返回地址

1.gdb调试

2.尝试输入1111111122222222333333334444444455555555,观察各个寄存器数值

 

 

3.注意eip寄存器中的值为0x35353535,即5555的ASCII码。大家知道eip寄存器的功能就是保存程序下一步所要执行指令的地址,此处我们可以看出本来应返回到foo函数的返回地址已被"5555"覆盖

4.将本来"55555555"的地方替换为"12345678"更方便看出是字符串中哪几个字符实现了覆盖,根据eip中的ASCII码0x34333231发现是"1234"。

  (三)确认用什么值来覆盖返回地址

1.现在我们通过反汇编已知返回地址(getshell地址)应为0804847d,但并不确定要这台机器采用的字节序是大端还是小端,所以无法确定输入数据应为x08x04x84x7d还是x7dx84x04x08。

2.在输入字符串的地方0x804849d处设置断点,查其eip 0x804849d 0x804849d

3.再对比之前 eip 0x34333231 0x34333231 (4321对应ASCII码为34333231)所以得出正确应输入 11111111222222223333333344444444x7dx84x04x08

 



 

 

    

  (四)构造输入字符串

1.无法通过键盘输入x7dx84x04x08这样的16进制值(foo函数的输入是字符串形式,不是数值)

2.所以要先生成包括这样字符串的一个文件。x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。

 

 

3.使用输出重定向">"将perl生成的字符串存储到文件input中;然后用16进制查看指令xxd来查看字符串是否如愿重定向到input文件中

  (五)完成

将input的输入,通过管道符"|",作为pwn1的输入。因为我的pwn1文件在学号姓名文件夹和home文件夹里各放了一份,所以两个文件夹中各执行shell的ls指令结果不同。

 

 

三、实践:直接修改程序机器指令,改变程序执行流程

  (一)制作副本,观察反汇编代码。

1.制作一个pw1执行文件的副本,pw2,对其进行反汇编,观察<main>、<foo>、<getshell>的核心代码,找出可供改变程序执行流程的"空子"

 2.先看main函数反汇编的第4行,"call 8048491 "是汇编指令,是说这条指令将调用位于地址8048491处的foo函数;其对应机器指令为"e8 d7ffffff",e8即跳转之意。本来正常流程,此时此刻EIP的值应该是下条指令的地址,即80484ba,但一解释e8这条指令呢,CPU就会转而执行 "EIP + d7ffffff"这个位置的指令。"d7ffffff"是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491这个值(foo函数调用入口),

3.main函数调用foo,对应机器指令为" e8 d7ffffff",那我们想让它调用getShell,只要修改"d7ffffff"为,"getShell-80484ba"对应的补码就行。用Windows计算器,直接 47d-4ba就能得到补码,是c3ffffff。

4.下面我们就修改可执行文件,将其中的call指令的目标地址由d7ffffff变为c3ffffff

  (二)直接在vim编辑器中修改(需要知道各种编辑操作口令)

      

改正之后的汇编码,e8d7ffffff变为e8c3ffffff

 

  (三)在图形化的16进制编程器中完成修改

  1.安装wxhexeditor

  root@KaliYL:~# apt-get install wxhexeditor

  root@KaliYL:~# wxHexEditor

    

      2.在菜单栏的file中选择open打开pwn2文件

      

    3.利用查找工具等完成e8d7到e8c3的替换

    

  (四)完成

下面我们再反汇编一下,看看call指令是否正确调用getshell,结果是正确的,完成。

 

 四、实践:shellcode注入

下一篇日志:shellcode入门 http://www.cnblogs.com/xxy745214935/p/6477120.html

原文地址:https://www.cnblogs.com/xxy745214935/p/6445992.html