一次基于windows_xp--SLmail服务的缓冲区溢出实践 一次基于windows_xp--SLmail服务的缓冲区溢出实践

20191331lyx

一、基本概念

  • 缓冲区溢出:当缓冲区边界限制不严格时,由于变量传入畸形数据或程序运行错误,导致缓冲区被填满从而覆盖了相邻内存区域的数据。可以修改内存数据,造成进程劫持,执行恶意代码,获取服务器控制权限等。

在Windows XP或2k3 server中的SLMail 5.5.0 Mail Server程序的POP3 PASS命令存在缓冲区溢出漏洞,无需身份验证实现远程代码执行。

Win7以上系统的防范机制可有效防止该缓冲区漏洞的利用:

  • DEP:阻止代码从数据页被执行;

  • ASLR:随机内存地址加载执行程序和DLL,每次重启地址变化。

二、实验环境准备

(1)攻击机:kali

(2)靶机:windows xp (关闭防火墙)

靶机环境准备:
邮件服务:SLMail 5.5.0 Mail Server
Debug工具:ImmunityDebugger_1_85_setup.exe
链接追踪工具:mona.py

SLmail安装:

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

将本地账户导入邮件服务器:

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

确认SLMail的端口是否正常开启

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

查看邮件相关服务是否启动

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

将mona.py复制到Immunity Debugger的PyCommands目录下

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

连通性测试

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

三、缓冲区溢出攻击

使用nc验证端口连接是否正常,测试pop3命令执行

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

测试 PASS 命令接收到大量数据时是否会溢出
EIP 寄存器:存放下一条指令的地址
pop3邮件服务侦听的端口是110,进程ID是832.

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

使用Immunity Debugger
file---attach---选中pid号为832的进程---attach调用

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

监控程运行状态

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

明确思路

漏洞利用原理:“PASS”命令后,当一些特殊定制的命令输入,会造成缓冲区溢出,上传shellcode,可控制目标系统,则不需要经过身份验证,获得权限。

(1)编写测试脚本,使用socket自动连接。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

(2)增大数据发送量,通过Debug确定是否会溢出。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

观察EIP确认溢出

EIP中的41是十六进制数,转换为字母就是A,也就是说此时EIP寄存器全部填满了AESP寄存器也被填满了A,每四个字节为一个存储单元进行存储,EIP就是当前邮件服务器SLmail下一个需要执行的指令的内存地址,所发送的A把下一条指令的内存地址给覆盖了,发生了缓冲区溢出。此时cpu会到EIP所在的内存地址中寻找指令代码,而该指令内存已被A全部覆盖,此时程序就会奔溃无法继续运行。

我们可以用shellcode填充EIP寄存器地址,这样就可能控制目标机器

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

注意每次溢出都会导致服务崩溃,因此需要每次实验前重启SLmail服务。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

(3)精确定位溢出的四个字节

使用唯一字符串法,可以在Kali Linux的/usr/share/metasploit-framework/tools/exploit/pattern_create.rb脚本中可以生成唯一字符串:

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

在Debug中找到溢出字节为8Di9

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

计算偏移量

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

精确的匹配出来偏移量是2606,也就是它前面有2606个字符,即8Di9中的8是第2607个字符。

(4)进行确认验证

buffer = 'A' * 2606+'LYXQ’+'C'*20

将前2606个字符替换为A,之后4个替换为B,再之后的20个字符替换为C,确认是否可以精确的把LYXQ写入EIP寄存器。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

确认

下一步思路:将EIP修改为shellcode代码的内存地址,将shellcode写入到该地址空间,程序读取EIP寄存器数值,将跳转到shellcode代码段并执行。

寻找可存放shellcode的内存空间(考虑ESP),修改EIP使其指向ESP所在的shellcode内存空间。

(5)修改字符C的填充量,判断内存空间大小能否存放shellcode
buffer = 'A' * 2606+'LYXQ'+'C'*(3500-2606+4) 让C去填满ESP的内存空间,判断C的个数。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

可以看到ESP起始地址为:01E7A154 终止地址为:01E7A2F4

