Skip to content

怎么开始编写 Exploit

L edited this page May 11, 2020 · 1 revision

Exploit 开发背后的真正功夫实际上并不在于你选择使用哪种语言来构建它, 而是与你对正在调试的应用程序如何处理输入以及如何通过操纵获得控制权的精确理解有关. 没错, 关键字是 "调试". 你的柔术 (逆向工程) 才是真正的功夫所在. 但是, 如果你的目标不仅是要弹出计算器, 而且实际上是想在现实世界中武器化, 维护和提供使用, 则需要一个开发框架. 这就是 Metasploit 的用武之地. 这个框架是免费和开源的, 由世界各地的研究人员积极贡献. 因此, 当你编写 Metasploit Exploit 程序时, 不必担心任何依赖关系问题, 版本错误或没有足够的 payload 来选择不同的渗透测试方案等. 你需要做的就是专注于开发该 Exploit, 仅此而已.

设计你的模块

与编写概念证明不同, 编写 Metasploit 模块时, 你需要考虑用户在现实世界中如何使用它. 隐蔽性通常是一个重要的考虑因素. 你的漏洞利用程序能否在不删除文件的情况下实现代码执行? 输入可以看起来更随机, 因此更难检测吗? 混淆呢? 它会产生不必要的流量吗? 它可以更稳定而不会导致系统崩溃太多等问题.

另外, 尝试精确地可利用的条件. 通常错误是特定于一系列版本甚至构建的程序. 如果你不能自动检查, 则至少需要在说明中提及它. 你的某些 Exploit 也可能是特定于应用程序的. 例如, 你可以利用应用程序中的特定行为以所需的方式生成堆分配, 但是在较新的版本中它可能更嘈杂, 从而给你带来一些稳定性问题. 它是否需要一个甚至可能不是每个人都安装的第三方组件才能工作? 即使是这样, 该组件是否还会经常修订, 这可能会使利用漏洞的可靠性降低?

知道在现实世界中, 你的 Exploit 可能以多种不同的方式终止或失败. 在学习困难的方法之前, 你应该尝试在开发和测试阶段找出并修复它.

可靠性等级

如你所见, 可靠性对于 Metasploit 非常重要, 我们尝试对此用户更加友好. 我知道你在想什么: "好吧, 如果他们正在使用该漏洞利用程序, 他们应该了解它的工作原理, 以便他们知道自己正在使用什么. " 在理想世界中, 是的. 知道漏洞的工作方式或漏洞利用的工作方式只会使用户受益, 但是你知道, 我们并不生活在完美的世界中. 如果你正在进行渗透测试, 则很难总是花时间重建漏洞环境, 将 Exploit 剥离为最基本的形式以调试正在发生的事情, 然后再进行测试. 你进入大型网络的时间很紧张, 因此你需要谨慎使用时间. 因此, 至少对模块有一个好的描述和参考很重要. 当然, 还有一个可以信任的可靠性等级系统.

Metasploit 框架有七个不同的等级来表明漏洞利用的可靠性. 有关更多详细信息, 请参见 Exploit 可靠性等级.

模板

如果你已读完本文, 我们认为你会给人留下深刻的印象, 因为要消化的东西很多. 你可能想知道为什么我们没有一行代码可以分享. 好了, 你还记得, 漏洞利用开发主要是关于你的逆向能力. 如果你拥有所有这些, 我们不应该告诉你如何编写漏洞利用程序. 到目前为止, 我们希望能正确传达你的想法, 以成为安全社区的 Metasploit 漏洞开发人员, 这意味着剩下的更多是关于如何使用我们的 Mixin 来构建该漏洞利用的. 因为有很多 Mixin, 所以不可能在一个页面中浏览所有这些, 因此你必须阅读API 文档, 现有代码示例, 或者查找我们为特定 Mixin 而编写的更多 Wiki 页面.

例如, 如果你正在寻找有关如何与 HTTP 服务器交互的文章, 那么你可能会感兴趣: 使用 HTTPClient 发送 HTTP 请求. 如果你对编写浏览器漏洞感兴趣, 请务必查看: 在浏览器 Exploit 中使用 BrowserExploitServer.

