Skip to content
L edited this page May 24, 2022 · 2 revisions

在本页面

Meterpreter 总是需要动态配置, 以便它知道如何与 Metasploit 对话. 多年来, 这种配置管理是通过使用简单的"字符串替换"方法动态修改 metsrv DLL/二进制文件的副本来实现的. 足以支持多种情况, 但限制了 Meterpreter 的灵活性及其对处理多种传输的支持.

被锁定的不仅仅是传输, 而是提供比核心 Meterpreter (metsrv) 本身包含更多内容的 payload 的能力. 将其他形式的信息即时传递给 Meterpreter 实例也不容易, 因为 stagers 只能传递活动 socket 传输的 handler.

最近对 Meterpreter 的修改已经取消了这种旧方法, 取而代之的是一个动态配置块, 可以用来缓解这些问题, 并为其他更有趣的事情提供灵活性.

本文档包含有关新配置块的结构和布局的信息, 以及如何使用 Meterpreter.

如何找到配置

过去, Meterpreter 要求 stager (或某些人喜欢称之为 stage0) 将句柄传递给活动 socket, 以便它可以在不创建新 socket 的情况下接管通信 (至少在 TCP 连接的情况下) . 虽然仍然需要此功能, 但它不会像过去那样发生. 相反, Meterpreter 现在要求 stager 传入一个指向配置块开头的指针. 配置块可以在内存中的任何位置, 只要内存区域被标记为 RWX.

在 Windows Meterpreter 中加载配置

加载 Windows Meterpreter 的第 1 阶段现在使用一个新的加载程序, 称为 meterpreter_loader (Win x86, Win x64), 它执行以下操作:

  • 从磁盘加载 metsrv DLL.
  • 修补 DLL 的 DOS 标头, 使其包含正确初始化 metsrv 并计算指向内存中 metsrv 末尾的位置的可执行 shellcode. 它还接受任何现有的 socket 值 (根据架构在 edirdi 中找到) 并将其直接写入配置 (稍后会详细介绍) .
  • 生成一个配置块并将其附加到 metsrv 二进制文件中.

结果是, 一旦准备好 payload , 它就具有以下结构:

 +--------------+
 | Patched DOS  |
 |    header    |
 +--------------+
 |              |
 .              .
 .  metsrv dll  .
 .              .
 |              |
 +--------------+
 | config block |
 +--------------+

在 POSIX Meterpreter (Mettle) 中加载配置

POSIX Meterpreter 的所有配置都可以通过命令行参数传递给有效负载. 在生成具有特定配置的有效负载时, 将模拟命令行修补到主启动代码中的静态变量中. 生成有效负载并查看 ./mettle -h 以获取可用参数的完整描述.

Windows Meterpreter 配置块结构

为了将信息传递给 Meterpreter 并且不让它中断, 需要一种已知的配置格式. 这种格式需要在每次调用时保持一致, 就像你期望的任何配置一样. 对于二进制 Meterpreter (POSIX 和 Windows) , 此配置块包含以下内容:

  • 一个 Session 配置块.
  • 一个或多个传输配置块, 后跟一个终止符.
  • 一个或多个扩展配置块, 后跟一个终止符.

这些块中的每一个都在下面的部分中详细描述.

Session 配置块

Session 配置块的概念用于包装以下值:

  • Socket handle - 当使用 TCP 通信调用 Meterpreter 时, 活动套接字已在使用中. 此 socket handle 在 metsrv 执行时由 Meterpreter 重用. 这个 socket handle 由加载程序即时写入配置块. 它存储在 Session 配置块中, 因此它具有已知位置. 此值始终是 32 位 DWORD, 即使在 64 位平台上也是如此.
  • Exit func - 该值是一个 32 位 DWORD 值, 用于标识终止 Meterpreter 会话时应使用的方法. 此值等效于表示要调用的函数的 Block API Hash. Meterpreter 曾经将处理这个问题的责任委托给调用它的 stager. Meterpreter 不再这样做, 相反, 它自己处理 Meterpreter 会话的关闭, 因此必须在配置中知道所选择的终止方法.
  • Session expiry 值 - 这是一个 32 位 DWORD, 包含 Meterpreter 会话应持续的秒数. 在 Meterpreter 运行时, 会不断检查此值, 如果达到会话到期时间, 则 Meterpreter 会自行关闭. 欲了解更多信息, 请阅读 Meterpreter 超时控制.
  • UUID - 这是一个 16 字节的值, 表示有效负载 UUID. UUID 是 Metasploit 的一个新概念, 其目标是跟踪有效负载类型和来源, 并验证 Metasploit 接收的会话是否旨在供当前安装使用. 欲了解更多信息, 请阅读 Payload UUID.