使用结束地址01E7A2F4的后三位2F4减去开始地址01E7A154的后三位154,结果再转化为十进制,得结果为416

意味着ESP空间大小为416字节可以放下一个shellcode

(6)查找坏字符

由于不同类型的程序、协议、漏洞,会将某些字符认为是坏字符,这些字符有固定用途。如:

null byte (0x00)空字符,用于终止字符串的拷贝操作;return (0x0D)回车操作,表示POP3 PASS指令操作完毕。

而,返回地址、shellcode、buffer都不能出现坏字符。

所以我们筛查坏字符,发送0x00-0xff 256个字符进行筛查。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

验证得0A 为坏字符 ;0D为坏字符不出现,缩进一格,全部检查,发现00也被过滤,则可发现该实验中坏字符为:0x00 0x0D 0x0A

(7)重定向数据流
重定向数据流,用ESP的地址替换EIP的值,但是ESP的地址是变化的,不能使用硬编码。在SLMali线程应用程序中,操作系统为每个线程分配一段的地址范围,每个线程地址范围不确定。
所以我们可以从内存地址中寻找固定的系统模块,在模块中寻找JMP ESP指令的地址跳转,再由该指令间接跳转到ESP从而执行shellcode

JMP ESP是汇编指令,需要使用kali将其转换为二进制。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

!mona find -s "xffxe4" -m openc32.dll:在该进程模块查找是否有执行JMP ESP的命令
通过检查openc32.dll进程模块中没有可以执行JMP ESP的命令。

继续查找发现SLMFC.DLL支持执行JMP ESP的命令,并且有20个内存地址可以执行。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

打开内存地图,找到SLMFC模块的基地址5F400000,可以看到该内存中存放的是一个pe文件头。地址5F401000存放code。

找到JMP ESP地址为5F4B41E3。

(8)生成shellcode
这里为了绕过防火墙生成一个反弹shell

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

过滤坏字符并重新编码编码(将病毒的特征字符冲编写,可以在一定程度上实现免杀)

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

(9)缓冲区溢出攻击
将shellcode放入脚本。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

建立本地侦听 nc -nvlp 8888
执行脚本发送shellcode

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

缓冲区攻击成功,成功拿到靶机shell。

一次基于windows_xp--SLmail服务的缓冲区溢出实践
一次基于windows_xp--SLmail服务的缓冲区溢出实践

四、实践体会:

缓冲区溢出攻击,是利用“缓冲区溢出漏洞”所进行的攻击行动。“缓冲区溢出”是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用“缓冲区溢出”进行攻击,可以导致程序运行失败、系统关机、重新启动等后果。

缓冲区溢出,是指当计算机向缓冲区内填充数据位数时,超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上。理想的情况是:程序会检查数据长度,而且并不允许输入超过缓冲区长度的字符。但是绝大多数程序都会假设数据长度,总是与所分配的储存空间相匹配,这就为“缓冲区溢出”埋下了隐患。

操作系统所使用的缓冲区,又被称为“堆栈”,在各个操作进程之间,指令会被临时储存在“堆栈”当中,“堆栈”也会出现缓冲区溢出。

缓冲区溢出的危害非常大,通过植入并且执行攻击代码。攻击者可以利用“堆栈溢出”,在函数返回时,改变返回程序的地址,让其跳转到任意地址。这带来的危害,一种是程序崩溃导致拒绝服务;另外一种就是跳转并且执行一段恶意代码,然后得到shell,为所欲为。

五、思考

在进行程序设计时,为了防范缓冲区溢出攻击,可以采用哪些方法?

1、强制写正确的代码的方法
谨慎使用各种可能导致缓冲区溢出的函数,系统调用等。增加代码的健壮性,规范性,安全性。

2、通过操作系统使得缓冲区不可执行,从而阻止攻击者植入攻击代码

3、利用编译器的边界检查,来实现缓冲区的保护

4、在程序指针失效前进行完整性检查

5、定时检查你的计算机,关闭不必要的系统服务,并监控好已开启的服务