rex 2.0.8 → 2.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rex.rb +1 -0
  3. data/lib/rex/arch.rb +5 -0
  4. data/lib/rex/arch/x86.rb +19 -5
  5. data/lib/rex/arch/zarch.rb +17 -0
  6. data/lib/rex/compat.rb +5 -4
  7. data/lib/rex/constants.rb +3 -1
  8. data/lib/rex/encoder/alpha2/alpha_mixed.rb +70 -9
  9. data/lib/rex/encoder/alpha2/alpha_upper.rb +67 -8
  10. data/lib/rex/exploitation/cmdstager.rb +1 -0
  11. data/lib/rex/exploitation/cmdstager/certutil.rb +115 -0
  12. data/lib/rex/exploitation/cmdstager/echo.rb +6 -3
  13. data/lib/rex/exploitation/egghunter.rb +1 -1
  14. data/lib/rex/google/geolocation.rb +68 -0
  15. data/lib/rex/io/bidirectional_pipe.rb +0 -4
  16. data/lib/rex/java/serialization.rb +2 -0
  17. data/lib/rex/java/serialization/decode_error.rb +11 -0
  18. data/lib/rex/java/serialization/encode_error.rb +11 -0
  19. data/lib/rex/java/serialization/model.rb +2 -0
  20. data/lib/rex/java/serialization/model/annotation.rb +3 -3
  21. data/lib/rex/java/serialization/model/block_data.rb +3 -3
  22. data/lib/rex/java/serialization/model/block_data_long.rb +3 -3
  23. data/lib/rex/java/serialization/model/class_desc.rb +6 -6
  24. data/lib/rex/java/serialization/model/contents.rb +17 -10
  25. data/lib/rex/java/serialization/model/field.rb +12 -11
  26. data/lib/rex/java/serialization/model/long_utf.rb +3 -3
  27. data/lib/rex/java/serialization/model/new_array.rb +22 -23
  28. data/lib/rex/java/serialization/model/new_class.rb +57 -0
  29. data/lib/rex/java/serialization/model/new_class_desc.rb +15 -16
  30. data/lib/rex/java/serialization/model/new_enum.rb +5 -5
  31. data/lib/rex/java/serialization/model/new_object.rb +22 -17
  32. data/lib/rex/java/serialization/model/proxy_class_desc.rb +109 -0
  33. data/lib/rex/java/serialization/model/reference.rb +4 -4
  34. data/lib/rex/java/serialization/model/stream.rb +7 -7
  35. data/lib/rex/java/serialization/model/utf.rb +3 -3
  36. data/lib/rex/json_hash_file.rb +94 -0
  37. data/lib/rex/logging/log_sink.rb +1 -0
  38. data/lib/rex/logging/sinks/timestamp_flatfile.rb +21 -0
  39. data/lib/rex/parser/appscan_nokogiri.rb +13 -23
  40. data/lib/rex/parser/fs/ntfs.rb +10 -5
  41. data/lib/rex/parser/nmap_nokogiri.rb +3 -1
  42. data/lib/rex/parser/openvas_nokogiri.rb +70 -73
  43. data/lib/rex/parser/winscp.rb +108 -0
  44. data/lib/rex/parser/x509_certificate.rb +92 -0
  45. data/lib/rex/payloads.rb +0 -1
  46. data/lib/rex/payloads/meterpreter/config.rb +154 -0
  47. data/lib/rex/payloads/meterpreter/uri_checksum.rb +136 -0
  48. data/lib/rex/post/meterpreter.rb +1 -1
  49. data/lib/rex/post/meterpreter/client.rb +26 -3
  50. data/lib/rex/post/meterpreter/client_core.rb +387 -75
  51. data/lib/rex/post/meterpreter/extensions/android/android.rb +127 -37
  52. data/lib/rex/post/meterpreter/extensions/android/tlv.rb +46 -25
  53. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +4 -0
  54. data/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb +39 -0
  55. data/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb +44 -0
  56. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +9 -0
  57. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +16 -1
  58. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +1 -1
  59. data/lib/rex/post/meterpreter/extensions/python/python.rb +114 -0
  60. data/lib/rex/post/meterpreter/extensions/python/tlv.rb +21 -0
  61. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +17 -14
  62. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +33 -12
  63. data/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb +57 -0
  64. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3 -3
  65. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +3 -1
  66. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +2 -0
  67. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -3
  68. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +29 -6
  69. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +5 -1
  70. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +18 -6
  71. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +2 -2
  72. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +34 -36
  73. data/lib/rex/post/meterpreter/packet.rb +29 -0
  74. data/lib/rex/post/meterpreter/packet_dispatcher.rb +20 -7
  75. data/lib/rex/post/meterpreter/ui/console.rb +1 -0
  76. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +230 -72
  77. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +544 -34
  78. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +188 -57
  79. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +115 -93
  80. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +1 -1
  81. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +1 -1
  82. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +49 -15
  83. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +11 -2
  84. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb +187 -0
  85. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +324 -133
  86. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +52 -2
  87. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +68 -65
  88. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +9 -1
  89. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +113 -118
  90. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
  91. data/lib/rex/powershell.rb +62 -0
  92. data/lib/rex/powershell/command.rb +359 -0
  93. data/lib/rex/{exploitation/powershell → powershell}/function.rb +0 -2
  94. data/lib/rex/{exploitation/powershell → powershell}/obfu.rb +0 -2
  95. data/lib/rex/{exploitation/powershell → powershell}/output.rb +11 -5
  96. data/lib/rex/{exploitation/powershell → powershell}/param.rb +0 -2
  97. data/lib/rex/powershell/parser.rb +182 -0
  98. data/lib/rex/powershell/payload.rb +78 -0
  99. data/lib/rex/{exploitation/powershell → powershell}/psh_methods.rb +16 -2
  100. data/lib/rex/{exploitation/powershell → powershell}/script.rb +2 -4
  101. data/lib/rex/proto/dcerpc/client.rb +6 -6
  102. data/lib/rex/proto/dcerpc/exceptions.rb +26 -0
  103. data/lib/rex/proto/http/client.rb +3 -3
  104. data/lib/rex/proto/http/client_request.rb +0 -5
  105. data/lib/rex/proto/http/response.rb +86 -0
  106. data/lib/rex/proto/ipmi/utils.rb +30 -26
  107. data/lib/rex/proto/kerberos/client.rb +1 -1
  108. data/lib/rex/proto/kerberos/model/kdc_request.rb +2 -2
  109. data/lib/rex/proto/rfb/client.rb +8 -3
  110. data/lib/rex/proto/rfb/constants.rb +1 -1
  111. data/lib/rex/proto/rmi.rb +2 -0
  112. data/lib/rex/proto/rmi/decode_error.rb +10 -0
  113. data/lib/rex/proto/rmi/exception.rb +10 -0
  114. data/lib/rex/proto/rmi/model.rb +5 -0
  115. data/lib/rex/proto/rmi/model/call.rb +4 -4
  116. data/lib/rex/proto/rmi/model/call_data.rb +137 -0
  117. data/lib/rex/proto/rmi/model/dgc_ack.rb +2 -2
  118. data/lib/rex/proto/rmi/model/element.rb +26 -11
  119. data/lib/rex/proto/rmi/model/output_header.rb +4 -4
  120. data/lib/rex/proto/rmi/model/ping.rb +2 -2
  121. data/lib/rex/proto/rmi/model/ping_ack.rb +2 -2
  122. data/lib/rex/proto/rmi/model/protocol_ack.rb +2 -2
  123. data/lib/rex/proto/rmi/model/return_data.rb +5 -5
  124. data/lib/rex/proto/rmi/model/return_value.rb +124 -0
  125. data/lib/rex/proto/rmi/model/unique_identifier.rb +77 -0
  126. data/lib/rex/proto/steam.rb +3 -0
  127. data/lib/rex/proto/steam/message.rb +125 -0
  128. data/lib/rex/proto/tftp/client.rb +35 -14
  129. data/lib/rex/random_identifier_generator.rb +2 -0
  130. data/lib/rex/ropbuilder.rb +1 -1
  131. data/lib/rex/socket/parameters.rb +9 -0
  132. data/lib/rex/socket/ssl_tcp.rb +25 -41
  133. data/lib/rex/socket/ssl_tcp_server.rb +10 -21
  134. data/lib/rex/sslscan/result.rb +20 -1
  135. data/lib/rex/text.rb +241 -55
  136. data/lib/rex/ui/output.rb +0 -3
  137. data/lib/rex/ui/subscriber.rb +0 -10
  138. data/lib/rex/ui/text/color.rb +9 -0
  139. data/lib/rex/ui/text/dispatcher_shell.rb +1 -0
  140. data/lib/rex/ui/text/output.rb +15 -4
  141. data/lib/rex/ui/text/output/file.rb +1 -0
  142. data/lib/rex/ui/text/output/stdio.rb +0 -16
  143. data/lib/rex/ui/text/shell.rb +3 -0
  144. data/lib/rex/ui/text/table.rb +85 -19
  145. data/lib/rex/user_agent.rb +118 -0
  146. data/rex.gemspec +2 -2
  147. metadata +41 -14
  148. data/lib/rex/exploitation/powershell.rb +0 -62
  149. data/lib/rex/exploitation/powershell/parser.rb +0 -183
  150. data/lib/rex/payloads/meterpreter.rb +0 -2
  151. data/lib/rex/payloads/meterpreter/patch.rb +0 -136
