119 lines
2.2 KiB
Ruby
119 lines
2.2 KiB
Ruby
|
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 MSSQL exploit module.
|
||
|
#
|
||
|
def initialize(info = {})
|
||
|
super
|
||
|
|
||
|
# Register the options that all FTP 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 (not (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)
|
||
|
if (self.recv_buff.length < 4)
|
||
|
self.recv_buff << (sock.get_once || '')
|
||
|
end
|
||
|
|
||
|
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
|
||
|
|
||
|
# 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
|