该块在内存中的布局如下所示:

 +--------------+
 |Socket Handle |
 +--------------+
 |  Exit func   |
 +--------------+
 |Session Expiry|
 +--------------+
 |              |
 |     UUID     |
 |              |
 |              |
 +--------------+

  | <- 4 bytes ->|

有了这个结构, Meterpreter 就知道会话配置块的大小正好是 28 字节.

会话配置块描述可以在 Meterpreter 源代码 中找到

传输配置块

传输配置块是一个术语, 用于指代 Payload 中存在的传输配置组. Meterpreter 现在支持多种传输, 因此配置也应该支持多种传输.

处理传输配置时有两个主要问题:

  • 该配置应允许指定许多传输配置.
  • 配置应允许每个传输具有不同的类型和大小.

Meterpreter 当前的传输实现提供了两个主要的传输"类型", 即 HTTP(S)TCP. 这些传输类中的每一个都需要不同的配置值以及公共值才能起作用.

常用配置值

HTTP(S)TCP 传输的共同值是:

  • URL - 该值是传输的元描述, 不仅用作传输本身的配置元素, 而且还用作确定该块代表什么类型的传输的一种方式. 该字段共有 512 个字符 (Windows Meterpreter 使用 wchar_t, 而 POSIX Meterpreter 使用 char) . 传输类型由 URL 中的 scheme 元素指定, URL 的主体指定关键信息, 例如主机和端口信息. Meterpreter 检查它以确定正在使用的传输块类型, 因此能够确定块的大小. 有效值如下所示:
    • tcp://<host>:<port> - 表示此有效负载是 reverse IPv4 TCP 连接.
    • tcp6://<host>:<port>?<scope> - 表示此有效负载是 reverse IPv6 TCP 连接.
    • tcp://:<port> - 表示此 payload 是在指定端口上侦听的 bind 的 payload (注意没有指定主机) .
    • http://<host>:<port>/<uri> - 表示此 payload 是 HTTP 连接 (只能 reverse) .
    • https://<host>:<port>/<uri> - 表示此 payload 是 HTTPS 连接 (只能 reverse) .
  • Communications expiry - 此值是另一个 32 位 DWORD 值, 表示在成功的数据包/接收调用之间等待的秒数. 有关更多信息, 请阅读 超时文档 (链接即将推出) .
  • Retry total - 此值是 32 位 DWORD 值, 表示 Meterpreter 在放弃之前应继续尝试重新连接此传输的秒数. 有关更多信息, 请阅读 超时文档 (链接即将推出) .
  • Retry wait - 此值是 32 位 DWORD 值, 表示 Meterpreter 在此传输上重新连接的每次尝试之间的秒数. 有关更多信息, 请阅读 超时文档 (链接即将推出) .

此块在内存中的布局如下所示:

 +--------------+
 |              |
 |    URL       |
 .              .
 .              .  512 characters worth
 .              .  (POSIX -> ASCII -> char)
 .              .  (Windows -> wide char -> wchar_t)
 .              .
 |              |
 +--------------+
 |  Comms T/O   |
 +--------------+
 |  Retry Total |
 +--------------+
 |  Retry Wait  |
 +--------------+

  | <- 4 bytes ->|

常见的传输配置块描述可以在 Meterpreter 源码.

TCP 配置值

此时, 没有特定于 TCP 的配置值, 因为通用配置块满足 TCP 传输的所有需求. 这可能会改变轨迹.

HTTP/S 配置值

HTTPHTTPS 连接具有许多额外的配置值, 这些值是使其在各种环境中正常运行所必需的. 这些值是:

  • Proxy host - 在需要手动设置代理的环境中, 此字段包含要使用的代理的详细信息. 该字段的大小为 128 个字符 (仅 wchar_t, 因为我们在 POSIX 中还没有 HTTP/S 传输) , 并且可以采用以下格式之一:
    • http://<proxy ip>:<proxy port>HTTP 代理的情况.
    • socks=<socks ip>:<sock port>socks 代理的情况.
  • Proxy user name - 一些代理需要身份验证. 在这种情况下, 此值包含应用于向给定代理进行身份验证的用户名. 该字段的大小为 64 个字符 (wchar_t).
  • Proxy password - 在需要代理身份验证的情况下, 该值将伴随用户名字段. 它包含用于通过代理进行身份验证的密码, 大小也是 64 个字符 (wchar_t).
  • ** User agent string** - 可定制的用户代理字符串. 这会更改向 Metasploit 发出 HTTP/S 请求时使用的用户代理. 该字段的大小为 256 个字符 (wchar_t).
  • Expected SSL certificate hash - Meterpreter 能够验证 Metasploit 在使用 HTTPS 时提供的 SSL 证书. 此值包含预期证书的 20 字节 SHA1 哈希. 有关更多信息, 请阅读 SSL 证书验证文档 (链接即将推出) .