@@ -29,8 +29,14 @@ class Console::CommandDispatcher::Core
29
29
  self.bgjobs = []
30
30
  self.bgjob_id = 0
31
31
 
32
+ # keep a lookup table to refer to transports by index
33
+ @transport_map = {}
32
34
  end
33
35
 
36
+ @@irb_opts = Rex::Parser::Arguments.new(
37
+ "-h" => [ false, "Help banner." ],
38
+ "-e" => [ true, "Expression to evaluate." ])
39
+
34
40
  @@load_opts = Rex::Parser::Arguments.new(
35
41
  "-l" => [ false, "List all available extensions" ],
36
42
  "-h" => [ false, "Help menu." ])
@@ -43,19 +49,22 @@ class Console::CommandDispatcher::Core
43
49
  "?" => "Help menu",
44
50
  "background" => "Backgrounds the current session",
45
51
  "close" => "Closes a channel",
46
- "channel" => "Displays information about active channels",
52
+ "channel" => "Displays information or control active channels",
47
53
  "exit" => "Terminate the meterpreter session",
48
54
  "help" => "Help menu",
49
- "interact" => "Interacts with a channel",
50
55
  "irb" => "Drop into irb scripting mode",
51
56
  "use" => "Deprecated alias for 'load'",
52
57
  "load" => "Load one or more meterpreter extensions",
