Class: Rex::Post::Meterpreter::Ui::Console::CommandDispatcher::Core
- Inherits:
-
Object
- Object
- Rex::Post::Meterpreter::Ui::Console::CommandDispatcher::Core
- Defined in:
- lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb
Overview
Core meterpreter client commands that provide only the required set of commands for having a functional meterpreter client<->server instance.
Constant Summary collapse
- @@load_opts =
Rex::Parser::Arguments.new( "-l" => [ false, "List all available extensions" ], "-h" => [ false, "Help menu." ])
- @@channel_opts =
Displays information about active channels
Rex::Parser::Arguments.new( "-c" => [ true, "Close the given channel." ], "-i" => [ true, "Interact with the given channel." ], "-l" => [ false, "List active channels." ], "-r" => [ true, "Read from the given channel." ], "-w" => [ true, "Write to the given channel." ], "-h" => [ false, "Help menu." ])
- @@write_opts =
Writes data to a channel.
Rex::Parser::Arguments.new( "-f" => [ true, "Write the contents of a file on disk" ], "-h" => [ false, "Help menu." ])
- @@client_extension_search_paths =
[ ::File.join(Rex::Root, "post", "meterpreter", "ui", "console", "command_dispatcher") ]
Instance Attribute Summary
Attributes included from Ui::Text::DispatcherShell::CommandDispatcher
Class Method Summary collapse
Instance Method Summary collapse
- #cmd_background ⇒ Object
- #cmd_background_help ⇒ Object
-
#cmd_bgkill(*args) ⇒ Object
Kill a background job.
-
#cmd_bglist(*args) ⇒ Object
List background jobs.
-
#cmd_bgrun(*args) ⇒ Object
Executes a script in the context of the meterpreter session in the background.
-
#cmd_bgrun_tabs(*args) ⇒ Object
Map this to the normal run command tab completion.
-
#cmd_channel(*args) ⇒ Object
Performs operations on the supplied channel.
- #cmd_channel_help ⇒ Object
-
#cmd_close(*args) ⇒ Object
Closes a supplied channel.
-
#cmd_exit(*args) ⇒ Object
(also: #cmd_quit)
Terminates the meterpreter session.
-
#cmd_info(*args) ⇒ Object
Show info for a given Post module.
- #cmd_info_help ⇒ Object
- #cmd_info_tabs(*args) ⇒ Object
-
#cmd_interact(*args) ⇒ Object
Interacts with a channel.
-
#cmd_irb(*args) ⇒ Object
Runs the IRB scripting shell.
-
#cmd_load(*args) ⇒ Object
Loads one or more meterpreter extensions.
- #cmd_load_help ⇒ Object (also: #cmd_use_help)
- #cmd_load_tabs(str, words) ⇒ Object (also: #cmd_use_tabs)
-
#cmd_migrate(*args) ⇒ Object
Migrates the server to the supplied process identifier.
-
#cmd_read(*args) ⇒ Object
Reads data from a channel.
- #cmd_resource(*args) ⇒ Object
- #cmd_resource_tabs(str, words) ⇒ Object
-
#cmd_run(*args) ⇒ Object
Executes a script in the context of the meterpreter session.
- #cmd_run_help ⇒ Object
- #cmd_run_tabs(str, words) ⇒ Object
- #cmd_use(*args) ⇒ Object
- #cmd_write(*args) ⇒ Object
- #cmd_write_help ⇒ Object
-
#commands ⇒ Object
List of supported commands.
-
#initialize(shell) ⇒ Core
constructor
Initializes an instance of the core command set using the supplied shell for interactivity.
-
#name ⇒ Object
Core baby.
Methods included from Rex::Post::Meterpreter::Ui::Console::CommandDispatcher
check_hash, #client, #log_error, #msf_loaded?, set_hash
Methods included from Ui::Text::DispatcherShell::CommandDispatcher
#cmd_help, #cmd_help_tabs, #print, #print_error, #print_good, #print_line, #print_status, #tab_complete_filenames, #update_prompt
Constructor Details
#initialize(shell) ⇒ Core
Initializes an instance of the core command set using the supplied shell for interactivity.
23 24 25 26 27 28 29 30 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 23 def initialize(shell) super self.extensions = [] self.bgjobs = [] self.bgjob_id = 0 end |
Class Method Details
.add_client_extension_search_path(path) ⇒ Object
698 699 700 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 698 def self.add_client_extension_search_path(path) @@client_extension_search_paths << path unless @@client_extension_search_paths.include?(path) end |
.client_extension_search_paths ⇒ Object
701 702 703 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 701 def self.client_extension_search_paths @@client_extension_search_paths end |
Instance Method Details
#cmd_background ⇒ Object
82 83 84 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 82 def cmd_background client.interacting = false end |
#cmd_background_help ⇒ Object
75 76 77 78 79 80 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 75 def cmd_background_help print_line "Usage: background" print_line print_line "Stop interacting with this session and return to the parent prompt" print_line end |
#cmd_bgkill(*args) ⇒ Object
Kill a background job
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 501 def cmd_bgkill(*args) if args.length == 0 print_line("Usage: bgkill [id]") return end args.each do |jid| jid = jid.to_i if self.bgjobs[jid] print_status("Killing background job #{jid}...") self.bgjobs[jid].kill self.bgjobs[jid] = nil else print_error("Job #{jid} was not running") end end end |
#cmd_bglist(*args) ⇒ Object
List background jobs
522 523 524 525 526 527 528 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 522 def cmd_bglist(*args) self.bgjobs.each_index do |jid| if self.bgjobs[jid] print_status("Job #{jid}: #{self.bgjobs[jid][:args].inspect}") end end end |
#cmd_bgrun(*args) ⇒ Object
Executes a script in the context of the meterpreter session in the background
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 462 def cmd_bgrun(*args) if args.length == 0 print_line( "Usage: bgrun <script> [arguments]\n\n" + "Executes a ruby script in the context of the meterpreter session.") return true end jid = self.bgjob_id self.bgjob_id += 1 # Get the script name self.bgjobs[jid] = Rex::ThreadFactory.spawn("MeterpreterBGRun(#{args[0]})-#{jid}", false, jid, args) do |myjid,xargs| ::Thread.current[:args] = xargs.dup begin # the rest of the arguments get passed in through the binding client.execute_script(args.shift, args) rescue ::Exception print_error("Error in script: #{$!.class} #{$!}") elog("Error in script: #{$!.class} #{$!}") dlog("Callstack: #{$@.join("\n")}") end self.bgjobs[myjid] = nil print_status("Background script with Job ID #{myjid} has completed (#{::Thread.current[:args].inspect})") end print_status("Executed Meterpreter with Job ID #{jid}") end |
#cmd_bgrun_tabs(*args) ⇒ Object
Map this to the normal run command tab completion
494 495 496 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 494 def cmd_bgrun_tabs(*args) cmd_run_tabs(*args) end |
#cmd_channel(*args) ⇒ Object
Performs operations on the supplied channel.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 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 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 107 def cmd_channel(*args) if args.include?("-h") or args.include?("--help") cmd_channel_help return end mode = nil chan = nil data = [] # Parse options @@channel_opts.parse(args) { |opt, idx, val| case opt when "-l" mode = :list when "-c" mode = :close chan = val when "-i" mode = :interact chan = val when "-r" mode = :read chan = val when "-w" mode = :write chan = val end if @@channel_opts.arg_required?(opt) unless chan print_error("Channel ID required") return end end } case mode when :list tbl = Rex::Ui::Text::Table.new( 'Indent' => 4, 'Columns' => [ 'Id', 'Class', 'Type' ]) items = 0 client.channels.each_pair { |cid, channel| tbl << [ cid, channel.class.cls, channel.type ] items += 1 } if (items == 0) print_line("No active channels.") else print("\n" + tbl.to_s + "\n") end when :close cmd_close(chan) when :interact cmd_interact(chan) when :read cmd_read(chan) when :write cmd_write(chan) else # No mode, no service. return true end end |
#cmd_channel_help ⇒ Object
97 98 99 100 101 102 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 97 def cmd_channel_help print_line "Usage: channel [options]" print_line print_line "Displays information about active channels." print_line @@channel_opts.usage end |
#cmd_close(*args) ⇒ Object
Closes a supplied channel.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 182 def cmd_close(*args) if (args.length == 0) print_line( "Usage: close channel_id\n\n" + "Closes the supplied channel.") return true end cid = args[0].to_i channel = client.find_channel(cid) if (!channel) print_error("Invalid channel identifier specified.") return true else channel._close # Issue #410 print_status("Closed channel #{cid}.") end end |
#cmd_exit(*args) ⇒ Object Also known as: cmd_quit
Terminates the meterpreter session.
206 207 208 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 206 def cmd_exit(*args) shell.stop end |
#cmd_info(*args) ⇒ Object
Show info for a given Post module.
See also cmd_info
in lib/msf/ui/console/command_dispatcher/core.rb
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 542 def cmd_info(*args) return unless msf_loaded? if args.length != 1 or args.include?("-h") cmd_info_help return end module_name = args.shift mod = client.framework.modules.create(module_name); if mod.nil? print_error 'Invalid module: ' << module_name end if (mod) print_line(::Msf::Serializer::ReadableText.dump_module(mod)) mod_opt = ::Msf::Serializer::ReadableText.(mod, ' ') print_line("\nModule options (#{mod.fullname}):\n\n#{mod_opt}") if (mod_opt and mod_opt.length > 0) end end |
#cmd_info_help ⇒ Object
530 531 532 533 534 535 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 530 def cmd_info_help print_line 'Usage: info <module>' print_line print_line 'Prints information about a post-exploitation module' print_line end |
#cmd_info_tabs(*args) ⇒ Object
564 565 566 567 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 564 def cmd_info_tabs(*args) return unless msf_loaded? tab_complete_postmods end |
#cmd_interact(*args) ⇒ Object
Interacts with a channel.
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 215 def cmd_interact(*args) if (args.length == 0) print_line( "Usage: interact channel_id\n\n" + "Interacts with the supplied channel.") return true end cid = args[0].to_i channel = client.find_channel(cid) if (channel) print_line("Interacting with channel #{cid}...\n") shell.interact_with_channel(channel) else print_error("Invalid channel identifier specified.") end end |
#cmd_irb(*args) ⇒ Object
Runs the IRB scripting shell
238 239 240 241 242 243 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 238 def cmd_irb(*args) print_status("Starting IRB shell") print_status("The 'client' variable holds the meterpreter client\n") Rex::Ui::Text::IrbShell.new(binding).run end |
#cmd_load(*args) ⇒ Object
Loads one or more meterpreter extensions.
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 281 def cmd_load(*args) if (args.length == 0) args.unshift("-h") end modules = nil @@load_opts.parse(args) { |opt, idx, val| case opt when "-l" exts = [] path = ::File.join(Msf::Config.install_root, 'data', 'meterpreter') ::Dir.entries(path).each { |f| if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ ) exts.push($1) end } print(exts.sort.join("\n") + "\n") return true when "-h" cmd_load_help return true end } # Load each of the modules args.each { |m| md = m.downcase if (extensions.include?(md)) print_error("The '#{md}' extension has already been loaded.") next end print("Loading extension #{md}...") begin # Use the remote side, then load the client-side if (client.core.use(md) == true) add_extension_client(md) end rescue print_line log_error("Failed to load extension: #{$!}") next end print_line("success.") } return true end |
#cmd_load_help ⇒ Object Also known as: cmd_use_help
271 272 273 274 275 276 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 271 def cmd_load_help print_line("Usage: load ext1 ext2 ext3 ...") print_line print_line "Loads a meterpreter extension module or modules." print_line @@load_opts.usage end |
#cmd_load_tabs(str, words) ⇒ Object Also known as: cmd_use_tabs
335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 335 def cmd_load_tabs(str, words) tabs = [] path = ::File.join(Msf::Config.install_root, 'data', 'meterpreter') ::Dir.entries(path).each { |f| if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ ) if (not extensions.include?($1)) tabs.push($1) end end } return tabs end |
#cmd_migrate(*args) ⇒ Object
Migrates the server to the supplied process identifier.
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 248 def cmd_migrate(*args) if (args.length == 0) print_line( "Usage: migrate pid\n\n" + "Migrates the server instance to another process.\n" + "Note: Any open channels or other dynamic state will be lost.") return true end pid = args[0].to_i if(pid == 0) print_error("A process ID must be specified, not a process name") return end print_status("Migrating to #{pid}...") # Do this thang. client.core.migrate(pid) print_status("Migration completed successfully.") end |
#cmd_read(*args) ⇒ Object
Reads data from a channel.
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 358 def cmd_read(*args) if (args.length == 0) print_line( "Usage: read channel_id [length]\n\n" + "Reads data from the supplied channel.") return true end cid = args[0].to_i length = (args.length >= 2) ? args[1].to_i : 16384 channel = client.find_channel(cid) if (!channel) print_error("Channel #{cid} is not valid.") return true end data = channel.read(length) if (data and data.length) print("Read #{data.length} bytes from #{cid}:\n\n#{data}\n") else print_error("No data was returned.") end return true end |
#cmd_resource(*args) ⇒ Object
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 659 def cmd_resource(*args) if args.empty? print( "Usage: resource path1 path2" + "Run the commands stored in the supplied files.\n") return false end args.each do |glob| files = ::Dir.glob(::File.(glob)) if files.empty? print_error("No such file #{glob}") next end files.each do |filename| print_status("Reading #{filename}") if (not ::File.readable?(filename)) print_error("Could not read file #{filename}") next else ::File.open(filename, "r").each_line do |line| next if line.strip.length < 1 next if line[0,1] == "#" begin print_status("Running #{line}") client.console.run_single(line) rescue ::Exception => e print_error("Error Running Command #{line}: #{e.class} #{e}") end end end end end end |
#cmd_resource_tabs(str, words) ⇒ Object
653 654 655 656 657 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 653 def cmd_resource_tabs(str, words) return [] if words.length > 1 tab_complete_filenames(str, words) end |
#cmd_run(*args) ⇒ Object
Executes a script in the context of the meterpreter session.
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 398 def cmd_run(*args) if args.length == 0 cmd_run_help return true end # Get the script name begin script_name = args.shift # First try it as a Post module if we have access to the Metasploit # Framework instance. If we don't, or if no such module exists, # fall back to using the scripting interface. if (msf_loaded? and mod = client.framework.modules.create(script_name)) omod = mod mod = client.framework.modules.reload_module(mod) if (not mod) print_error("Failed to reload module: #{client.framework.modules.failed[omod.file_path]}") return end opts = (args + [ "SESSION=#{client.sid}" ]).join(',') mod.run_simple( #'RunAsJob' => true, 'LocalInput' => shell.input, 'LocalOutput' => shell.output, 'OptionStr' => opts ) else # the rest of the arguments get passed in through the binding client.execute_script(script_name, args) end rescue print_error("Error in script: #{$!.class} #{$!}") elog("Error in script: #{$!.class} #{$!}") dlog("Callstack: #{$@.join("\n")}") end end |
#cmd_run_help ⇒ Object
386 387 388 389 390 391 392 393 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 386 def cmd_run_help print_line "Usage: run <script> [arguments]" print_line print_line "Executes a ruby script or Metasploit Post module in the context of the" print_line "meterpreter session. Post modules can take arguments in var=val format." print_line "Example: run post/foo/bar BAZ=abcd" print_line end |
#cmd_run_tabs(str, words) ⇒ Object
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 435 def cmd_run_tabs(str, words) tabs = [] if(not words[1] or not words[1].match(/^\//)) begin if (msf_loaded?) tabs += tab_complete_postmods end [ ::Msf::Sessions::Meterpreter.script_base, ::Msf::Sessions::Meterpreter.user_script_base ].each do |dir| next if not ::File.exist? dir tabs += ::Dir.new(dir).find_all { |e| path = dir + ::File::SEPARATOR + e ::File.file?(path) and ::File.readable?(path) } end rescue Exception end end return tabs.map { |e| e.sub(/\.rb$/, '') } end |
#cmd_use(*args) ⇒ Object
348 349 350 351 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 348 def cmd_use(*args) #print_error("Warning: The 'use' command is deprecated in favor of 'load'") cmd_load(*args) end |
#cmd_write(*args) ⇒ Object
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 583 def cmd_write(*args) if (args.length == 0 or args.include?("-h")) cmd_write_help return end src_file = nil cid = nil @@write_opts.parse(args) { |opt, idx, val| case opt when "-f" src_file = val else cid = val.to_i end } # Find the channel associated with this cid, assuming the cid is valid. if ((!cid) or (!(channel = client.find_channel(cid)))) print_error("Invalid channel identifier specified.") return true end # If they supplied a source file, read in its contents and write it to # the channel if (src_file) begin data = '' ::File.open(src_file, 'rb') { |f| data = f.read(f.stat.size) } rescue Errno::ENOENT print_error("Invalid source file specified: #{src_file}") return true end if (data and data.length > 0) channel.write(data) print_status("Wrote #{data.length} bytes to channel #{cid}.") else print_error("No data to send from file #{src_file}") return true end # Otherwise, read from the input descriptor until we're good to go. else print("Enter data followed by a '.' on an empty line:\n\n") data = '' # Keep truckin' while (s = shell.input.gets) break if (s =~ /^\.\r?\n?$/) data += s end if (!data or data.length == 0) print_error("No data to send.") else channel.write(data) print_status("Wrote #{data.length} bytes to channel #{cid}.") end end return true end |
#cmd_write_help ⇒ Object
576 577 578 579 580 581 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 576 def cmd_write_help print_line "Usage: write [options] channel_id" print_line print_line "Writes data to the supplied channel." print_line @@write_opts.usage end |
#commands ⇒ Object
List of supported commands.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 39 def commands c = { "?" => "Help menu", "background" => "Backgrounds the current session", "close" => "Closes a channel", "channel" => "Displays information about active channels", "exit" => "Terminate the meterpreter session", "help" => "Help menu", "interact" => "Interacts with a channel", "irb" => "Drop into irb scripting mode", "migrate" => "Migrate the server to another process", "use" => "Deprecated alias for 'load'", "load" => "Load one or more meterpreter extensions", "quit" => "Terminate the meterpreter session", "resource" => "Run the commands stored in a file", "read" => "Reads data from a channel", "run" => "Executes a meterpreter script or Post module", "bgrun" => "Executes a meterpreter script as a background thread", "bgkill" => "Kills a background meterpreter script", "bglist" => "Lists running background scripts", "write" => "Writes data to a channel", } if (msf_loaded?) c["info"] = "Displays information about a Post module" end c end |
#name ⇒ Object
Core baby.
71 72 73 |
# File 'lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb', line 71 def name "Core" end |