diff --git a/lib/msf/core/exploit/smb/server/share/information_level/query.rb b/lib/msf/core/exploit/smb/server/share/information_level/query.rb index 5d610326c8..da6aab7cbe 100644 --- a/lib/msf/core/exploit/smb/server/share/information_level/query.rb +++ b/lib/msf/core/exploit/smb/server/share/information_level/query.rb @@ -4,29 +4,34 @@ module Msf module Exploit::Remote::SMB::Server module Share module InformationLevel - # This mixin provides methods to handle TRAN2_QUERY_PATH_INFORMATION subcommands module Query + # Handles a TRANS2_QUERY_FILE_INFORMATION transaction request with SMB_QUERY_FILE_BASIC_INFO + # Information Level. # - # Responds to QUERY_PATH_INFO (Basic) requests - # + # @param c [Socket] The client sending the request. + # @param fid [Fixnum] The file identifier which the client is requesting info from. + # @return [Fixnum] The number of bytes returned to the client as response. def smb_cmd_trans_query_file_info_basic(c, fid) smb = @state[c] if fid.eql?smb[:file_id].to_i - attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL # File attributes => file - elsif fid.nil? || fid.empty? || fid == "\x00" # empty path - # QUERY_PATH_INFO_PARAMETERS doesn't include a file name, return a Directory answer - attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY # File attributes => directory + attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL + elsif fid.nil? || fid.empty? || fid == "\x00" # empty fid + attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY else - smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true) - return + return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true) end send_info_basic_res(c, { file_attributes: attrib }) end - # shortcut, we only have one file.... + # Handles a TRANS2_QUERY_FILE_INFORMATION transaction request with SMB_QUERY_FILE_STANDARD_INFO + # Information Level. + # + # @param c [Socket] The client sending the request. + # @param fid [Fixnum] The file identifier which the client is requesting info from. + # @return [Fixnum] The number of bytes returned to the client as response. def smb_cmd_trans_query_file_info_standard(c, fid) send_info_standard_res(c, { allocation_size: 1048576, @@ -37,9 +42,12 @@ module Msf }) end + # Handles a TRANS2_QUERY_PATH_INFORMATION transaction request with SMB_QUERY_FILE_BASIC_INFO + # Information Level. # - # Responds to QUERY_PATH_INFO (Basic) requests - # + # @param c [Socket] The client sending the request. + # @param path [String] The path which the client is requesting info from. + # @return [Fixnum] The number of bytes returned to the client as response. def smb_cmd_trans_query_path_info_basic(c, path) if path && path.ends_with?(file_name) #TODO: do it better attrib = CONST::SMB_EXT_FILE_ATTR_NORMAL @@ -50,58 +58,54 @@ module Msf elsif path.nil? || path.empty? || path == "\x00" # empty path attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY else - smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true) - return + return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true) end send_info_basic_res(c, { file_attributes: attrib }) end + # Handles a TRANS2_QUERY_PATH_INFORMATION transaction request with SMB_QUERY_FILE_STANDARD_INFO + # Information Level. # - # Responds to QUERY_PATH_INFO (Standard) requests - # - # At the moment we just support '\\' path always send a SUCCESS... + # @param c [Socket] The client sending the request. + # @param path [String] The path which the client is requesting info from. + # @return [Fixnum] The number of bytes returned to the client as response. def smb_cmd_trans_query_path_info_standard(c, path) - - puts "[smb_cmd_trans_query_path_info_standard] #{path}" - - if path && path.include?(file_name) #TODO: do it better + if path && path.include?(file_name) attrib = 0 # File attributes => file elsif path && path == path_name attrib = 1 # File attributes => directory elsif path.nil? || path.empty? || path == "\x00" # empty path attrib = 1 # File attributes => directory else - smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true) - return + return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true) end send_info_standard_res(c, { - allocation_size: 1048576, - number_links: 1, - delete_pending: 0, - directory: attrib, - end_of_file: exe_contents.length + allocation_size: 1048576, + number_links: 1, + delete_pending: 0, + directory: attrib, + end_of_file: exe_contents.length }) end + # Handles a TRANS2_QUERY_PATH_INFORMATION transaction request with SMB_QUERY_FILE_NETWORK_INFO + # Information Level. # - # Responds to QUERY_PATH_INFO (Network Open) requests - # - # At the moment we just support '\\' path always send a SUCCESS... + # @param c [Socket] The client sending the request. + # @param path [String] The path which the client is requesting info from. + # @return [Fixnum] The number of bytes returned to the client as response. def smb_cmd_trans_query_path_info_network(c, path) - if path && path.include?(file_name) #TODO: do it better - attrib = 0 # File attributes => file + if path && path.include?(file_name) + attrib = 0 elsif path && path == path_name - # QUERY_PATH_INFO_PARAMETERS doesn't include a file name, return a Directory answer - attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY # File attributes => directory + attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY elsif path.nil? || path.empty? || path == "\x00" # empty path - # QUERY_PATH_INFO_PARAMETERS doesn't include a file name, return a Directory answer - attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY # File attributes => directory + attrib = CONST::SMB_EXT_FILE_ATTR_DIRECTORY else - smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true) - return + return smb_error(CONST::SMB_COM_TRANSACTION2, c, CONST::SMB_STATUS_OBJECT_NAME_NOT_FOUND, true) end send_info_network_res(c, { @@ -111,6 +115,13 @@ module Msf }) end + # Builds and sends an TRANS2_QUERY_PATH_INFORMATION response with SMB_QUERY_FILE_BASIC_INFO + # information level. + # + # @param c [Socket] The client to answer. + # @param opts [Hash{Symbol => }] Response custom values. + # @option opts [Fixnum] :file_attributes The extended file attributes of the file. + # @return [Fixnum] The number of bytes returned to the client as response. def send_info_basic_res(c, opts = {}) file_attributes = opts[:file_attributes] || 0 @@ -131,6 +142,17 @@ module Msf send_trans2_res(c, trans2_params, query_path_info) end + # Builds and sends an TRANS2_QUERY_PATH_INFORMATION response with SMB_QUERY_FILE_STANDARD_INFO + # information level. + # + # @param c [Socket] The client to answer. + # @param opts [Hash{Symbol => }] Response custom values. + # @option opts [Fixnum] :allocation_size The number of bytes that are allocated to the file. + # @option opts [Fixnum] :number_links The number of hard links to the file. + # @option opts [Fixnum] :delete_pending Indicates whether there is a delete action pending for the file. + # @option opts [Fixnum] :directory Indicates whether the file is a directory. + # @option opts [Fixnum] :end_of_file The offset from the start to the end of the file. + # @return [Fixnum] The number of bytes returned to the client as response. def send_info_standard_res(c, opts = {}) allocation_size = opts[:allocation_size] || 0 number_links = opts[:number_links] || 0 @@ -151,6 +173,15 @@ module Msf send_trans2_res(c, trans2_params, query_path_info) end + # Builds and sends an TRANS2_QUERY_PATH_INFORMATION response with SMB_QUERY_FILE_NETWORK_INFO + # information level. + # + # @param c [Socket] The client to answer. + # @param opts [Hash{Symbol => }] Response custom values. + # @option opts [Fixnum] :allocation_size The number of bytes that are allocated to the file. + # @option opts [Fixnum] :end_of_file The offset from the start to the end of the file. + # @option opts [Fixnum] :file_attributes The file attributes. + # @return [Fixnum] The number of bytes returned to the client as response. def send_info_network_res(c, opts= {}) allocation_size = opts[:allocation_size] || 0 end_of_file = opts[:end_of_file] || 0