58
+ "machine_id" => "Get the MSF ID of the machine attached to the session",
53
59
  "quit" => "Terminate the meterpreter session",
54
60
  "resource" => "Run the commands stored in a file",
61
+ "uuid" => "Get the UUID for the current session",
55
62
  "read" => "Reads data from a channel",
56
63
  "run" => "Executes a meterpreter script or Post module",
57
64
  "bgrun" => "Executes a meterpreter script as a background thread",
58
65
  "bgkill" => "Kills a background meterpreter script",
66
+ "get_timeouts" => "Get the current session timeout values",
67
+ "set_timeouts" => "Set the current session timeout values",
59
68
  "bglist" => "Lists running background scripts",
60
69
  "write" => "Writes data to a channel",
61
70
  "enable_unicode_encoding" => "Enables encoding of unicode strings",
@@ -65,14 +74,29 @@ class Console::CommandDispatcher::Core
65
74
  if client.passive_service
66
75
  c["detach"] = "Detach the meterpreter session (for http/https)"
67
76
  end
68
- # The only meterp that implements this right now is native Windows and for
69
- # whatever reason it is not adding core_migrate to its list of commands.
70
- # Use a dumb platform til it gets sorted.
71
- #if client.commands.include? "core_migrate"
77
+
78
+ # Currently we have some windows-specific core commands`
79
+ if client.platform =~ /win/
80
+ # only support the SSL switching for HTTPS
81
+ if client.passive_service && client.sock.type? == 'tcp-ssl'
82
+ c["ssl_verify"] = "Modify the SSL certificate verification setting"
83
+ end
84
+ end
85
+
72
86
  if client.platform =~ /win/ || client.platform =~ /linux/
87
+ # Migration only supported on windows and linux
73
88
  c["migrate"] = "Migrate the server to another process"
74
89
  end
75
90
 
91
+ if client.platform =~ /win/ || client.platform =~ /linux/ || client.platform =~ /python/ || client.platform =~ /java/
92
+ # Yet to implement transport hopping for other meterpreters.
93
+ c["transport"] = "Change the current transport mechanism"
94
+
95
+ # sleep functionality relies on the transport features, so only
96
+ # wire that in with the transport stuff.
97
+ c["sleep"] = "Force Meterpreter to go quiet, then re-establish session."
98
+ end
99
+
76
100
  if (msf_loaded?)
77
101
  c["info"] = "Displays information about a Post module"
78
102
  end
@@ -270,10 +294,6 @@ class Console::CommandDispatcher::Core
270
294
  # Disconnects the session
271
295
  #
272
296
  def cmd_detach(*args)
273
- if not client.passive_service
274
- print_error("Detach is only possible for non-stream sessions (http/https)")
275
- return
276
- end
277
297
  client.shutdown_passive_dispatcher
278
298
  shell.stop
279
299
  end
@@ -308,27 +328,508 @@ class Console::CommandDispatcher::Core
308
328
 