当然, 开始时, 你很可能需要一个模板来使用. 下面将说明如何填写必填字段:

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  def initialize(info={})
    super(update_info(info,
      'Name'           => "[Vendor] [Software] [Root Cause] [Vulnerability type]",
      'Description'    => %q{
        Say something that the user might need to know
      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'Name' ],
      'References'     =>
        [
          [ 'URL', '' ]
        ],
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ 'System or software version',
            {
              'Ret' => 0x41414141 # This will be available in `target.ret`
            }
          ]
        ],
      'Payload'        =>
        {
          'BadChars' => "\x00"
        },
      'Privileged'     => false,
      'DisclosureDate' => "",
      'DefaultTarget'  => 0))
  end

  def check
    # For the check command
  end

  def exploit
    # Main function
  end

end

Name 应该以供应商名称开头, 然后是软件. 理想情况下. "Root Cause" 字段表示找到该错误的组件或功能, 最后是模块漏洞类型.

Description 解释模块的作用, 包含需要注意的事情和特定要求越好. 目的是让用户了解他在使用什么, 而无需实际阅读模块的源代码并弄清楚事情. 相信我, 他们中的大多数都不知道.

Author 是你输入名字的地方. 格式应为 "名称". 如果你想在那里处理 Twitter, 请将其保留为注释, 例如: " Name#handle"

References 是与漏洞或 Exploit 相关的一系列参考链接. 例如: 咨询, 博客文章等. 确保你使用已知的参考标识符, 有关列表请参考Metasploit 模块参考标识.

Platform 指定支持的平台, 例如: win, linux, osx, unix, bsd.

Targets 攻击针对的系统, 应用程序, 设置或特定版本的数组. 第二个元素或每个目标数组是你存储有关该目标的特定元数据的位置, 例如: 特定偏移量, gadget, ret 地址等. 当用户选择目标时, 元数据将被加载并跟踪 "target index", 可以使用 target 方法进行检索.

Payloads 指定应如何编码和生成有效负载. 你可以指定: Space, SaveRegisters, Prepend, PrependEncoder, BadChars, Append, AppendEncoder, MaxNops, MinNops, Encoder, Nop, EncoderType, EncoderOptions, ExtendedOptions, EncoderDontFallThrough.

DisclosureDate 关于漏洞披露的日期: "M D Y". 例如: "Apr 04 2014"

你的漏洞利用还应该有一个支持 check 命令的检查方法, 但是在不可能的情况下这是可选的.

最后, 漏洞利用方法就像你的 main 方法一样. 从那里开始编写代码.

还提供了一个示例利用模块: example.rb

基础 git 命令

Metasploit 不再使用 svn 进行源代码管理, 而是使用 git, 因此了解 git 的一些技巧将大有帮助. 我们并不是在这里向你介绍 git 的出色表现, 我们知道它具有学习曲线, 并且发现新用户出错也就不足为奇了. git 利用分支对你来说很重要.

每次创建模块或对现有代码进行某些更改时, 都不应在默认的 master 分支上执行此操作. 为什么? 因为当你执行 msfupdate (这是 Metasploit 的用于更新的实用程序) 时, 它将在合并更改之前执行 git reset, 因此所有的修改都会消失.

另一个常见的错误是在提交 pull request 之前将所有更改都 commit 在 master 上. 这是个坏主意, 因为你很可能要提交其他你不想更改的修改, 并且你可能要求我们在仅需一次提交时合并其他不必要的提交历史记录.

因此, 作为一种习惯, 当你要创建或更改某些代码时, 请从一个新的分支开始, 该分支是最新的. 如果你执行 git status 则它会告诉你所在的分支.

$ git status
# On branch upstream-master
nothing to commit, working directory clean

好的, 现在执行 git pull 从 Metasploit 下载最新更改:

$ git pull
Already up-to-date.

此时, 你就可以开始新的分支了. 将新分支命名为 my_awesome_branch:

$ git checkout -b my_awesome_branch
Switched to a new branch 'my_awesome_branch'

然后, 你可以继续添加该 Exploit 模块. 确保它在正确的路径中:

$ git add [module path]

当你决定保存更改时, 提交 (如果只有一个模块, 你也可以执行 git commit -a, 因此你不必键入模块路径. 注意 -a 确实意味着所有) :

$ git commit [module path]

完成后, 请推送更改, 这会将你的代码上传到远程分支 my_awesome_branch. 你必须推送你的更改才能提交 pull request, 与 Internet 上的其他人共享请求.

$ git push origin my_awesome_branch

参考

https://github.com/rapid7/metasploit-framework/blob/master/lib/msf/core/exploit.rb

Clone this wiki locally