Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

core.rb 40KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491
  1. # -*- coding: binary -*-
  2. require 'set'
  3. require 'rex/post/meterpreter'
  4. require 'rex/parser/arguments'
  5. module Rex
  6. module Post
  7. module Meterpreter
  8. module Ui
  9. ###
  10. #
  11. # Core meterpreter client commands that provide only the required set of
  12. # commands for having a functional meterpreter client<->server instance.
  13. #
  14. ###
  15. class Console::CommandDispatcher::Core
  16. include Console::CommandDispatcher
  17. #
  18. # Initializes an instance of the core command set using the supplied shell
  19. # for interactivity.
  20. #
  21. def initialize(shell)
  22. super
  23. self.extensions = []
  24. self.bgjobs = []
  25. self.bgjob_id = 0
  26. # keep a lookup table to refer to transports by index
  27. @transport_map = {}
  28. end
  29. @@irb_opts = Rex::Parser::Arguments.new(
  30. "-h" => [ false, "Help banner." ],
  31. "-e" => [ true, "Expression to evaluate." ])
  32. @@load_opts = Rex::Parser::Arguments.new(
  33. "-l" => [ false, "List all available extensions" ],
  34. "-h" => [ false, "Help menu." ])
  35. #
  36. # List of supported commands.
  37. #
  38. def commands
  39. c = {
  40. "?" => "Help menu",
  41. "background" => "Backgrounds the current session",
  42. "close" => "Closes a channel",
  43. "channel" => "Displays information or control active channels",
  44. "exit" => "Terminate the meterpreter session",
  45. "help" => "Help menu",
  46. "irb" => "Drop into irb scripting mode",
  47. "use" => "Deprecated alias for 'load'",
  48. "load" => "Load one or more meterpreter extensions",
  49. "machine_id" => "Get the MSF ID of the machine attached to the session",
  50. "quit" => "Terminate the meterpreter session",
  51. "resource" => "Run the commands stored in a file",
  52. "uuid" => "Get the UUID for the current session",
  53. "read" => "Reads data from a channel",
  54. "run" => "Executes a meterpreter script or Post module",
  55. "bgrun" => "Executes a meterpreter script as a background thread",
  56. "bgkill" => "Kills a background meterpreter script",
  57. "get_timeouts" => "Get the current session timeout values",
  58. "set_timeouts" => "Set the current session timeout values",
  59. "bglist" => "Lists running background scripts",
  60. "write" => "Writes data to a channel",
  61. "enable_unicode_encoding" => "Enables encoding of unicode strings",
  62. "disable_unicode_encoding" => "Disables encoding of unicode strings"
  63. }
  64. if client.passive_service
  65. c["detach"] = "Detach the meterpreter session (for http/https)"
  66. end
  67. # Currently we have some windows-specific core commands`
  68. if client.platform =~ /win/
  69. # only support the SSL switching for HTTPS
  70. if client.passive_service && client.sock.type? == 'tcp-ssl'
  71. c["ssl_verify"] = "Modify the SSL certificate verification setting"
  72. end
  73. end
  74. if client.platform =~ /win/ || client.platform =~ /linux/
  75. # Migration only supported on windows and linux
  76. c["migrate"] = "Migrate the server to another process"
  77. end
  78. if client.platform =~ /win/ || client.platform =~ /linux/ || client.platform =~ /python/ || client.platform =~ /java/
  79. # Yet to implement transport hopping for other meterpreters.
  80. c["transport"] = "Change the current transport mechanism"
  81. # sleep functionality relies on the transport features, so only
  82. # wire that in with the transport stuff.
  83. c["sleep"] = "Force Meterpreter to go quiet, then re-establish session."
  84. end
  85. if (msf_loaded?)
  86. c["info"] = "Displays information about a Post module"
  87. end
  88. c
  89. end
  90. #
  91. # Core baby.
  92. #
  93. def name
  94. "Core"
  95. end
  96. def cmd_background_help
  97. print_line "Usage: background"
  98. print_line
  99. print_line "Stop interacting with this session and return to the parent prompt"
  100. print_line
  101. end
  102. def cmd_background
  103. print_status "Backgrounding session #{client.name}..."
  104. client.interacting = false
  105. end
  106. #
  107. # Displays information about active channels
  108. #
  109. @@channel_opts = Rex::Parser::Arguments.new(
  110. "-c" => [ true, "Close the given channel." ],
  111. "-k" => [ true, "Close the given channel." ],
  112. "-i" => [ true, "Interact with the given channel." ],
  113. "-l" => [ false, "List active channels." ],
  114. "-r" => [ true, "Read from the given channel." ],
  115. "-w" => [ true, "Write to the given channel." ],
  116. "-h" => [ false, "Help menu." ])
  117. def cmd_channel_help
  118. print_line "Usage: channel [options]"
  119. print_line
  120. print_line "Displays information about active channels."
  121. print_line @@channel_opts.usage
  122. end
  123. #
  124. # Performs operations on the supplied channel.
  125. #
  126. def cmd_channel(*args)
  127. if args.empty? or args.include?("-h") or args.include?("--help")
  128. cmd_channel_help
  129. return
  130. end
  131. mode = nil
  132. chan = nil
  133. # Parse options
  134. @@channel_opts.parse(args) { |opt, idx, val|
  135. case opt
  136. when "-l"
  137. mode = :list
  138. when "-c", "-k"
  139. mode = :close
  140. chan = val
  141. when "-i"
  142. mode = :interact
  143. chan = val
  144. when "-r"
  145. mode = :read
  146. chan = val
  147. when "-w"
  148. mode = :write
  149. chan = val
  150. end
  151. if @@channel_opts.arg_required?(opt)
  152. unless chan
  153. print_error("Channel ID required")
  154. return
  155. end
  156. end
  157. }
  158. case mode
  159. when :list
  160. tbl = Rex::Text::Table.new(
  161. 'Indent' => 4,
  162. 'Columns' =>
  163. [
  164. 'Id',
  165. 'Class',
  166. 'Type'
  167. ])
  168. items = 0
  169. client.channels.each_pair { |cid, channel|
  170. tbl << [ cid, channel.class.cls, channel.type ]
  171. items += 1
  172. }
  173. if (items == 0)
  174. print_line("No active channels.")
  175. else
  176. print("\n" + tbl.to_s + "\n")
  177. end
  178. when :close
  179. cmd_close(chan)
  180. when :interact
  181. cmd_interact(chan)
  182. when :read
  183. cmd_read(chan)
  184. when :write
  185. cmd_write(chan)
  186. else
  187. # No mode, no service.
  188. return true
  189. end
  190. end
  191. def cmd_channel_tabs(str, words)
  192. case words.length
  193. when 1
  194. @@channel_opts.fmt.keys
  195. when 2
  196. case words[1]
  197. when "-k", "-c", "-i", "-r", "-w"
  198. tab_complete_channels
  199. else
  200. []
  201. end
  202. else
  203. []
  204. end
  205. end
  206. def cmd_close_help
  207. print_line "Usage: close <channel_id>"
  208. print_line
  209. print_line "Closes the supplied channel."
  210. print_line
  211. end
  212. #
  213. # Closes a supplied channel.
  214. #
  215. def cmd_close(*args)
  216. if (args.length == 0)
  217. cmd_close_help
  218. return true
  219. end
  220. cid = args[0].to_i
  221. channel = client.find_channel(cid)
  222. if (!channel)
  223. print_error("Invalid channel identifier specified.")
  224. return true
  225. else
  226. channel._close # Issue #410
  227. print_status("Closed channel #{cid}.")
  228. end
  229. end
  230. def cmd_close_tabs(str, words)
  231. return [] if words.length > 1
  232. return tab_complete_channels
  233. end
  234. #
  235. # Terminates the meterpreter session.
  236. #
  237. def cmd_exit(*args)
  238. print_status("Shutting down Meterpreter...")
  239. client.core.shutdown rescue nil
  240. client.shutdown_passive_dispatcher
  241. shell.stop
  242. end
  243. alias cmd_quit cmd_exit
  244. def cmd_detach_help
  245. print_line "Detach from the victim. Only possible for non-stream sessions (http/https)"
  246. print_line
  247. print_line "The victim will continue to attempt to call back to the handler until it"
  248. print_line "successfully connects (which may happen immediately if you have a handler"
  249. print_line "running in the background), or reaches its expiration."
  250. print_line
  251. print_line "This session may #{client.passive_service ? "" : "NOT"} be detached."
  252. print_line
  253. end
  254. #
  255. # Disconnects the session
  256. #
  257. def cmd_detach(*args)
  258. client.shutdown_passive_dispatcher
  259. shell.stop
  260. end
  261. def cmd_interact_help
  262. print_line "Usage: interact <channel_id>"
  263. print_line
  264. print_line "Interacts with the supplied channel."
  265. print_line
  266. end
  267. #
  268. # Interacts with a channel.
  269. #
  270. def cmd_interact(*args)
  271. if (args.length == 0)
  272. cmd_info_help
  273. return true
  274. end
  275. cid = args[0].to_i
  276. channel = client.find_channel(cid)
  277. if (channel)
  278. print_line("Interacting with channel #{cid}...\n")
  279. shell.interact_with_channel(channel)
  280. else
  281. print_error("Invalid channel identifier specified.")
  282. end
  283. end
  284. alias cmd_interact_tabs cmd_close_tabs
  285. def cmd_irb_help
  286. print_line "Usage: irb"
  287. print_line
  288. print_line "Execute commands in a Ruby environment"
  289. print @@irb_opts.usage
  290. end
  291. #
  292. # Runs the IRB scripting shell
  293. #
  294. def cmd_irb(*args)
  295. expressions = []
  296. # Parse the command options
  297. @@irb_opts.parse(args) do |opt, idx, val|
  298. case opt
  299. when '-e'
  300. expressions << val
  301. when '-h'
  302. return cmd_irb_help
  303. end
  304. end
  305. session = client
  306. framework = client.framework
  307. if expressions.empty?
  308. print_status("Starting IRB shell")
  309. print_status("The 'client' variable holds the meterpreter client\n")
  310. Rex::Ui::Text::IrbShell.new(binding).run
  311. else
  312. expressions.each { |expression| eval(expression, binding) }
  313. end
  314. end
  315. @@set_timeouts_opts = Rex::Parser::Arguments.new(
  316. '-c' => [ true, 'Comms timeout (seconds)' ],
  317. '-x' => [ true, 'Expiration timout (seconds)' ],
  318. '-t' => [ true, 'Retry total time (seconds)' ],
  319. '-w' => [ true, 'Retry wait time (seconds)' ],
  320. '-h' => [ false, 'Help menu' ])
  321. def cmd_set_timeouts_help
  322. print_line('Usage: set_timeouts [options]')
  323. print_line
  324. print_line('Set the current timeout options.')
  325. print_line('Any or all of these can be set at once.')
  326. print_line(@@set_timeouts_opts.usage)
  327. end
  328. def cmd_set_timeouts(*args)
  329. if ( args.length == 0 or args.include?("-h") )
  330. cmd_set_timeouts_help
  331. return
  332. end
  333. opts = {}
  334. @@set_timeouts_opts.parse(args) do |opt, idx, val|
  335. case opt
  336. when '-c'
  337. opts[:comm_timeout] = val.to_i if val
  338. when '-x'
  339. opts[:session_exp] = val.to_i if val
  340. when '-t'
  341. opts[:retry_total] = val.to_i if val
  342. when '-w'
  343. opts[:retry_wait] = val.to_i if val
  344. end
  345. end
  346. if opts.keys.length == 0
  347. print_error("No options set")
  348. else
  349. timeouts = client.core.set_transport_timeouts(opts)
  350. print_timeouts(timeouts)
  351. end
  352. end
  353. def cmd_get_timeouts(*args)
  354. # Calling set without passing values is the same as
  355. # getting all the current timeouts
  356. timeouts = client.core.set_transport_timeouts
  357. print_timeouts(timeouts)
  358. end
  359. def print_timeouts(timeouts)
  360. if timeouts[:session_exp]
  361. print_line("Session Expiry : @ #{(Time.now + timeouts[:session_exp]).strftime('%Y-%m-%d %H:%M:%S')}")
  362. end
  363. if timeouts[:comm_timeout]
  364. print_line("Comm Timeout : #{timeouts[:comm_timeout]} seconds")
  365. end
  366. if timeouts[:retry_total]
  367. print_line("Retry Total Time: #{timeouts[:retry_total]} seconds")
  368. end
  369. if timeouts[:retry_wait]
  370. print_line("Retry Wait Time : #{timeouts[:retry_wait]} seconds")
  371. end
  372. end
  373. #
  374. # Get the machine ID of the target
  375. #
  376. def cmd_machine_id(*args)
  377. client.machine_id = client.core.machine_id unless client.machine_id
  378. print_good("Machine ID: #{client.machine_id}")
  379. end
  380. #
  381. # Get the machine ID of the target
  382. #
  383. def cmd_uuid(*args)
  384. client.payload_uuid = client.core.uuid unless client.payload_uuid
  385. print_good("UUID: #{client.payload_uuid}")
  386. end
  387. #
  388. # Arguments for ssl verification
  389. #
  390. @@ssl_verify_opts = Rex::Parser::Arguments.new(
  391. '-e' => [ false, 'Enable SSL certificate verification' ],
  392. '-d' => [ false, 'Disable SSL certificate verification' ],
  393. '-q' => [ false, 'Query the statis of SSL certificate verification' ],
  394. '-h' => [ false, 'Help menu' ])
  395. #
  396. # Help for ssl verification
  397. #
  398. def cmd_ssl_verify_help
  399. print_line('Usage: ssl_verify [options]')
  400. print_line
  401. print_line('Change and query the current setting for SSL verification')
  402. print_line('Only one of the following options can be used at a time')
  403. print_line(@@ssl_verify_opts.usage)
  404. end
  405. #
  406. # Handle the SSL verification querying and setting function.
  407. #
  408. def cmd_ssl_verify(*args)
  409. if ( args.length == 0 or args.include?("-h") )
  410. cmd_ssl_verify_help
  411. return
  412. end
  413. query = false
  414. enable = false
  415. disable = false
  416. settings = 0
  417. @@ssl_verify_opts.parse(args) do |opt, idx, val|
  418. case opt
  419. when '-q'
  420. query = true
  421. settings += 1
  422. when '-e'
  423. enable = true
  424. settings += 1
  425. when '-d'
  426. disable = true
  427. settings += 1
  428. end
  429. end
  430. # Make sure only one action has been chosen
  431. if settings != 1
  432. cmd_ssl_verify_help
  433. return
  434. end
  435. if query
  436. hash = client.core.get_ssl_hash_verify
  437. if hash
  438. print_good("SSL verification is enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
  439. else
  440. print_good("SSL verification is disabled.")
  441. end
  442. elsif enable
  443. hash = client.core.enable_ssl_hash_verify
  444. if hash
  445. print_good("SSL verification has been enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
  446. else
  447. print_error("Failed to enable SSL verification")
  448. end
  449. else
  450. if client.core.disable_ssl_hash_verify
  451. print_good('SSL verification has been disabled')
  452. else
  453. print_error("Failed to disable SSL verification")
  454. end
  455. end
  456. end
  457. #
  458. # Display help for the sleep.
  459. #
  460. def cmd_sleep_help
  461. print_line('Usage: sleep <time>')
  462. print_line
  463. print_line(' time: Number of seconds to wait (positive integer)')
  464. print_line
  465. print_line(' This command tells Meterpreter to go to sleep for the specified')
  466. print_line(' number of seconds. Sleeping will result in the transport being')
  467. print_line(' shut down and restarted after the designated timeout.')
  468. end
  469. #
  470. # Handle the sleep command.
  471. #
  472. def cmd_sleep(*args)
  473. if args.length == 0
  474. cmd_sleep_help
  475. return
  476. end
  477. seconds = args.shift.to_i
  478. if seconds <= 0
  479. cmd_sleep_help
  480. return
  481. end
  482. print_status("Telling the target instance to sleep for #{seconds} seconds ...")
  483. if client.core.transport_sleep(seconds)
  484. print_good("Target instance has gone to sleep, terminating current session.")
  485. client.shutdown_passive_dispatcher
  486. shell.stop
  487. else
  488. print_error("Target instance failed to go to sleep.")
  489. end
  490. end
  491. #
  492. # Arguments for transport switching
  493. #
  494. @@transport_opts = Rex::Parser::Arguments.new(
  495. '-t' => [ true, "Transport type: #{Rex::Post::Meterpreter::ClientCore::VALID_TRANSPORTS.keys.join(', ')}" ],
  496. '-l' => [ true, 'LHOST parameter (for reverse transports)' ],
  497. '-p' => [ true, 'LPORT parameter' ],
  498. '-i' => [ true, 'Specify transport by index (currently supported: remove)' ],
  499. '-u' => [ true, 'Custom URI for HTTP/S transports (used when removing transports)' ],
  500. '-lu' => [ true, 'Local URI for HTTP/S transports (used when adding/changing transports with a custom LURI)' ],
  501. '-ua' => [ true, 'User agent for HTTP/S transports (optional)' ],
  502. '-ph' => [ true, 'Proxy host for HTTP/S transports (optional)' ],
  503. '-pp' => [ true, 'Proxy port for HTTP/S transports (optional)' ],
  504. '-pu' => [ true, 'Proxy username for HTTP/S transports (optional)' ],
  505. '-ps' => [ true, 'Proxy password for HTTP/S transports (optional)' ],
  506. '-pt' => [ true, 'Proxy type for HTTP/S transports (optional: http, socks; default: http)' ],
  507. '-c' => [ true, 'SSL certificate path for https transport verification (optional)' ],
  508. '-to' => [ true, 'Comms timeout (seconds) (default: same as current session)' ],
  509. '-ex' => [ true, 'Expiration timout (seconds) (default: same as current session)' ],
  510. '-rt' => [ true, 'Retry total time (seconds) (default: same as current session)' ],
  511. '-rw' => [ true, 'Retry wait time (seconds) (default: same as current session)' ],
  512. '-v' => [ false, 'Show the verbose format of the transport list' ],
  513. '-h' => [ false, 'Help menu' ])
  514. #
  515. # Display help for transport management.
  516. #
  517. def cmd_transport_help
  518. print_line('Usage: transport <list|change|add|next|prev|remove> [options]')
  519. print_line
  520. print_line(' list: list the currently active transports.')
  521. print_line(' add: add a new transport to the transport list.')
  522. print_line(' change: same as add, but changes directly to the added entry.')
  523. print_line(' next: jump to the next transport in the list (no options).')
  524. print_line(' prev: jump to the previous transport in the list (no options).')
  525. print_line(' remove: remove an existing, non-active transport.')
  526. print_line(@@transport_opts.usage)
  527. end
  528. def update_transport_map
  529. result = client.core.transport_list
  530. @transport_map.clear
  531. sorted_by_url = result[:transports].sort_by { |k| k[:url] }
  532. sorted_by_url.each_with_index { |t, i| @transport_map[i+1] = t }
  533. end
  534. #
  535. # Manage transports
  536. #
  537. def cmd_transport(*args)
  538. if ( args.length == 0 or args.include?("-h") )
  539. cmd_transport_help
  540. return
  541. end
  542. command = args.shift
  543. unless ['list', 'add', 'change', 'prev', 'next', 'remove'].include?(command)
  544. cmd_transport_help
  545. return
  546. end
  547. opts = {
  548. :uuid => client.payload_uuid,
  549. :transport => nil,
  550. :lhost => nil,
  551. :lport => nil,
  552. :uri => nil,
  553. :ua => nil,
  554. :proxy_host => nil,
  555. :proxy_port => nil,
  556. :proxy_type => nil,
  557. :proxy_user => nil,
  558. :proxy_pass => nil,
  559. :comm_timeout => nil,
  560. :session_exp => nil,
  561. :retry_total => nil,
  562. :retry_wait => nil,
  563. :cert => nil,
  564. :verbose => false
  565. }
  566. valid = true
  567. transport_index = 0
  568. @@transport_opts.parse(args) do |opt, idx, val|
  569. case opt
  570. when '-c'
  571. opts[:cert] = val
  572. when '-u'
  573. opts[:uri] = val
  574. when '-i'
  575. transport_index = val.to_i
  576. when '-lu'
  577. opts[:luri] = val
  578. when '-ph'
  579. opts[:proxy_host] = val
  580. when '-pp'
  581. opts[:proxy_port] = val.to_i
  582. when '-pt'
  583. opts[:proxy_type] = val
  584. when '-pu'
  585. opts[:proxy_user] = val
  586. when '-ps'
  587. opts[:proxy_pass] = val
  588. when '-ua'
  589. opts[:ua] = val
  590. when '-to'
  591. opts[:comm_timeout] = val.to_i if val
  592. when '-ex'
  593. opts[:session_exp] = val.to_i if val
  594. when '-rt'
  595. opts[:retry_total] = val.to_i if val
  596. when '-rw'
  597. opts[:retry_wait] = val.to_i if val
  598. when '-p'
  599. opts[:lport] = val.to_i if val
  600. when '-l'
  601. opts[:lhost] = val
  602. when '-v'
  603. opts[:verbose] = true
  604. when '-t'
  605. unless client.core.valid_transport?(val)
  606. cmd_transport_help
  607. return
  608. end
  609. opts[:transport] = val
  610. else
  611. valid = false
  612. end
  613. end
  614. unless valid
  615. cmd_transport_help
  616. return
  617. end
  618. update_transport_map
  619. case command
  620. when 'list'
  621. result = client.core.transport_list
  622. current_transport_url = result[:transports].first[:url]
  623. sorted_by_url = result[:transports].sort_by { |k| k[:url] }
  624. # this will output the session timeout first
  625. print_timeouts(result)
  626. columns =[
  627. 'ID',
  628. 'Curr',
  629. 'URL',
  630. 'Comms T/O',
  631. 'Retry Total',
  632. 'Retry Wait'
  633. ]
  634. if opts[:verbose]
  635. columns << 'User Agent'
  636. columns << 'Proxy Host'
  637. columns << 'Proxy User'
  638. columns << 'Proxy Pass'
  639. columns << 'Cert Hash'
  640. end
  641. # next draw up a table of transport entries
  642. tbl = Rex::Text::Table.new(
  643. 'SortIndex' => 0, # sort by ID
  644. 'Indent' => 4,
  645. 'Columns' => columns)
  646. sorted_by_url.each_with_index do |t, i|
  647. entry = [ i+1, (current_transport_url == t[:url]) ? '*' : '', t[:url],
  648. t[:comm_timeout], t[:retry_total], t[:retry_wait] ]
  649. if opts[:verbose]
  650. entry << t[:ua]
  651. entry << t[:proxy_host]
  652. entry << t[:proxy_user]
  653. entry << t[:proxy_pass]
  654. entry << (t[:cert_hash] || '').unpack("H*")[0]
  655. end
  656. tbl << entry
  657. end
  658. print("\n" + tbl.to_s + "\n")
  659. when 'next'
  660. print_status("Changing to next transport ...")
  661. if client.core.transport_next
  662. print_good("Successfully changed to the next transport, killing current session.")
  663. client.shutdown_passive_dispatcher
  664. shell.stop
  665. else
  666. print_error("Failed to change transport, please check the parameters")
  667. end
  668. when 'prev'
  669. print_status("Changing to previous transport ...")
  670. if client.core.transport_prev
  671. print_good("Successfully changed to the previous transport, killing current session.")
  672. client.shutdown_passive_dispatcher
  673. shell.stop
  674. else
  675. print_error("Failed to change transport, please check the parameters")
  676. end
  677. when 'change'
  678. print_status("Changing to new transport ...")
  679. if client.core.transport_change(opts)
  680. print_good("Successfully added #{opts[:transport]} transport, killing current session.")
  681. client.shutdown_passive_dispatcher
  682. shell.stop
  683. else
  684. print_error("Failed to change transport, please check the parameters")
  685. end
  686. when 'add'
  687. print_status("Adding new transport ...")
  688. if client.core.transport_add(opts)
  689. print_good("Successfully added #{opts[:transport]} transport.")
  690. else
  691. print_error("Failed to add transport, please check the parameters")
  692. end
  693. when 'remove'
  694. if opts[:transport] && !opts[:transport].end_with?('_tcp') && opts[:uri].nil?
  695. print_error("HTTP/S transport specified without session URI")
  696. return
  697. end
  698. if !transport_index.zero? && @transport_map.has_key?(transport_index)
  699. # validate the URL
  700. url_to_delete = @transport_map[transport_index][:url]
  701. begin
  702. uri = URI.parse(url_to_delete)
  703. opts[:transport] = "reverse_#{uri.scheme}"
  704. opts[:lhost] = uri.host
  705. opts[:lport] = uri.port
  706. opts[:uri] = uri.path[1..-2] if uri.scheme.include?("http")
  707. rescue URI::InvalidURIError
  708. print_error("Failed to parse URL: #{url_to_delete}")
  709. return
  710. end
  711. end
  712. print_status("Removing transport ...")
  713. if client.core.transport_remove(opts)
  714. print_good("Successfully removed #{opts[:transport]} transport.")
  715. else
  716. print_error("Failed to remove transport, please check the parameters")
  717. end
  718. end
  719. end
  720. @@migrate_opts = Rex::Parser::Arguments.new(
  721. '-P' => [true, 'PID to migrate to.'],
  722. '-N' => [true, 'Process name to migrate to.'],
  723. '-p' => [true, 'Writable path - Linux only (eg. /tmp).'],
  724. '-t' => [true, 'The number of seconds to wait for migration to finish (default: 60).'],
  725. '-h' => [false, 'Help menu.']
  726. )
  727. def cmd_migrate_help
  728. if client.platform =~ /linux/
  729. print_line('Usage: migrate <<pid> | -P <pid> | -N <name>> [-p writable_path] [-t timeout]')
  730. else
  731. print_line('Usage: migrate <<pid> | -P <pid> | -N <name>> [-t timeout]')
  732. end
  733. print_line
  734. print_line('Migrates the server instance to another process.')
  735. print_line('NOTE: Any open channels or other dynamic state will be lost.')
  736. print_line
  737. end
  738. #
  739. # Migrates the server to the supplied process identifier.
  740. #
  741. # @param args [Array<String>] Commandline arguments, -h or a pid. On linux
  742. # platforms a path for the unix domain socket used for IPC.
  743. # @return [void]
  744. def cmd_migrate(*args)
  745. if args.length == 0 || args.any? { |arg| %w(-h --pid --name).include? arg }
  746. cmd_migrate_help
  747. return true
  748. end
  749. pid = nil
  750. writable_dir = nil
  751. opts = {
  752. timeout: nil
  753. }
  754. @@migrate_opts.parse(args) do |opt, idx, val|
  755. case opt
  756. when '-t'
  757. opts[:timeout] = val.to_i
  758. when '-p'
  759. writable_dir = val
  760. when '-P'
  761. unless val =~ /^\d+$/
  762. print_error("Not a PID: #{val}")
  763. return
  764. end
  765. pid = val.to_i
  766. when '-N'
  767. if val.to_s.empty?
  768. print_error("No process name provided")
  769. return
  770. end
  771. # this will migrate to the first process with a matching name
  772. unless (process = client.sys.process.processes.find { |p| p['name'] == val })
  773. print_error("Could not find process name #{val}")
  774. return
  775. end
  776. pid = process['pid']
  777. end
  778. end
  779. unless pid
  780. unless (pid = args.first)
  781. print_error('A process ID or name argument must be provided')
  782. return
  783. end
  784. unless pid =~ /^\d+$/
  785. print_error("Not a PID: #{pid}")
  786. return
  787. end
  788. pid = pid.to_i
  789. end
  790. begin
  791. server = client.sys.process.open
  792. rescue TimeoutError => e
  793. elog(e.to_s)
  794. rescue RequestError => e
  795. elog(e.to_s)
  796. end
  797. service = client.pfservice
  798. # If we have any open port forwards, we need to close them down
  799. # otherwise we'll end up with local listeners which aren't connected
  800. # to valid channels in the migrated meterpreter instance.
  801. existing_relays = []
  802. if service
  803. service.each_tcp_relay do |lhost, lport, rhost, rport, opts|
  804. next unless opts['MeterpreterRelay']
  805. if existing_relays.empty?
  806. print_status('Removing existing TCP relays...')
  807. end
  808. if (service.stop_tcp_relay(lport, lhost))
  809. print_status("Successfully stopped TCP relay on #{lhost || '0.0.0.0'}:#{lport}")
  810. existing_relays << {
  811. :lport => lport,
  812. :opts => opts
  813. }
  814. else
  815. print_error("Failed to stop TCP relay on #{lhost || '0.0.0.0'}:#{lport}")
  816. next
  817. end
  818. end
  819. unless existing_relays.empty?
  820. print_status("#{existing_relays.length} TCP relay(s) removed.")
  821. end
  822. end
  823. server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}")
  824. # Do this thang.
  825. client.core.migrate(pid, writable_dir, opts)
  826. print_status('Migration completed successfully.')
  827. # Update session info (we may have a new username)
  828. client.update_session_info
  829. unless existing_relays.empty?
  830. print_status('Recreating TCP relay(s)...')
  831. existing_relays.each do |r|
  832. client.pfservice.start_tcp_relay(r[:lport], r[:opts])
  833. print_status("Local TCP relay recreated: #{r[:opts]['LocalHost'] || '0.0.0.0'}:#{r[:lport]} <-> #{r[:opts]['PeerHost']}:#{r[:opts]['PeerPort']}")
  834. end
  835. end
  836. end
  837. def cmd_load_help
  838. print_line("Usage: load ext1 ext2 ext3 ...")
  839. print_line
  840. print_line "Loads a meterpreter extension module or modules."
  841. print_line @@load_opts.usage
  842. end
  843. #
  844. # Loads one or more meterpreter extensions.
  845. #
  846. def cmd_load(*args)
  847. if (args.length == 0)
  848. args.unshift("-h")
  849. end
  850. @@load_opts.parse(args) { |opt, idx, val|
  851. case opt
  852. when "-l"
  853. exts = SortedSet.new
  854. msf_path = MetasploitPayloads.msf_meterpreter_dir
  855. gem_path = MetasploitPayloads.local_meterpreter_dir
  856. [msf_path, gem_path].each do |path|
  857. ::Dir.entries(path).each { |f|
  858. if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
  859. exts.add($1)
  860. end
  861. }
  862. end
  863. print(exts.to_a.join("\n") + "\n")
  864. return true
  865. when "-h"
  866. cmd_load_help
  867. return true
  868. end
  869. }
  870. # Load each of the modules
  871. args.each { |m|
  872. md = m.downcase
  873. if (extensions.include?(md))
  874. print_error("The '#{md}' extension has already been loaded.")
  875. next
  876. end
  877. print("Loading extension #{md}...")
  878. begin
  879. # Use the remote side, then load the client-side
  880. if (client.core.use(md) == true)
  881. add_extension_client(md)
  882. end
  883. rescue
  884. print_line
  885. log_error("Failed to load extension: #{$!}")
  886. next
  887. end
  888. print_line("success.")
  889. }
  890. return true
  891. end
  892. def cmd_load_tabs(str, words)
  893. tabs = SortedSet.new
  894. msf_path = MetasploitPayloads.msf_meterpreter_dir
  895. gem_path = MetasploitPayloads.local_meterpreter_dir
  896. [msf_path, gem_path].each do |path|
  897. ::Dir.entries(path).each { |f|
  898. if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
  899. if (not extensions.include?($1))
  900. tabs.add($1)
  901. end
  902. end
  903. }
  904. end
  905. return tabs.to_a
  906. end
  907. def cmd_use(*args)
  908. #print_error("Warning: The 'use' command is deprecated in favor of 'load'")
  909. cmd_load(*args)
  910. end
  911. alias cmd_use_help cmd_load_help
  912. alias cmd_use_tabs cmd_load_tabs
  913. def cmd_read_help
  914. print_line "Usage: read <channel_id> [length]"
  915. print_line
  916. print_line "Reads data from the supplied channel."
  917. print_line
  918. end
  919. #
  920. # Reads data from a channel.
  921. #
  922. def cmd_read(*args)
  923. if (args.length == 0)
  924. cmd_read_help
  925. return true
  926. end
  927. cid = args[0].to_i
  928. length = (args.length >= 2) ? args[1].to_i : 16384
  929. channel = client.find_channel(cid)
  930. if (!channel)
  931. print_error("Channel #{cid} is not valid.")
  932. return true
  933. end
  934. data = channel.read(length)
  935. if (data and data.length)
  936. print("Read #{data.length} bytes from #{cid}:\n\n#{data}\n")
  937. else
  938. print_error("No data was returned.")
  939. end
  940. return true
  941. end
  942. alias cmd_read_tabs cmd_close_tabs
  943. def cmd_run_help
  944. print_line "Usage: run <script> [arguments]"
  945. print_line
  946. print_line "Executes a ruby script or Metasploit Post module in the context of the"
  947. print_line "meterpreter session. Post modules can take arguments in var=val format."
  948. print_line "Example: run post/foo/bar BAZ=abcd"
  949. print_line
  950. end
  951. #
  952. # Executes a script in the context of the meterpreter session.
  953. #
  954. def cmd_run(*args)
  955. if args.length == 0
  956. cmd_run_help
  957. return true
  958. end
  959. # Get the script name
  960. begin
  961. script_name = args.shift
  962. # First try it as a Post module if we have access to the Metasploit
  963. # Framework instance. If we don't, or if no such module exists,
  964. # fall back to using the scripting interface.
  965. if (msf_loaded? and mod = client.framework.modules.create(script_name))
  966. original_mod = mod
  967. reloaded_mod = client.framework.modules.reload_module(original_mod)
  968. unless reloaded_mod
  969. error = client.framework.modules.module_load_error_by_path[original_mod.file_path]
  970. print_error("Failed to reload module: #{error}")
  971. return
  972. end
  973. opts = (args + [ "SESSION=#{client.sid}" ]).join(',')
  974. reloaded_mod.run_simple(
  975. #'RunAsJob' => true,
  976. 'LocalInput' => shell.input,
  977. 'LocalOutput' => shell.output,
  978. 'OptionStr' => opts
  979. )
  980. else
  981. # the rest of the arguments get passed in through the binding
  982. client.execute_script(script_name, args)
  983. end
  984. rescue
  985. print_error("Error in script: #{$!.class} #{$!}")
  986. elog("Error in script: #{$!.class} #{$!}")
  987. dlog("Callstack: #{$@.join("\n")}")
  988. end
  989. end
  990. def cmd_run_tabs(str, words)
  991. tabs = []
  992. if(not words[1] or not words[1].match(/^\//))
  993. begin
  994. if (msf_loaded?)
  995. tabs += tab_complete_postmods
  996. end
  997. [
  998. ::Msf::Sessions::Meterpreter.script_base,
  999. ::Msf::Sessions::Meterpreter.user_script_base
  1000. ].each do |dir|
  1001. next if not ::File.exist? dir
  1002. tabs += ::Dir.new(dir).find_all { |e|
  1003. path = dir + ::File::SEPARATOR + e
  1004. ::File.file?(path) and ::File.readable?(path)
  1005. }
  1006. end
  1007. rescue Exception
  1008. end
  1009. end
  1010. return tabs.map { |e| e.sub(/\.rb$/, '') }
  1011. end
  1012. #
  1013. # Executes a script in the context of the meterpreter session in the background
  1014. #
  1015. def cmd_bgrun(*args)
  1016. if args.length == 0
  1017. print_line(
  1018. "Usage: bgrun <script> [arguments]\n\n" +
  1019. "Executes a ruby script in the context of the meterpreter session.")
  1020. return true
  1021. end
  1022. jid = self.bgjob_id
  1023. self.bgjob_id += 1
  1024. # Get the script name
  1025. self.bgjobs[jid] = Rex::ThreadFactory.spawn("MeterpreterBGRun(#{args[0]})-#{jid}", false, jid, args) do |myjid,xargs|
  1026. ::Thread.current[:args] = xargs.dup
  1027. begin
  1028. # the rest of the arguments get passed in through the binding
  1029. client.execute_script(args.shift, args)
  1030. rescue ::Exception
  1031. print_error("Error in script: #{$!.class} #{$!}")
  1032. elog("Error in script: #{$!.class} #{$!}")
  1033. dlog("Callstack: #{$@.join("\n")}")
  1034. end
  1035. self.bgjobs[myjid] = nil
  1036. print_status("Background script with Job ID #{myjid} has completed (#{::Thread.current[:args].inspect})")
  1037. end
  1038. print_status("Executed Meterpreter with Job ID #{jid}")
  1039. end
  1040. #
  1041. # Map this to the normal run command tab completion
  1042. #
  1043. def cmd_bgrun_tabs(*args)
  1044. cmd_run_tabs(*args)
  1045. end
  1046. #
  1047. # Kill a background job
  1048. #
  1049. def cmd_bgkill(*args)
  1050. if args.length == 0
  1051. print_line("Usage: bgkill [id]")
  1052. return
  1053. end
  1054. args.each do |jid|
  1055. jid = jid.to_i
  1056. if self.bgjobs[jid]
  1057. print_status("Killing background job #{jid}...")
  1058. self.bgjobs[jid].kill
  1059. self.bgjobs[jid] = nil
  1060. else
  1061. print_error("Job #{jid} was not running")
  1062. end
  1063. end
  1064. end
  1065. #
  1066. # List background jobs
  1067. #
  1068. def cmd_bglist(*args)
  1069. self.bgjobs.each_index do |jid|
  1070. if self.bgjobs[jid]
  1071. print_status("Job #{jid}: #{self.bgjobs[jid][:args].inspect}")
  1072. end
  1073. end
  1074. end
  1075. def cmd_info_help
  1076. print_line 'Usage: info <module>'
  1077. print_line
  1078. print_line 'Prints information about a post-exploitation module'
  1079. print_line
  1080. end
  1081. #
  1082. # Show info for a given Post module.
  1083. #
  1084. # See also +cmd_info+ in lib/msf/ui/console/command_dispatcher/core.rb
  1085. #
  1086. def cmd_info(*args)
  1087. return unless msf_loaded?
  1088. if args.length != 1 or args.include?("-h")
  1089. cmd_info_help
  1090. return
  1091. end
  1092. module_name = args.shift
  1093. mod = client.framework.modules.create(module_name);
  1094. if mod.nil?
  1095. print_error 'Invalid module: ' << module_name
  1096. end
  1097. if (mod)
  1098. print_line(::Msf::Serializer::ReadableText.dump_module(mod))
  1099. mod_opt = ::Msf::Serializer::ReadableText.dump_options(mod, ' ')
  1100. print_line("\nModule options (#{mod.fullname}):\n\n#{mod_opt}") if (mod_opt and mod_opt.length > 0)
  1101. end
  1102. end
  1103. def cmd_info_tabs(*args)
  1104. return unless msf_loaded?
  1105. tab_complete_postmods
  1106. end
  1107. #
  1108. # Writes data to a channel.
  1109. #
  1110. @@write_opts = Rex::Parser::Arguments.new(
  1111. "-f" => [ true, "Write the contents of a file on disk" ],
  1112. "-h" => [ false, "Help menu." ])
  1113. def cmd_write_help
  1114. print_line "Usage: write [options] channel_id"
  1115. print_line
  1116. print_line "Writes data to the supplied channel."
  1117. print_line @@write_opts.usage
  1118. end
  1119. def cmd_write(*args)
  1120. if (args.length == 0 or args.include?("-h"))
  1121. cmd_write_help
  1122. return
  1123. end
  1124. src_file = nil
  1125. cid = nil
  1126. @@write_opts.parse(args) { |opt, idx, val|
  1127. case opt
  1128. when "-f"
  1129. src_file = val
  1130. else
  1131. cid = val.to_i
  1132. end
  1133. }
  1134. # Find the channel associated with this cid, assuming the cid is valid.
  1135. if ((!cid) or (!(channel = client.find_channel(cid))))
  1136. print_error("Invalid channel identifier specified.")
  1137. return true
  1138. end
  1139. # If they supplied a source file, read in its contents and write it to
  1140. # the channel
  1141. if (src_file)
  1142. begin
  1143. data = ''
  1144. ::File.open(src_file, 'rb') { |f|
  1145. data = f.read(f.stat.size)
  1146. }
  1147. rescue Errno::ENOENT
  1148. print_error("Invalid source file specified: #{src_file}")
  1149. return true
  1150. end
  1151. if (data and data.length > 0)
  1152. channel.write(data)
  1153. print_status("Wrote #{data.length} bytes to channel #{cid}.")
  1154. else
  1155. print_error("No data to send from file #{src_file}")
  1156. return true
  1157. end
  1158. # Otherwise, read from the input descriptor until we're good to go.
  1159. else
  1160. print("Enter data followed by a '.' on an empty line:\n\n")
  1161. data = ''
  1162. # Keep truckin'
  1163. while (s = shell.input.gets)
  1164. break if (s =~ /^\.\r?\n?$/)
  1165. data += s
  1166. end
  1167. if (!data or data.length == 0)
  1168. print_error("No data to send.")
  1169. else
  1170. channel.write(data)
  1171. print_status("Wrote #{data.length} bytes to channel #{cid}.")
  1172. end
  1173. end
  1174. return true
  1175. end
  1176. def cmd_resource_help
  1177. print_line "Usage: resource <path1> [path2 ...]"
  1178. print_line
  1179. print_line "Run the commands stored in the supplied files."
  1180. print_line
  1181. end
  1182. def cmd_resource(*args)
  1183. if args.empty?
  1184. return false
  1185. end
  1186. args.each do |glob|
  1187. files = ::Dir.glob(::File.expand_path(glob))
  1188. if files.empty?
  1189. print_error("No such file #{glob}")
  1190. next
  1191. end
  1192. files.each do |filename|
  1193. print_status("Reading #{filename}")
  1194. if (not ::File.readable?(filename))
  1195. print_error("Could not read file #{filename}")
  1196. next
  1197. else
  1198. ::File.open(filename, "r").each_line do |line|
  1199. next if line.strip.length < 1
  1200. next if line[0,1] == "#"
  1201. begin
  1202. print_status("Running #{line}")
  1203. client.console.run_single(line)
  1204. rescue ::Exception => e
  1205. print_error("Error Running Command #{line}: #{e.class} #{e}")
  1206. end
  1207. end
  1208. end
  1209. end
  1210. end
  1211. end
  1212. def cmd_resource_tabs(str, words)
  1213. return [] if words.length > 1
  1214. tab_complete_filenames(str, words)
  1215. end
  1216. def cmd_enable_unicode_encoding
  1217. client.encode_unicode = true
  1218. print_status("Unicode encoding is enabled")
  1219. end
  1220. def cmd_disable_unicode_encoding
  1221. client.encode_unicode = false
  1222. print_status("Unicode encoding is disabled")
  1223. end
  1224. @@client_extension_search_paths = [ ::File.join(Rex::Root, "post", "meterpreter", "ui", "console", "command_dispatcher") ]
  1225. def self.add_client_extension_search_path(path)
  1226. @@client_extension_search_paths << path unless @@client_extension_search_paths.include?(path)
  1227. end
  1228. def self.client_extension_search_paths
  1229. @@client_extension_search_paths
  1230. end
  1231. protected
  1232. attr_accessor :extensions # :nodoc:
  1233. attr_accessor :bgjobs, :bgjob_id # :nodoc:
  1234. CommDispatcher = Console::CommandDispatcher
  1235. #
  1236. # Loads the client extension specified in mod
  1237. #
  1238. def add_extension_client(mod)
  1239. loaded = false
  1240. klass = nil
  1241. self.class.client_extension_search_paths.each do |path|
  1242. path = ::File.join(path, "#{mod}.rb")
  1243. klass = CommDispatcher.check_hash(path)
  1244. if (klass == nil)
  1245. old = CommDispatcher.constants
  1246. next unless ::File.exist? path
  1247. if (require(path))
  1248. new = CommDispatcher.constants
  1249. diff = new - old
  1250. next if (diff.empty?)
  1251. klass = CommDispatcher.const_get(diff[0])
  1252. CommDispatcher.set_hash(path, klass)
  1253. loaded = true
  1254. break
  1255. else
  1256. print_error("Failed to load client script file: #{path}")
  1257. return false
  1258. end
  1259. else
  1260. # the klass is already loaded, from a previous invocation
  1261. loaded = true
  1262. break
  1263. end
  1264. end
  1265. unless loaded
  1266. print_error("Failed to load client portion of #{mod}.")
  1267. return false
  1268. end
  1269. # Enstack the dispatcher
  1270. self.shell.enstack_dispatcher(klass)
  1271. # Insert the module into the list of extensions
  1272. self.extensions << mod
  1273. end
  1274. def tab_complete_postmods
  1275. tabs = client.framework.modules.post.map { |name,klass|
  1276. mod = client.framework.modules.post.create(name)
  1277. if mod and mod.session_compatible?(client)
  1278. mod.fullname.dup
  1279. else
  1280. nil
  1281. end
  1282. }
  1283. # nils confuse readline
  1284. tabs.compact
  1285. end
  1286. def tab_complete_channels
  1287. client.channels.keys.map { |k| k.to_s }
  1288. end
  1289. end
  1290. end
  1291. end
  1292. end
  1293. end