309
329
  alias cmd_interact_tabs cmd_close_tabs
310
330
 
331
+ def cmd_irb_help
332
+ print_line "Usage: irb"
333
+ print_line
334
+ print_line "Execute commands in a Ruby environment"
335
+ print @@irb_opts.usage
336
+ end
337
+
311
338
  #
312
339
  # Runs the IRB scripting shell
313
340
  #
314
341
  def cmd_irb(*args)
315
- print_status("Starting IRB shell")
316
- print_status("The 'client' variable holds the meterpreter client\n")
342
+ expressions = []
343
+
344
+ # Parse the command options
345
+ @@irb_opts.parse(args) do |opt, idx, val|
346
+ case opt
347
+ when '-e'
348
+ expressions << val
349
+ when '-h'
350
+ return cmd_irb_help
351
+ end
352
+ end
317
353
 
318
354
  session = client
319
355
  framework = client.framework
320
- Rex::Ui::Text::IrbShell.new(binding).run
356
+
357
+ if expressions.empty?
358
+ print_status("Starting IRB shell")
359
+ print_status("The 'client' variable holds the meterpreter client\n")
360
+
361
+ Rex::Ui::Text::IrbShell.new(binding).run
362
+ else
363
+ expressions.each { |expression| eval(expression, binding) }
364
+ end
365
+ end
366
+
367
+ @@set_timeouts_opts = Rex::Parser::Arguments.new(
368
+ '-c' => [ true, 'Comms timeout (seconds)' ],
369
+ '-x' => [ true, 'Expiration timout (seconds)' ],
370
+ '-t' => [ true, 'Retry total time (seconds)' ],
371
+ '-w' => [ true, 'Retry wait time (seconds)' ],
372
+ '-h' => [ false, 'Help menu' ])
373
+
374
+ def cmd_set_timeouts_help
375
+ print_line('Usage: set_timeouts [options]')
376
+ print_line
377
+ print_line('Set the current timeout options.')
378
+ print_line('Any or all of these can be set at once.')
379
+ print_line(@@set_timeouts_opts.usage)
380
+ end
381
+
382
+ def cmd_set_timeouts(*args)
383
+ if ( args.length == 0 or args.include?("-h") )
384
+ cmd_set_timeouts_help
385
+ return
386
+ end
387
+
388
+ opts = {}
389
+
390
+ @@set_timeouts_opts.parse(args) do |opt, idx, val|
391
+ case opt
392
+ when '-c'
393
+ opts[:comm_timeout] = val.to_i if val
394
+ when '-x'
395
+ opts[:session_exp] = val.to_i if val
396
+ when '-t'
397
+ opts[:retry_total] = val.to_i if val
398
+ when '-w'
399
+ opts[:retry_wait] = val.to_i if val
400
+ end
401
+ end
402
+
403
+ if opts.keys.length == 0
404
+ print_error("No options set")
405
+ else
406
+ timeouts = client.core.set_transport_timeouts(opts)
407
+ print_timeouts(timeouts)
408
+ end
409
+ end
410
+
411
+ def cmd_get_timeouts(*args)
412
+ # Calling set without passing values is the same as
413
+ # getting all the current timeouts
414
+ timeouts = client.core.set_transport_timeouts
415
+ print_timeouts(timeouts)
416
+ end
417
+
418
+ def print_timeouts(timeouts)
419
+ if timeouts[:session_exp]
420
+ print_line("Session Expiry : @ #{(Time.now + timeouts[:session_exp]).strftime('%Y-%m-%d %H:%M:%S')}")
421
+ end
422
+ if timeouts[:comm_timeout]
423
+ print_line("Comm Timeout : #{timeouts[:comm_timeout]} seconds")
424
+ end
425
+ if timeouts[:retry_total]
426
+ print_line("Retry Total Time: #{timeouts[:retry_total]} seconds")
427
+ end
428
+ if timeouts[:retry_wait]
429
+ print_line("Retry Wait Time : #{timeouts[:retry_wait]} seconds")
430
+ end
431
+ end
432
+
433
+ #
434
+ # Get the machine ID of the target
435
+ #
436
+ def cmd_machine_id(*args)
437
+ client.machine_id = client.core.machine_id unless client.machine_id
438
+ print_good("Machine ID: #{client.machine_id}")
439
+ end
440
+
441
+ #
442
+ # Get the machine ID of the target
443
+ #
444
+ def cmd_uuid(*args)
445
+ client.payload_uuid = client.core.uuid unless client.payload_uuid
446
+ print_good("UUID: #{client.payload_uuid}")
447
+ end
448
+
449
+ #
450
+ # Arguments for ssl verification
451
+ #
452
+ @@ssl_verify_opts = Rex::Parser::Arguments.new(
453
+ '-e' => [ false, 'Enable SSL certificate verification' ],
454
+ '-d' => [ false, 'Disable SSL certificate verification' ],
455
+ '-q' => [ false, 'Query the statis of SSL certificate verification' ],
456
+ '-h' => [ false, 'Help menu' ])
457
+
458
+ #
459
+ # Help for ssl verification
460
+ #
461
+ def cmd_ssl_verify_help
462
+ print_line('Usage: ssl_verify [options]')
463
+ print_line
464
+ print_line('Change and query the current setting for SSL verification')
465
+ print_line('Only one of the following options can be used at a time')
466
+ print_line(@@ssl_verify_opts.usage)
467
+ end
468
+
469
+ #
470
+ # Handle the SSL verification querying and setting function.
471
+ #
472
+ def cmd_ssl_verify(*args)
473
+ if ( args.length == 0 or args.include?("-h") )
474
+ cmd_ssl_verify_help
475
+ return
476
+ end
477
+
478
+ query = false
479
+ enable = false
480
+ disable = false
481
+
482
+ settings = 0
483
+
484
+ @@ssl_verify_opts.parse(args) do |opt, idx, val|
485
+ case opt
486
+ when '-q'
487
+ query = true
488
+ settings += 1
489
+ when '-e'
490
+ enable = true
491
+ settings += 1
492
+ when '-d'
493
+ disable = true
494
+ settings += 1
495
+ end
496
+ end
497
+
498
+ # Make sure only one action has been chosen
499
+ if settings != 1
500
+ cmd_ssl_verify_help
501
+ return
502
+ end
503
+
504
+ if query
505
+ hash = client.core.get_ssl_hash_verify
506
+ if hash
507
+ print_good("SSL verification is enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
508
+ else
509
+ print_good("SSL verification is disabled.")
510
+ end
511
+
512
+ elsif enable
513
+ hash = client.core.enable_ssl_hash_verify
514
+ if hash
515
+ print_good("SSL verification has been enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
516
+ else
517
+ print_error("Failed to enable SSL verification")
518
+ end
519
+
520
+ else
521
+ if client.core.disable_ssl_hash_verify
522
+ print_good('SSL verification has been disabled')
523
+ else
524
+ print_error("Failed to disable SSL verification")
525
+ end
526
+ end
527
+
528
+ end
529
+
530
+ #
531
+ # Display help for the sleep.
532
+ #
533
+ def cmd_sleep_help
534
+ print_line('Usage: sleep <time>')
535
+ print_line
536
+ print_line(' time: Number of seconds to wait (positive integer)')
537
+ print_line
538
+ print_line(' This command tells Meterpreter to go to sleep for the specified')
539
+ print_line(' number of seconds. Sleeping will result in the transport being')
540
+ print_line(' shut down and restarted after the designated timeout.')
541
+ end
542
+
543
+ #
544
+ # Handle the sleep command.
545
+ #
546
+ def cmd_sleep(*args)
547
+ if args.length == 0
548
+ cmd_sleep_help
549
+ return
550
+ end
551
+
552
+ seconds = args.shift.to_i
553
+
554
+ if seconds <= 0
555
+ cmd_sleep_help
556
+ return
557
+ end
558
+
559
+ print_status("Telling the target instance to sleep for #{seconds} seconds ...")
560
+ if client.core.transport_sleep(seconds)
561
+ print_good("Target instance has gone to sleep, terminating current session.")
562
+ client.shutdown_passive_dispatcher
563
+ shell.stop
564
+ else
565
+ print_error("Target instance failed to go to sleep.")
566
+ end
567
+ end
568
+
569
+ #
570
+ # Arguments for transport switching
571
+ #
572
+ @@transport_opts = Rex::Parser::Arguments.new(
573
+ '-t' => [ true, "Transport type: #{Rex::Post::Meterpreter::ClientCore::VALID_TRANSPORTS.keys.join(', ')}" ],
574
+ '-l' => [ true, 'LHOST parameter (for reverse transports)' ],
575
+ '-p' => [ true, 'LPORT parameter' ],
576
+ '-i' => [ true, 'Specify transport by index (currently supported: remove)' ],
577
+ '-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ],
578
+ '-ua' => [ true, 'User agent for HTTP/S transports (optional)' ],
579
+ '-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ],
580
+ '-pp' => [ true, 'Proxy port for HTTP/S transports (optional)' ],
581
+ '-pu' => [ true, 'Proxy username for HTTP/S transports (optional)' ],
582
+ '-ps' => [ true, 'Proxy password for HTTP/S transports (optional)' ],
583
+ '-pt' => [ true, 'Proxy type for HTTP/S transports (optional: http, socks; default: http)' ],
584
+ '-c' => [ true, 'SSL certificate path for https transport verification (optional)' ],
585
+ '-to' => [ true, 'Comms timeout (seconds) (default: same as current session)' ],
586
+ '-ex' => [ true, 'Expiration timout (seconds) (default: same as current session)' ],
587
+ '-rt' => [ true, 'Retry total time (seconds) (default: same as current session)' ],
588
+ '-rw' => [ true, 'Retry wait time (seconds) (default: same as current session)' ],
589
+ '-v' => [ false, 'Show the verbose format of the transport list' ],
590
+ '-h' => [ false, 'Help menu' ])
591
+
592
+ #
593
+ # Display help for transport management.
594
+ #
595
+ def cmd_transport_help
596
+ print_line('Usage: transport <list|change|add|next|prev|remove> [options]')
597
+ print_line
598
+ print_line(' list: list the currently active transports.')
599
+ print_line(' add: add a new transport to the transport list.')
600
+ print_line(' change: same as add, but changes directly to the added entry.')
601
+ print_line(' next: jump to the next transport in the list (no options).')
602
+ print_line(' prev: jump to the previous transport in the list (no options).')
603
+ print_line(' remove: remove an existing, non-active transport.')
604
+ print_line(@@transport_opts.usage)
605
+ end
606
+
607
+ def update_transport_map
608
+ result = client.core.transport_list
609
+ @transport_map.clear
610
+ sorted_by_url = result[:transports].sort_by { |k| k[:url] }
611
+ sorted_by_url.each_with_index { |t, i| @transport_map[i+1] = t }
612
+ end
613
+
614
+ #
615
+ # Manage transports
616
+ #
617
+ def cmd_transport(*args)
618
+ if ( args.length == 0 or args.include?("-h") )
619
+ cmd_transport_help
620
+ return
621
+ end
622
+
623
+ command = args.shift
624
+ unless ['list', 'add', 'change', 'prev', 'next', 'remove'].include?(command)
625
+ cmd_transport_help
626
+ return
627
+ end
628
+
629
+ opts = {
630
+ :uuid => client.payload_uuid,
631
+ :transport => nil,
632
+ :lhost => nil,
633
+ :lport => nil,
634
+ :uri => nil,
635
+ :ua => nil,
636
+ :proxy_host => nil,
637
+ :proxy_port => nil,
638
+ :proxy_type => nil,
639
+ :proxy_user => nil,
640
+ :proxy_pass => nil,
641
+ :comm_timeout => nil,
642
+ :session_exp => nil,
643
+ :retry_total => nil,
644
+ :retry_wait => nil,
645
+ :cert => nil,
646
+ :verbose => false
647
+ }
648
+
649
+ valid = true
650
+ transport_index = 0
651
+ @@transport_opts.parse(args) do |opt, idx, val|
652
+ case opt
653
+ when '-c'
654
+ opts[:cert] = val
655
+ when '-u'
656
+ opts[:uri] = val
657
+ when '-i'
658
+ transport_index = val.to_i
659
+ when '-ph'
660
+ opts[:proxy_host] = val
661
+ when '-pp'
662
+ opts[:proxy_port] = val.to_i
663
+ when '-pt'
664
+ opts[:proxy_type] = val
665
+ when '-pu'
666
+ opts[:proxy_user] = val
667
+ when '-ps'
668
+ opts[:proxy_pass] = val
669
+ when '-ua'
670
+ opts[:ua] = val
671
+ when '-to'
672
+ opts[:comm_timeout] = val.to_i if val
673
+ when '-ex'
674
+ opts[:session_exp] = val.to_i if val
675
+ when '-rt'
676
+ opts[:retry_total] = val.to_i if val
677
+ when '-rw'
678
+ opts[:retry_wait] = val.to_i if val
679
+ when '-p'
680
+ opts[:lport] = val.to_i if val
681
+ when '-l'
682
+ opts[:lhost] = val
683
+ when '-v'
684
+ opts[:verbose] = true
685
+ when '-t'
686
+ unless client.core.valid_transport?(val)
687
+ cmd_transport_help
688
+ return
689
+ end
690
+ opts[:transport] = val
691
+ else
692
+ valid = false
693
+ end
694
+ end
695
+
696
+ unless valid
697
+ cmd_transport_help
698
+ return
699
+ end
700
+
701
+ update_transport_map
702
+
703
+ case command
704
+ when 'list'
705
+ result = client.core.transport_list
706
+
707
+ current_transport_url = result[:transports].first[:url]
708
+
709
+ sorted_by_url = result[:transports].sort_by { |k| k[:url] }
710
+
711
+ # this will output the session timeout first
712
+ print_timeouts(result)
713
+
714
+ columns =[
715
+ 'ID',
716
+ 'Curr',
717
+ 'URL',
718
+ 'Comms T/O',
719
+ 'Retry Total',
720
+ 'Retry Wait'
721
+ ]
722
+
723
+ if opts[:verbose]
724
+ columns << 'User Agent'
725
+ columns << 'Proxy Host'
726
+ columns << 'Proxy User'
727
+ columns << 'Proxy Pass'
728
+ columns << 'Cert Hash'
729
+ end
730
+
731
+ # next draw up a table of transport entries
732
+ tbl = Rex::Ui::Text::Table.new(
733
+ 'SortIndex' => 0, # sort by ID
734
+ 'Indent' => 4,
735
+ 'Columns' => columns)
736
+
737
+ sorted_by_url.each_with_index do |t, i|
738
+ entry = [ i+1, (current_transport_url == t[:url]) ? '*' : '', t[:url],
739
+ t[:comm_timeout], t[:retry_total], t[:retry_wait] ]
740
+
741
+ if opts[:verbose]
742
+ entry << t[:ua]
743
+ entry << t[:proxy_host]
744
+ entry << t[:proxy_user]
745
+ entry << t[:proxy_pass]
746
+ entry << (t[:cert_hash] || '').unpack("H*")[0]
747
+ end
748
+
749
+ tbl << entry
750
+ end
751
+
752
+ print("\n" + tbl.to_s + "\n")
753
+ when 'next'
754
+ print_status("Changing to next transport ...")
755
+ if client.core.transport_next
756
+ print_good("Successfully changed to the next transport, killing current session.")
757
+ client.shutdown_passive_dispatcher
758
+ shell.stop
759
+ else
760
+ print_error("Failed to change transport, please check the parameters")
761
+ end
762
+ when 'prev'
763
+ print_status("Changing to previous transport ...")
764
+ if client.core.transport_prev
765
+ print_good("Successfully changed to the previous transport, killing current session.")
766
+ client.shutdown_passive_dispatcher
767
+ shell.stop
768
+ else
769
+ print_error("Failed to change transport, please check the parameters")
770
+ end
771
+ when 'change'
772
+ print_status("Changing to new transport ...")
773
+ if client.core.transport_change(opts)
774
+ print_good("Successfully added #{opts[:transport]} transport, killing current session.")
775
+ client.shutdown_passive_dispatcher
776
+ shell.stop
777
+ else
778
+ print_error("Failed to change transport, please check the parameters")
779
+ end
780
+ when 'add'
781
+ print_status("Adding new transport ...")
782
+ if client.core.transport_add(opts)
783
+ print_good("Successfully added #{opts[:transport]} transport.")
784
+ else
785
+ print_error("Failed to add transport, please check the parameters")
786
+ end
787
+ when 'remove'
788
+ if opts[:transport] && !opts[:transport].end_with?('_tcp') && opts[:uri].nil?
789
+ print_error("HTTP/S transport specified without session URI")
790
+ return
791
+ end
792
+
793
+ if !transport_index.zero? && @transport_map.has_key?(transport_index)
794
+ # validate the URL
795
+ url_to_delete = @transport_map[transport_index][:url]
796
+ begin
797
+ uri = URI.parse(url_to_delete)
798
+ opts[:transport] = "reverse_#{uri.scheme}"
799
+ opts[:lhost] = uri.host
800
+ opts[:lport] = uri.port
801
+ opts[:uri] = uri.path[1..-2] if uri.scheme.include?("http")
802
+
803
+ rescue URI::InvalidURIError
804
+ print_error("Failed to parse URL: #{url_to_delete}")
805
+ return
806
+ end
807
+ end
808
+
809
+ print_status("Removing transport ...")
810
+ if client.core.transport_remove(opts)
811
+ print_good("Successfully removed #{opts[:transport]} transport.")
812
+ else
813
+ print_error("Failed to remove transport, please check the parameters")
814
+ end
815
+ end
321
816
  end
322
817
 
818
+ @@migrate_opts = Rex::Parser::Arguments.new(
819
+ '-p' => [true, 'Writable path - Linux only (eg. /tmp).'],
820
+ '-t' => [true, 'The number of seconds to wait for migration to finish (default: 60).'],
821
+ '-h' => [false, 'Help menu.']
822
+ )
823
+
323
824
  def cmd_migrate_help
324
825
  if client.platform =~ /linux/
325
- print_line "Usage: migrate <pid> [writable_path]"
826
+ print_line('Usage: migrate <pid> [-p writable_path] [-t timeout]')
326
827
  else
327
- print_line "Usage: migrate <pid>"
828
+ print_line('Usage: migrate <pid> [-t timeout]')
328
829
  end
329
830
  print_line
330
- print_line "Migrates the server instance to another process."
331
- print_line "NOTE: Any open channels or other dynamic state will be lost."
831
+ print_line('Migrates the server instance to another process.')
832
+ print_line('NOTE: Any open channels or other dynamic state will be lost.')
332
833
  print_line
333
834
  end
334
835
 
@@ -339,19 +840,29 @@ class Console::CommandDispatcher::Core
339
840
  # platforms a path for the unix domain socket used for IPC.
340
841
  # @return [void]
341
842
  def cmd_migrate(*args)
342
- if ( args.length == 0 or args.include?("-h") )
843
+ if args.length == 0 || args.include?('-h')
343
844
  cmd_migrate_help
344
845
  return true
345
846
  end
346
847
 
347
848
  pid = args[0].to_i
348
- if(pid == 0)
349
- print_error("A process ID must be specified, not a process name")
849
+ if pid == 0
850
+ print_error('A process ID must be specified, not a process name')
350
851
  return
351
852
  end
352
853
 
353
- if client.platform =~ /linux/
354
- writable_dir = (args.length >= 2) ? args[1] : nil
854
+ writable_dir = nil
855
+ opts = {
856
+ timeout: nil
857
+ }
858
+
859
+ @@transport_opts.parse(args) do |opt, idx, val|
860
+ case opt
861
+ when '-t'
862
+ opts[:timeout] = val.to_i
863
+ when '-p'
864
+ writable_dir = val
865
+ end
355
866
  end
356
867
 
357
868
  begin
@@ -373,7 +884,7 @@ class Console::CommandDispatcher::Core
373
884
  service.each_tcp_relay do |lhost, lport, rhost, rport, opts|
374
885
  next unless opts['MeterpreterRelay']
375
886
  if existing_relays.empty?
376
- print_status("Removing existing TCP relays...")
887
+ print_status('Removing existing TCP relays...')
377
888
  end
378
889
  if (service.stop_tcp_relay(lport, lhost))
379
890
  print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}")
@@ -394,16 +905,15 @@ class Console::CommandDispatcher::Core
394
905
  server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}")
