# -*- 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