126 lines
2.6 KiB
Ruby
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
|
|
|