metasploit-framework/lib/msf/core/exploit/ndmp.rb

126 lines
2.6 KiB
Ruby

# -*- coding: binary -*-
require 'msf/core'
module Msf
###
#
# This module exposes methods for accessing NDMP services
#
###
module Exploit::Remote::NDMP
include Exploit::Remote::Tcp
#
# Creates an instance of a NDMP exploit module.
#
def initialize(info = {})
super
# Register the options that all NDMP exploits may make use of.
register_options(
[
Opt::RHOST,
Opt::RPORT(10000),
], Msf::Exploit::Remote::NDMP)
self.recv_buff = ''
end
#
# Flush the receive buffer on a new connection
#
def connect
super
self.recv_buff = ''
end
#
# This method dumps ndmp version information
#
def ndmp_info
connect
req = [
1, # Sequence number
Time.now.to_i, # Current time
0, # Message type (request)
0x108, # Message name (version)
0, # Reply sequence number
0, # Error status
].pack('NNNNNN')
resp = ndmp_recv()
ndmp_send(req)
resp = ndmp_recv()
disconnect
if !(resp and resp.length > 28)
return false
end
info = { }
i = 32
vend_len = resp[i, 4].unpack('N')[0]
vend = resp[i + 4, vend_len]
i += vend_len + 4 + 1
prod_len = resp[i, 4].unpack('N')[0]
prod = resp[i + 4, prod_len]
i += prod_len + 4 + 1
vers_len = resp[i, 4].unpack('N')[0]
vers = resp[i + 4, vers_len]
i += vers_len + 4 + 1
info['Version'] = vers
info['Product'] = prod
info['Vendor'] = vend
return info
end
#
# This method reads from the socket and parses out a single
# NDMP response, buffering the rest
#
def ndmp_recv(nsock = self.sock)
# Attempt to read at least four bytes (the length value)
if (self.recv_buff.length < 4)
self.recv_buff << ( sock.get_once( 4 - self.recv_buff.length, 5) || '' )
end
# If we did not receive a full length value, return early
if (self.recv_buff.length < 4)
return false
end
# Read the length header out of the message
dlen = self.recv_buff[0, 4].unpack('N')[0] & 0x7fffffff
# Read any pending data and append it to the buffer
self.recv_buff << ( sock.get_once || '' )
# Do we have the entire response message?
if (self.recv_buff.length >= dlen + 4)
return self.recv_buff.slice!(0, dlen + 4)
end
return false
end
#
# This method tacks a length header on a packet then sends
# it out the socket
#
def ndmp_send(data, nsock = self.sock)
nsock.put( [ data.length + 0x80000000 ].pack('N') + data )
end
attr_accessor :recv_buff
end
end