Metasploit攻击载荷介绍

Metasploit 结构

Metasploit 设计尽可能采用模块化的理念。大致由库文件、插件、接口、功能程序、模块等组成。

Metasploit V4结构如下:

模块是通过 Metasploit 框架所装载、集成并对外提供的最核心的渗透测试功能实现代码。分为辅助模块(Auxiliary)、渗透攻击模块(Exploits)、后渗透攻击模块(Post)、攻击载荷模块(payloads)、编码器模块(Encoders)、空指令模块(Nops)以及 V5 版本新增免杀模块(Evasion)。以下是模块的功能介绍:

  1. 辅助模块:通过对网络服务的扫描,收集登陆密码或者 Fuzz 测试发掘漏洞等方式取得目标系统丰富的情报信息,从而发起精准攻击。
  2. 渗透攻击模块:包括利用已发现的安全漏洞等方式对目标发起攻击,执行攻击载荷的主动攻击和利用伪造的 office 文档或浏览器等方式使目标上的用户自动触发执行攻击载荷的被动攻击。
  3. 空指令模块:跟随渗透攻击模块成功后的造成任何实质影响的空操作或者无关操作指令的无效植入代码,目的保证后面的攻击载荷能顺利执行。常见的在 x86 CPU 体系架构平台上的操作码是 0x90。
  4. 攻击载荷模块:跟随渗透攻击模块成功后在目标系统运行的有效植入代码,目标是建立连接,得到目标 shell。
  5. 编码器模块:同空指令模块作用相似,保证不会受到漏洞参数或者目标系统类型的限制导致无法顺利执行。
  6. 后渗透攻击模块:在获取到目标 shell 之后,进行后渗透攻击,比如获取信息,跳板甚至内网渗透。
  7. 免杀模块:作为 V5 版本新增的功能,只包含对 windows defender 类型。免杀方式较为简单,申请内存,拷贝攻击载荷,执行攻击载荷。

由其功能可以看出,除了漏洞代码外,其构造攻击载荷的核心在于攻击载荷模块和编码区模块。

(一)攻击载荷模块

攻击载荷模块的功能是依据不同平台,不同通讯方式以及不同执行方式的需求构造生成不同的基础 payload。

分类

攻击载荷模块在执行方式上分为独立 (Single)、传输器 (Stager)、传输体 (Stage),前者单独执行,后两种为共同执行的方式。

  • single:独立载荷,可直接植入目标系统并执行相应的程序。
  • stager:传输器载荷,用于目标机与攻击机之间建立稳定的网络连接,与传输体载荷配合攻击。通常该种载荷体积都非常小,可以在漏洞利用后方便注入。
  • stage:传输体载荷,如 shell、meterpreter 等。在 stager 建立好稳定的连接后,攻击机将 stage 传输给目标机,由 stagers 进行相应处理,将控制权转交给 stage。比如得到目标机的 shell,或者 meterpreter 控制程序运行。

其实 Single 等于 Stage 和 Stager 的集合,以下将着重讲解 Stage 和 Stager 的方式。Stage+Stager 应用在攻击载荷的大小、运行条件有限制的环境,比如漏洞填充缓冲区的可用空间很小、Windows 7 等新型操作系统所引入的 NX (堆栈不可执行)、DEP (数据执行保护)等安全防御机制,就像 web 入侵里面的通过小马上传大马类似,分阶段植入以达到目的。

传输器载荷 (Stager)

Stager的结构大致如下

首先清除标志位

使用 cld 清除标志位,避免前面的 nop 指令或者漏洞利用的代码等产生干扰,从而执行失败,然后跳转到执行远程连接行为。

在获取函数地址

Windows 系统下采用的方式是PEB寻址原理,Linux 下是采用 SysCall 系统调用号,这里阐释 Windows 的方式。如下图所示,在 NT 内核系统中 fs 寄存器指向 TEB 结构,TEB+0x30 处指向 PEB 结构,PEB+0x0c 处指向 PEB_LDR_DATA 结构,PEB_LDR_DATA 结构中包含本程序调用的 dll 链表,遍历链表,逐个遍历 dll 导出表的函数名称,算出其 Hash,对比传入的 Hash 相等即获取到函数地址。

获取函数地址结构图

此外,对于Cobalt Strike,其为获取函数地址所使用的寻址方式以及计算方式与 Metasploit 相同,所以函数 Hash 也相同,而且基于其兼容性问题,这些函数 Hash 短时间内也不会发生变化。

常见的函数 Hash 如下

然后执行网络连接

由于选择不同的连接方式会有不同的网络行为,从而会调用不同的函数,后面分析以 resever_tcp 为例,stager 通过 socket 连接指定的 IP 和 Port,建立连接后,申请内存,接收 stage 到申请的内存中,跳转到申请的内存地址首地址,然后开始执行 stage,完成交接。

函数调用顺序如下

传输体载荷(Stage)

在漏洞利用成功后会发送第二阶段的 Stage,本质上是个 dll。上面提到 Stager 在内存中拷贝完 Stage 后就跳转到内存的首地址了,然后从 dll 的头部开始执行并运行此 dll。

了解过程序运行原理的都知道,程序运行需要一个加载器加载程序,先解析程序结构,然后 CPU 才执行代码。然而这种传输的方式在内存中,并没有加载器,那么如何做到 dll 运行呢?即采用 ReflectiveLoader 反射注入的方式。

原理上简单来说就是通过前面执行的汇编先调用 ReflectiveLoader 反射函数,该函数模拟加载器解析自身的结构,然后跳转到 DllMain 正常执行。但由于 PE 文件的种种限制,所以这种文件的注入方式的特点比较明显。

构造基础 payload

在 kail 中集成了 Metasploit 框架,有两种方式。

  • 可以直接使用 Msfconsole 一体化集中控制台

  • 也可以使用 msfvenom 工具直接生成

(二)编码器模块

上文提到 stager 和 stage 的特征十分明显,杀毒软件非常容易检测到,并且可能由于渗透目标的种种限制,导致生成的 payload 可能无法正常使用。所以 Metasploit 集成了许多编码类型(Encode)以应对不同要求。

1)优点:使用编码生成的 payload 没有坏字符以及轻微免杀。

2)原理:基于异或的方式,但是方式不同,而且很多编码格式可以做到任意次多重编码或者多种编码格式混合编码,然而基于其实现的原理,每种编码格式又一定有相应的特征。这些特征就是识别解析的关键。

3)结构:异或循环结构+已异或的数据

这种异或循环是如何实现的?根据异或解密三要素:异或值(key),长度 (length) 以及数据地址 (addr) 可知其原理:

1)首先要找到异或后的数据起始地址,最简单的是汇编(call $+5)等获取当前地址等手段,再加上计算后的偏移得到数据起始地址;

2)其次数据的长度;

3)最后是异或密钥,可以是固定方式,也可以是与上一个密钥或揭秘内容有关的非固定方式。

以下将以 x86/shikata_ga_nai 编码为例,这种编码在 Metasploit 中最为实用和常用。

x86/shikata_ga_nai

使用 -e x86/shikata_ga_nai 选择编码格式为 x86/shikata_ga_nai,使用 -i 2 选择编码次数为 2 次,生成编码后 payload。