Module: Msf::Exploit::CmdStager
- Defined in:
- lib/msf/core/exploit/cmd_stager.rb,
lib/msf/core/exploit/cmd_stager/http.rb
Overview
This mixin provides an interface to generating cmdstagers
Defined Under Namespace
Modules: HTTP
Constant Summary collapse
- STAGERS =
Constant for stagers - used when creating an stager instance.
{ :bourne => Rex::Exploitation::CmdStagerBourne, :debug_asm => Rex::Exploitation::CmdStagerDebugAsm, :debug_write => Rex::Exploitation::CmdStagerDebugWrite, :echo => Rex::Exploitation::CmdStagerEcho, :printf => Rex::Exploitation::CmdStagerPrintf, :vbs => Rex::Exploitation::CmdStagerVBS, :vbs_adodb => Rex::Exploitation::CmdStagerVBS, :certutil => Rex::Exploitation::CmdStagerCertutil, :tftp => Rex::Exploitation::CmdStagerTFTP, :wget => Rex::Exploitation::CmdStagerWget, :curl => Rex::Exploitation::CmdStagerCurl, :fetch => Rex::Exploitation::CmdStagerFetch, :lwprequest => Rex::Exploitation::CmdStagerLwpRequest, :psh_invokewebrequest => Rex::Exploitation::CmdStagerPSHInvokeWebRequest, :ftp_http => Rex::Exploitation::CmdStagerFtpHttp, }
- DECODERS =
Constant for decoders - used when checking the default flavor decoder.
{ :debug_asm => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "debug_asm"), :debug_write => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "debug_write"), :vbs => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "vbs_b64"), :vbs_adodb => File.join(Rex::Exploitation::DATA_DIR, "exploits", "cmdstager", "vbs_b64_adodb") }
Instance Attribute Summary collapse
-
#cmd_list ⇒ Object
Returns the value of attribute cmd_list.
-
#decoder ⇒ Object
Returns the value of attribute decoder.
-
#exe ⇒ Object
Returns the value of attribute exe.
-
#flavor ⇒ Object
Returns the value of attribute flavor.
-
#stager_instance ⇒ Object
Returns the value of attribute stager_instance.
Attributes included from Remote::SocketServer
Instance Method Summary collapse
-
#compatible_flavor?(f) ⇒ Boolean
Answers if the input flavor is compatible with the current target or module.
-
#create_stager ⇒ Rex::Exploitation::CmdStagerBase
Create an instance of the flavored stager.
-
#default_decoder(f) ⇒ Symbol?
Returns the default decoder stub for the input flavor.
-
#execute_cmdstager(opts = {}) ⇒ void
Executes the command stager while showing the progress.
-
#execute_cmdstager_begin(opts = {}) ⇒ Object
Code to execute before the cmd stager stub.
-
#execute_cmdstager_end(opts = {}) ⇒ Object
Code to execute after the cmd stager stub.
-
#execute_command(cmd, opts = {}) ⇒ Object
Code called to execute each command via an arbitrary module-defined vector.
-
#generate_cmdstager(opts = {}, pl = nil) ⇒ Array
Generates a cmd stub based on the current target’s architecture and platform.
-
#guess_flavor ⇒ Symbol?
Guess the cmd stager flavor to use using information from the module, target or platform.
-
#initialize(info = {}) ⇒ Msf::Module::Exploit
Creates an instance of an exploit that uses an CMD Stager and register the datastore options provided by the mixin.
-
#module_flavors ⇒ Array
Returns all the compatible stager flavors specified by the module and each of its targets.
-
#opts_with_decoder(opts = {}) ⇒ Hash
Returns a hash with the :decoder option if possible.
-
#progress(total, sent) ⇒ void
Show the progress of the upload while cmd staging.
-
#select_cmdstager(opts = {}) ⇒ void
Selects the correct cmd stager and decoder stub to use.
-
#select_decoder(opts = {}) ⇒ String?
Selects the correct cmd stager decoder to use based on three rules: (1) use the decoder provided in input options, (2) use the decoder provided by the user through datastore options, (3) select the default decoder for the current cmd stager flavor if available.
-
#select_flavor(opts = {}) ⇒ Symbol?
Selects the correct cmd stager to use based on three rules: (1) use the flavor provided in options, (2) use the flavor provided by the user through datastore options, (3) guess the flavor using the target platform.
-
#target_flavor ⇒ Array, ...
Returns the compatible stager flavors for the current target or module.
Methods included from HTTP
#cmdstager_on_request_uri, #cmdstager_start_service
Methods included from Remote::HttpServer
#add_resource, #add_robots_resource, #autofilter, #check_dependencies, #cleanup, #cli, #cli=, #close_client, #create_response, #fingerprint_user_agent, #get_resource, #get_uri, #hardcoded_uripath, #on_request_uri, #print_prefix, #random_uri, #regenerate_payload, #remove_resource, #report_user_agent, #resource_uri, #send_local_redirect, #send_not_found, #send_redirect, #send_response, #send_robots, #srvhost_addr, #srvport, #start_service, #use_zlib
Methods included from Auxiliary::Report
#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot
Methods included from Metasploit::Framework::Require
optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines
Methods included from Remote::TcpServer
#on_client_close, #on_client_connect, #ssl, #ssl_cert, #ssl_cipher, #ssl_compression, #ssl_version, #start_service
Methods included from Remote::SocketServer
#_determine_server_comm, #bindhost, #bindport, #cleanup, #cleanup_service, #exploit, #on_client_data, #primer, #regenerate_payload, #srvhost, #srvport, #start_service, #via_string
Methods included from EXE
#exe_init_options, #exe_post_generation, #generate_payload_dccw_gdiplus_dll, #generate_payload_dll, #generate_payload_exe, #generate_payload_exe_service, #generate_payload_msi, #get_custom_exe, #get_eicar_exe
Instance Attribute Details
#cmd_list ⇒ Object
Returns the value of attribute cmd_list.
42 43 44 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 42 def cmd_list @cmd_list end |
#decoder ⇒ Object
Returns the value of attribute decoder.
44 45 46 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 44 def decoder @decoder end |
#exe ⇒ Object
Returns the value of attribute exe.
45 46 47 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 45 def exe @exe end |
#flavor ⇒ Object
Returns the value of attribute flavor.
43 44 45 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 43 def flavor @flavor end |
#stager_instance ⇒ Object
Returns the value of attribute stager_instance.
41 42 43 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 41 def stager_instance @stager_instance end |
Instance Method Details
#compatible_flavor?(f) ⇒ Boolean
Answers if the input flavor is compatible with the current target or module.
325 326 327 328 329 330 331 332 333 334 335 336 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 325 def compatible_flavor?(f) return true if target_flavor.nil? case target_flavor when String return true if target_flavor == f.to_s when Array target_flavor.each { |tr| return true if tr.to_sym == f } when Symbol return true if target_flavor == f end false end |
#create_stager ⇒ Rex::Exploitation::CmdStagerBase
Create an instance of the flavored stager.
213 214 215 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 213 def create_stager STAGERS[flavor].new(exe) end |
#default_decoder(f) ⇒ Symbol?
Returns the default decoder stub for the input flavor.
223 224 225 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 223 def default_decoder(f) DECODERS[f] end |
#execute_cmdstager(opts = {}) ⇒ void
This method returns an undefined value.
Executes the command stager while showing the progress. This method should be called from exploits using this mixin.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 86 def execute_cmdstager(opts = {}) self.cmd_list = generate_cmdstager(opts) stager_instance.setup(self) begin execute_cmdstager_begin(opts) sent = 0 total_bytes = 0 cmd_list.each { |cmd| total_bytes += cmd.bytesize } delay = opts[:delay] delay ||= 0.25 cmd_list.each do |cmd| # calculate string beforehand length in case exploit mutates string command_length = cmd.bytesize execute_command(cmd, opts) sent += command_length # In cases where a server has multiple threads, we want to be sure that # commands we execute happen in the correct (serial) order. ::IO.select(nil, nil, nil, delay) progress(total_bytes, sent) end execute_cmdstager_end(opts) ensure stager_instance.teardown(self) end end |
#execute_cmdstager_begin(opts = {}) ⇒ Object
Code to execute before the cmd stager stub. This method is designed to be overridden by a module this mixin.
342 343 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 342 def execute_cmdstager_begin(opts = {}) end |
#execute_cmdstager_end(opts = {}) ⇒ Object
Code to execute after the cmd stager stub. This method is designed to be overridden by a module this mixin.
349 350 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 349 def execute_cmdstager_end(opts = {}) end |
#execute_command(cmd, opts = {}) ⇒ Object
Code called to execute each command via an arbitrary module-defined vector. This method needs to be overridden by modules using this mixin.
357 358 359 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 357 def execute_command(cmd, opts = {}) raise NotImplementedError end |
#generate_cmdstager(opts = {}, pl = nil) ⇒ Array
Generates a cmd stub based on the current target’s architecture and platform.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 131 def generate_cmdstager(opts = {}, pl = nil) select_cmdstager(opts) exe_opts = {code: pl}.merge( platform: target_platform, arch: target_arch ) self.exe = generate_payload_exe(exe_opts) if exe.nil? raise ArgumentError, 'The executable could not be generated' end self.stager_instance = create_stager if datastore['CMDSTAGER::TEMP'] opts[:temp] = datastore['CMDSTAGER::TEMP'] elsif datastore['WritableDir'] opts[:temp] = datastore['WritableDir'] end if stager_instance.respond_to?(:http?) && stager_instance.http? opts[:ssl] = datastore['CMDSTAGER::SSL'] unless opts.key?(:ssl) opts['Path'] = datastore['CMDSTAGER::URIPATH'] unless datastore['CMDSTAGER::URIPATH'].blank? opts[:payload_uri] = cmdstager_start_service(opts) end cmd_list = stager_instance.generate(opts_with_decoder(opts)) if cmd_list.nil? || cmd_list.length.zero? raise ArgumentError, 'The command stager could not be generated' end vprint_status("Generated command stager: #{cmd_list.inspect}") cmd_list end |
#guess_flavor ⇒ Symbol?
Guess the cmd stager flavor to use using information from the module, target or platform.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 265 def guess_flavor # First try to guess a compatible flavor based on the module & target information. unless target_flavor.nil? case target_flavor when Array return target_flavor[0].to_sym when String return target_flavor.to_sym when Symbol return target_flavor end end # Second try to guess a compatible flavor based on the target platform. return nil unless target_platform.names.length == 1 c_platform = target_platform.names.first case c_platform when /linux/i :bourne when /osx/i :bourne when /unix/i :bourne when /win/i :vbs else nil end end |
#initialize(info = {}) ⇒ Msf::Module::Exploit
Creates an instance of an exploit that uses an CMD Stager and register the datastore options provided by the mixin.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 52 def initialize(info = {}) super flavors = module_flavors flavors = STAGERS.keys if flavors.empty? flavors.unshift('auto') server_conditions = ['CMDSTAGER::FLAVOR', 'in', %w{auto tftp wget curl fetch lwprequest psh_invokewebrequest ftp_http}] ( [ OptAddressLocal.new('SRVHOST', [true, 'The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses.', '0.0.0.0' ], conditions: server_conditions), OptPort.new('SRVPORT', [true, "The local port to listen on.", 8080], conditions: server_conditions) ]) ( [ OptEnum.new('CMDSTAGER::FLAVOR', [false, 'The CMD Stager to use.', 'auto', flavors]), OptString.new('CMDSTAGER::DECODER', [false, 'The decoder stub to use.']), OptString.new('CMDSTAGER::TEMP', [false, 'Writable directory for staged files']), OptString.new('CMDSTAGER::URIPATH', [false, 'Payload URI path for supported stagers']), OptBool.new('CMDSTAGER::SSL', [false, 'Use SSL/TLS for supported stagers', false]) ], self.class) end |
#module_flavors ⇒ Array
Returns all the compatible stager flavors specified by the module and each of its targets.
299 300 301 302 303 304 305 306 307 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 299 def module_flavors flavors = [] flavors += Array(module_info['CmdStagerFlavor']) if module_info['CmdStagerFlavor'] targets.each do |target| flavors += Array(target.opts['CmdStagerFlavor']) if target.opts['CmdStagerFlavor'] end flavors.uniq! flavors.map { |flavor| flavor.to_s } end |
#opts_with_decoder(opts = {}) ⇒ Hash
Returns a hash with the :decoder option if possible
202 203 204 205 206 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 202 def opts_with_decoder(opts = {}) return opts if opts.include?(:decoder) return opts.merge(:decoder => decoder) if decoder opts end |
#progress(total, sent) ⇒ void
This method returns an undefined value.
Show the progress of the upload while cmd staging
174 175 176 177 178 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 174 def progress(total, sent) done = (sent.to_f / total.to_f) * 100 percent = "%3.2f%%" % done.to_f print_status("Command Stager progress - %7s done (%d/%d bytes)" % [percent, sent, total]) end |
#select_cmdstager(opts = {}) ⇒ void
This method returns an undefined value.
Selects the correct cmd stager and decoder stub to use
189 190 191 192 193 194 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 189 def select_cmdstager(opts = {}) self.flavor = select_flavor(opts) raise ArgumentError, "Unable to select CMD Stager" if flavor.nil? raise ArgumentError, "The CMD Stager '#{flavor}' isn't compatible with the target" unless compatible_flavor?(flavor) self.decoder = select_decoder(opts) end |
#select_decoder(opts = {}) ⇒ String?
Selects the correct cmd stager decoder to use based on three rules: (1) use the decoder provided in input options, (2) use the decoder provided by the user through datastore options, (3) select the default decoder for the current cmd stager flavor if available.
237 238 239 240 241 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 237 def select_decoder(opts = {}) return opts[:decoder] if opts.include?(:decoder) return datastore['CMDSTAGER::DECODER'] unless datastore['CMDSTAGER::DECODER'].blank? default_decoder(flavor) end |
#select_flavor(opts = {}) ⇒ Symbol?
Selects the correct cmd stager to use based on three rules: (1) use the flavor provided in options, (2) use the flavor provided by the user through datastore options, (3) guess the flavor using the target platform.
252 253 254 255 256 257 258 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 252 def select_flavor(opts = {}) return opts[:flavor].to_sym if opts.include?(:flavor) unless datastore['CMDSTAGER::FLAVOR'].blank? or datastore['CMDSTAGER::FLAVOR'] == 'auto' return datastore['CMDSTAGER::FLAVOR'].to_sym end guess_flavor end |
#target_flavor ⇒ Array, ...
Returns the compatible stager flavors for the current target or module.
315 316 317 318 319 |
# File 'lib/msf/core/exploit/cmd_stager.rb', line 315 def target_flavor return target.opts['CmdStagerFlavor'] if target && target.opts['CmdStagerFlavor'] return module_info['CmdStagerFlavor'] if module_info['CmdStagerFlavor'] nil end |