上面显示的所有值都需要在配置中指定, 包括普通 HTTP 连接的 SSL 证书验证. 未使用的值应清零.

HTTP/S 配置的结构如下.

 +--------------+
 |              |
 |  Proxy host  |
 .              .  128 characters worth (wchar_t)
 |              |
 +--------------+
 |              |
 |  Proxy user  |
 .              .  64 characters worth (wchar_t)
 |              |
 +--------------+
 |              |
 |  Proxy pass  |
 .              .  64 characters worth (wchar_t)
 |              |
 +--------------+
 |              |
 | User agent   |
 .              .  256 characters worth (wchar_t)
 |              |
 +--------------+
 |              |
 |  SSL cert    |
 |  SHA1 hash   |
 |              |
 |              |
 +--------------+

  | <- 4 bytes ->|

HTTP/S 传输配置块描述可以在 Meterpreter 源码 中找到.

传输配置列表

如前所述, 可以指定多个传输配置块. 为了促进这一点, Meterpreter 需要知道传输"列表"何时结束. 使用 URL, Meterpreter 可以确定块的大小并可以移动到下一个块, 具体取决于发现的类型. 一旦 Meterpreter 检测到字符串长度为零的传输配置 URL 值, 例如, POSIX 中的单个 NULL ASCII 字符和 Windows 中的单个 NULL 多字节字符, 它就会假定传输列表已终止. 紧随其后的字节被认为是扩展配置的开始, 这将在下一节中记录.

扩展配置块

扩展配置块旨在允许 Meterpreter 有效负载包含用户想要捆绑的任何额外扩展. 目标是提供拥有 Stageless payload 的能力 (链接即将推出) , 并提供在迁移期间共享扩展的方法 (尽管尚未实现). 每个扩展都必须使用 反射 DLL 注入 支持进行编译, 因为这是在 Meterpreter 启动时用于加载扩展的机制. 有关此工具的更多信息, 请参阅 Stagless payload (即将提供链接) 文档.

扩展配置块还用作"列表"以允许包含任意数量的扩展. 每个扩展条目需要包含:

  • Size - 这是扩展 DLL 本身的确切大小 (以字节为单位) . 该值为 32 位 DWORD.
  • Extension binary - 这是直接从 DLL 复制的完整二进制文件. 该值需要与 "Size" 字段中指定的长度完全相同.

从配置中加载扩展时, Meterpreter 将继续解析条目, 直到找到 size 值为 0. 此时, Meterpreter 假定它已到达扩展列表的末尾并停止解析.

该结构的布局简单如下:

 +--------------+
 |  Ext. Size   |
 +--------------+
 | Ext. content |
 +--------------+
 |  NULL term.  |
 |   (4 bytes)  |
 +--------------+

配置块概述

总而言之, 以下显示了完整配置的布局:

 +--------------+
 |Socket Handle |
 +--------------+
 |  Exit func   |
 +--------------+
 |Session Expiry|
 +--------------+
 |              |
 |      UUID    |
 |              |
 |              |
 +--------------+
 |  Transport 1 |
 |  tcp://...   |
 .              .
 |              |
 +--------------+
 |  Comms T/O   |
 +--------------+
 |  Retry Total |
 +--------------+
 |  Retry Wait  |
 +--------------+
 |  Transport 2 |
 |  http://...  |
 .              .
 |              |
 +--------------+
 |  Comms T/O   |
 +--------------+
 |  Retry Total |
 +--------------+
 |  Retry Wait  |
 +--------------+
 |              |
 |  Proxy host  |
 |              |
 +--------------+
 |              |
 |  Proxy user  |
 |              |
 +--------------+
 |              |
 |  Proxy pass  |
 |              |
 +--------------+
 |              |
 |  User agent  |
 |              |
 +--------------+
 |              |
 |   SSL cert   |
 |   SHA1 hash  |
 |              |
 +--------------+
 |  NULL term.  |
 |(1 or 2 bytes)|
 +--------------+
 | Ext 1. Size  |
 +--------------+
 |Ext 1. content|
 +--------------+
 | Ext 2. Size  |
 +--------------+
 |Ext 2. content|
 +--------------+
 |  NULL term.  |
 +--------------+
Clone this wiki locally