-
Notifications
You must be signed in to change notification settings - Fork 3
怎么使用 Msf::Exploit::Remote::Tcp mixin
在 Metasploit 框架中, TCP 套接字被实现为 Rex::Socket::Tcp
, 它扩展了内置的 Ruby Socket 基类. 你应该始终使用 Rex 套接字而不是本机 Ruby 套接字, 因为如果不这样做, 你的套接字将无法由框架本身管理, 并且当然会缺少某些功能, 例如转发. Metasploit 文档目录中的 开发人员指南 解释了它是如何工作的.
对于模块开发, 通常你不会直接使用 Rex, 而是使用 Msf::Exploit::Remote::Tcp
混合. mixin 已经提供了一些你在开发过程中不必担心的有用功能, 例如 TCP 规避、代理、SSL 等. 你所要做的就是建立连接、发送某些内容、接收某些内容, 然后你就可以完毕.
听起来很容易, 对吧?
要使用 mixin, 只需在模块的 class MetasploitModule
范围内添加以下语句:
include Msf::Exploit::Remote::Tcp
当包含 mixin 时, 请注意将在你的模块下注册以下 datastore 选项:
- SSL - 协商 SSL 连接
- SSLVersion - SSL 使用的版本: SSL2, SSL3, TLS1. 默认为 TLS1.
- SSLVerifyMode - 验证模式: CLIENT_ONCE, FAIL_IF_NO_PEER_CERT, NONE, PEER. 默认是 PEER.
- Proxies - 允许模块支持代理.
- ConnectTimeout - 默认 10 秒.
- TCP::max_send_size - 回避选项. 最大 TCP 段大小.
- TCP::send_delay - 回避选项. 在每次发送之前插入延迟.
如果你想了解如何更改 datastore 选项的默认值, 请阅读 "更改 datastore 选项的默认值"
要建立连接, 只需执行以下操作:
connect
执行此操作时, connect
方法将调用 Rex::Socket::Tcp.create
来创建套接字, 并将其注册到框架. 它会自动检查 RHOST/RPORT 数据存储选项 (因此它知道连接到哪里) , 但你也可以手动更改:
# 连接到 metasploit.com
connect(true, {'RHOST'=>'208.118.237.137', 'RPORT'=>80})
然后 connect
方法将返回 Socket 对象, 该对象也可以全局访问.
connect 方法还可以引发一些你可能想要捕获的 Rex 异常, 包括:
- Rex::AddressInUse - 当它可能实际绑定到相同的 IP/端口时.
-
::Errno::ETIMEDOUT - 当
Timeout.timeout()
等待很长时间才能连接时. - Rex::HostUnreachable - 主机不可达.
- Rex::ConnectionTimeout - 连接超时.
- Rex::ConnectionRefused - 连接中断.
所以总结一下, 理想情况下, 当你使用 connect 方法时, 你应该 rescue
这些:
rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused
如果你好奇所有这些异常是在哪里引发的, 你可以在 lib/rex/socket/comm/local.rb 中查看.
有几种方法可以使用 Tcp mixin 发送数据. 为了让事情变得更容易和更安全, 我们建议只使用 put
方法:
sock.put "Hello, World!"
put
方法更安全的原因是它不允许线程永远挂起. 默认情况下, 它不会等待, 但如果你想让它更灵活, 你可以这样做:
begin
sock.put("data", {'Timeout'=>5})
rescue ::Timeout::Error
# 如果写入超时, 你可以决定该怎么做
end
现在, 我们来谈谈如何接收数据. 主要可以使用三种方法: get_once
, get
和 timed_read
.不同之处在于 get_once
只会尝试轮询流以查看是否有任何读取数据可用一次, 但 get
方法将继续读取, 直到没有更多内容为止. 至于 timed_read
, 它基本上是用 Timeout 包裹的 read
方法.
下面演示了如何使用 get_once
:
begin
buf = sock.get_once
rescue ::EOFError
end
请注意, 如果没有读取数据, get_once
也可能返回 nil, 或者如果它接收到 nil 作为数据, 它会遇到 EOFError. 所以请确保你在你的模块中捕捉到 nil .
数据读取方法可以在 lib/rex/io/stream.rb 中找到.
要断开连接, 只需执行以下操作:
disconnect
在 ensure
块中断开连接非常重要, 显然是为了确保在出现问题时始终断开连接. 如果你不这样做, 你最终可能会得到一个模块, 该模块只能向服务器发出一个请求 (即第一个请求) , 其余的都被破坏了.
以下示例应演示你通常希望如何使用 Tcp mixin:
# 发送一些数据到远程机器
#
# @param data [String] 需要发送的数据
# @return [String] 接受的数据
def send_recv_once(data)
buf = ''
begin
connect
sock.put(data)
buf = sock.get_once || ''
rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
ensure
disconnect
end
buf
end