395
906
 
396
907
  # Do this thang.
397
- if client.platform =~ /linux/
398
- client.core.migrate(pid, writable_dir)
399
- else
400
- client.core.migrate(pid)
401
- end
908
+ client.core.migrate(pid, writable_dir, opts)
909
+
910
+ print_status('Migration completed successfully.')
402
911
 
403
- print_status("Migration completed successfully.")
912
+ # Update session info (we may have a new username)
913
+ client.update_session_info
404
914
 
405
915
  unless existing_relays.empty?
406
- print_status("Recreating TCP relay(s)...")
916
+ print_status('Recreating TCP relay(s)...')
407
917
  existing_relays.each do |r|
408
918
  client.pfservice.start_tcp_relay(r[:lport], r[:opts])
409
919
  print_status("Local TCP relay recreated: #{r[:opts]['LocalHost'] || '0.0.0.0'}:#{r[:lport]} <-> #{r[:opts]['PeerHost']}:#{r[:opts]['PeerPort']}")
@@ -431,8 +941,8 @@ class Console::CommandDispatcher::Core
431
941
  case opt
432
942
  when "-l"
433
943
  exts = SortedSet.new
434
- msf_path = MeterpreterBinaries.metasploit_data_dir
435
- gem_path = MeterpreterBinaries.local_dir
944
+ msf_path = MetasploitPayloads.msf_meterpreter_dir
945
+ gem_path = MetasploitPayloads.local_meterpreter_dir
436
946
  [msf_path, gem_path].each do |path|
437
947
  ::Dir.entries(path).each { |f|
438
948
  if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
@@ -479,8 +989,8 @@ class Console::CommandDispatcher::Core
479
989
 
480
990
  def cmd_load_tabs(str, words)
481
991
  tabs = SortedSet.new
482
- msf_path = MeterpreterBinaries.metasploit_data_dir
483
- gem_path = MeterpreterBinaries.local_dir
992
+ msf_path = MetasploitPayloads.msf_meterpreter_dir
993
+ gem_path = MetasploitPayloads.local_meterpreter_dir
484
994
  [msf_path, gem_path].each do |path|
485
995
  ::Dir.entries(path).each { |f|
486
996
  if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )