rex 2.0.8 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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}/ )